Timber + WooCommerce is our series of integrating WooCommerce with Timber Library.
Ch.1 – Shop and Single page
Ch.2 – Cart Dropdown
Ch.3 – Login Page (Coming Soon)
When integrating WooCommerce, it is best to use built-in functions and actions.
The main reason is to keep compatibility with other plugins. Also, it’s tough and confusing to customize.
With that in mind, let’s dive into how to integrate it with Timber:
Note: WooCommerce version used in this tutorial is 3.9.0
1. Add Theme Support
add_action( 'after_setup_theme', 'my_wc_theme_supports' );
function my_wc_theme_supports() {
add_theme_support( 'woocommerce', [
'product_grid' => [ 'default_columns' => 4 ],
'single_image_width' => 480,
] );
add_theme_support( 'wc-product-gallery-zoom' );
add_theme_support( 'wc-product-gallery-lightbox' );
add_theme_support( 'wc-product-gallery-slider' );
}
/**
* Assign global $product object in Timber
*/
function timber_set_product( $post ) {
global $product;
$product = isset( $post->product ) ? $post->product : wc_get_product( $post->ID );
}
We will use the timber_set_product()
function later.
2. Create an Entry Point
All WooCommerce pages will go through a file named woocommerce.php
. This is where you put your Timber codes.
<?php
$context = Timber::get_context();
// if SINGLE PRODUCT
if( is_singular( 'product' ) ) {
$context['product'] = Timber::get_post();
Timber::render( 'shop-single.twig', $context );
}
// if SHOP or CATEGORY page
else {
// if CATEGORY page
if( is_product_category() || is_product_tag() ) {
$context['term'] = get_queried_object();
}
$context['products'] = Timber::get_posts();
Timber::render( 'shop.twig', $context );
}
3. Create the Views
The TWIG snippet below does not include the extend
and block
part. You need to adapt it to your naming.
Below is for the Shop and Category page:
<header class="shop-header">
{% if term %}
<h1>{{ term.name }}</h1>
{{ term.description | wpautop }}
{% endif %}
{% do action("woocommerce_before_main_content") %}
</header>
<div class="shop-wrapper">
{% do action("woocommerce_before_shop_loop") %}
{% include "_shop-products.twig" %}
{% do action("woocommerce_after_shop_loop") %}
</div>
{% do action("woocommerce_after_main_content") %}
Below is for the Product List partial that we called in [Line 12] above:
<div class="shop-products">
{% for p in products %}
{{ fn("timber_set_product", p) }}
<div class="product-tease">
<a href="{{ p.link }}">
<figure>
{% do action( 'woocommerce_before_shop_loop_item_title' ) %}
</figure>
<h3> {{ p.title }} </h3>
</a>
{% do action("woocommerce_after_shop_loop_item_title") %}
{% do action("woocommerce_after_shop_loop_item") %}
</div>
{% endfor %}
</div>
[Line 3] We call the function we created in Step 1. This is to set the global context so the action will show the correct information.
Lastly, we need the view for Single Product page:
{{ fn('the_post') }}
<div class="product-wrapper">
{% do action("woocommerce_before_single_product") %}
<figure class="product-photo">
{% do action("woocommerce_before_single_product_summary") %}
</figure>
<article class="product-summary">
{% do action("woocommerce_single_product_summary") %}
</article>
{% do action("woocommerce_after_single_product_summary") %}
{% do action("woocommerce_after_single_product") %}
</div>
Done! For other pages like Cart, Checkout, and My Account page, they will go through the standard page.php
file. I prefer leaving them untouched.
Conclusion
This tutorial is a simplified version of the official integration guide. Check it out to learn more.
You might ask how do you know about all the action names? Simply open the WooCommerce plugin and check out the codes in /templates
folder.
In Part 2, we will learn about creating Cart Popup and Sign In links.
Let us know in the comment below if you have trouble with this integration 🙂
Hi Henner,
Thanks for the informative article! Really looking forward to your next articles on Timber + WooCommerce integration. Was looking for a good tutorial about this since 2016.
Hi Atelier!
Good news, I've just published Part 2 at https://wptips.dev/timber-woocommerce-2/
It's covering the topic about Cart Dropdown.
Let me know what you think in the comment section over that post 🙂
Great stuff! Do you have a boilerplate wp theme for this? Thanks in advance!
Hi Colin,
Thanks!
I have a theme boilerplate at https://github.com/hrsetyono/edje-wp-theme. But I haven't updated the WooCommerce part for long (It's been a while since my last WooCommerce project XD)
It uses the same approach as this tutorial but I was experimenting with removing all actions and use each functions explicitly. It ended up being not a good idea because it breaks plugin compatibility.
Hi and nice article. I am currently trying to integrate a custom checkout page. What I don't find true is this statement by you: "All WooCommerce pages will go through a file named woocommerce.php." When I echo something for product-category, or a single product inside woocommerce.php it works. But it doesn't work for /checkout. This page doesn't get handled by woocommerce.php. Do you have any suggestions?
Hi Simon,
Yes sorry for the mistake. Checkout and Cart page is handled by page.php. If you need to customize Checkout, I recommend to use the built-in Action or Filter instead. It's too complicated to do with Timber and may cause incompatibility with plugins.
You can see the list of actions by opening the Woocommerce plugin and open
/templates
folder.You can also overwrite checkout the same way as it is always done. Create a file in this directory:
yourtheme/woocommerce/checkout/form-checkout.php
As mentioned by you, you shouldn't use twig for that. Just copy the existing file from woocommerce and work in php. This solution is not really satisfying but it works.