Markus Michalski FAQ

Facebook Pixel: Storefront Integration

Facebook Pixel plugin for Sylius: Twig hooks per event, event deduplication, Klaro consent gating, AddToCart timing and price values.

Deutsche Version

Back to overview

Facebook Pixel: Storefront Integration

Live Demo: Try this and other plugins live — no installation, no risk: demo.markus-michalski.net

Twig hooks

Every event is rendered through a Twig hook, never through an overridden core template:

Hook Template Event
sylius_shop.base#javascripts bootstrap.html.twig The fbq() bootstrap script including PageView, once per page.
sylius_shop.product.show.content view_content.html.twig ViewContent on the product detail page.
sylius_shop.product.index.content.body.main.header view_category.html.twig ViewCategory on a category listing page (custom event).
sylius_shop.cart.index.content add_to_cart.html.twig The AddToCart script queued by the real add action (see below).
sylius_shop.checkout.address.content initiate_checkout.html.twig InitiateCheckout on the first checkout step.
sylius_shop.order.thank_you.content purchase.html.twig Purchase on the order confirmation page.

A theme that overrides one of these hook points still shows the pixel script as long as it keeps rendering the hook in its own template version. That is the usual Sylius Twig Hooks contract.

The templates call the Twig functions mmd_facebook_pixel_bootstrap, mmd_facebook_pixel_view_content, mmd_facebook_pixel_view_category, mmd_facebook_pixel_initiate_checkout, mmd_facebook_pixel_purchase and mmd_facebook_pixel_pending_add_to_cart. Each returns nothing if the channel has no valid configuration or the event is switched off.

Event data sent

Event Content (custom_data)
PageView none
ViewContent content_ids (variant code of the first enabled variant), content_name, content_type (product), currency, value (the channel's variant price; omitted if the channel has no price for it)
ViewCategory content_name, content_category (taxon path, for example Clothing > Shirts)
AddToCart content_ids, content_name, content_type, value, currency, num_items (the line that was just added)
InitiateCheckout, Purchase content_ids (variant codes), content_type, value, currency, num_items, order_id (order number)

The browser call always carries {eventID: '...'} as its last argument. The scripts are encoded XSS-safe.

Event deduplication

Every event shares exactly one event_id between the fbq() call in the browser and the matching server-side CAPI message, if one is sent. This is the mechanism by which Meta merges the two copies into one event. The ID is generated once per call and reused for both halves.

AddToCart timing

Unlike a check on every load of the cart page, AddToCart reacts to Sylius's own sylius.cart_item_post_add event, i.e. the real add action, exactly once per add. The server-side copy is created right there.

Because the add action does not render a full page, the browser script cannot be emitted from there: event_id and product data are queued in the session (flash bag) and emitted on the next full page render through the sylius_shop.cart.index.content hook, typically on the cart page itself. One script is emitted per add action; the queued entry is consumed in the process.

Check the flow once in a real browser before going live: click "Add to cart" and verify in the Network tab or with the Meta Pixel Helper extension that AddToCart appears with an eventID.

This section only concerns the browser pixel. Consent for the server-side CAPI is a separate, stricter setting. See Configuration and Extending.

With Release the tracking scripts through Klaro consent ticked and mmd/sylius-klaro-consent-plugin installed, every pixel script is emitted following Klaro's convention:

<script type="text/plain" data-type="application/javascript" data-name="facebook_pixel">

The browser then only executes it once Klaro has granted consent for the facebook_pixel service. Saving the channel settings with the box ticked creates this service in the Klaro catalog if it does not exist yet (purpose marketing, cookies _fbp, _fbc and fr, title and description in German and English). An existing entry, including one edited by hand, is never overwritten.

Effective gating is the box AND an installed Klaro. The box is disabled in the admin while Klaro is missing. Without Klaro (or with the box unticked), the scripts are emitted as normal, executable <script> tags. A shop with another consent tool must then block the pixel script itself.

Price values

The value of ViewContent is the channel's configured price of the product variant, taken as is. The plugin does not convert tax there, so Track gross prices has no effect on ViewContent. For AddToCart, InitiateCheckout and Purchase, the values come from the line or order totals; here the setting chooses between the total with tax and the total without tax (order total minus tax amount).

For ViewContent the currency is the channel's base currency; for AddToCart, InitiateCheckout and Purchase it is the currency of the cart or order.