WP Manifestindependent plugin directory
manifest / analytics / metatrac

MetaTrac self-updates

MetaTrac: WooCommerce -> Meta Pixel + Conversions API tracking plugin

by LifeX Marketing · github.com/lifexmarketing/metatrac · website

1stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/lifexmarketing/metatrac/archive/refs/heads/main.zip

Ships its own WordPress updater (Plugin Update Checker), so new versions show up under Dashboard → Updates.

A WordPress/WooCommerce plugin that tracks core ecommerce and lead-gen events and sends them to Meta through both the browser Pixel and the server-side Conversions API (CAPI), so tracking survives ad blockers and iOS ATT opt-outs. Built as a successor to the internal zooraz (Cloudflare Zaraz) plugin, but talks to Meta directly instead of going through a dataLayer/Zaraz intermediary.

Installed on multiple client sites and updated centrally from this repo via the bundled Plugin Update Checker.

Requirements

  • A Meta Pixel ID and a Conversions API access token (Events Manager > Data Sources > your Pixel > Settings > Conversions API > Generate access token).
  • WooCommerce active, only if you want the ecommerce events (ViewContent, AddToCart, InitiateCheckout, Purchase); PageView, Contact, FindLocation, and Lead all work without it. On the settings screen, the ecommerce checkboxes are grayed out while WooCommerce is inactive.
  • Gravity Forms active, only if you want the Lead event; MetaTrac still works fully without it, Lead just never fires.

Setup on a site

  1. Install the plugin (see "Installing / updating" below).
  2. Go to Settings > MetaTrac (requires the manage_options capability).
  3. Enter the Meta Pixel ID and Conversions API Access Token.
  4. Check which events to track: ViewContent, AddToCart, InitiateCheckout, Purchase, Contact, FindLocation, Lead.
  5. Optionally, under Page Events, assign any of Meta's standard events to any published page, to fire that event on every load of that page; see "Page Events" below.
  6. Optionally turn on Debug Mode while verifying a new install (see "Debug mode" below), and turn it back off once confirmed.
  7. Optionally paste a Test Event Code from Events Manager > Test Events while verifying CAPI delivery, then remove it.

How events are tracked

Every event fires twice, sharing the same event_id so Meta deduplicates the browser and server copies:

  • Browser (Pixel): fbq('track', ...), queued during page render and flushed in the footer (or, for ajax add-to-cart, pushed via a WooCommerce fragment, see below).
  • Server (CAPI): a wp_remote_post() to graph.facebook.com, including fbp/fbc cookies, client IP/user agent, and, when available, a hashed email/phone for match quality.

Page-cache safety: ViewContent, InitiateCheckout, and Page Events are queued via Metatrac_Pixel::queue_deferred_event() rather than fire_event(), since they fire from an ordinary page render that a caching plugin might serve unchanged to many different visitors. fire_event() mints the event_id and sends the CAPI call at render time, which is only safe when that specific render is guaranteed to run fresh per visitor (an ajax response, or a page with a naturally unique URL like an order-received page): baking a real event_id into cached HTML would mean every visitor served from that cache entry fires a Pixel event Meta dedupes away against the single CAPI call sent when the cache was generated, undercounting real traffic for as long as the page stays cached. Deferred events instead mint their event_id in the browser on every real page load (metatracFireEvent() in assets/js/metatrac-frontend.js) and report it to a dedicated admin-ajax.php endpoint (metatrac_deferred_event) so the CAPI call runs fresh every time too, the same approach Contact and FindLocation already use below, just applied to page-load events instead of click events. AddToCart and Purchase still use fire_event() directly: the ajax add-to-cart response is never page-cached, and an order-received URL is unique per order.

Every one of these admin-ajax.php endpoints (metatrac_deferred_event, metatrac_contact, and metatrac_find_location) is itself gated by a WP nonce that's baked into the same cached page render as the event it's authorizing. A plain wp_create_nonce() is normally only valid for ~12-24 hours, which a page cache can easily outlive (some of the cache entries that first surfaced the event_id bug above were 43-51 hours old), so each of the three trackers extends its own nonce's lifetime to a week via the nonce_life filter (extend_nonce_life() in Metatrac_Contact_Tracker/Metatrac_Find_Location_Tracker/Metatrac_Pixel). That comfortably covers realistic cache TTLs without leaving the nonce valid indefinitely.

Known limitation: a cache entry that somehow outlives a week without being regenerated or purged would still cause that specific event's CAPI call to silently fail its nonce check (the Pixel call is unaffected, since it doesn't depend on the nonce). Turning on Debug Mode surfaces this as a nonce_check_failed line in the debug log; previously it failed with no trace at all.

Event Fires on
ViewContent Single product page view
AddToCart woocommerce_add_to_cart (ajax or classic form submit)
InitiateCheckout Checkout page load, if the cart isn't empty; deduped per cart contents so refreshing/revisiting an unchanged cart doesn't refire it
Purchase Order-received ("thank you") page, once per order
Contact First click/tap on a tel:/sms: link and/or a mailto: link anywhere on the site (independently toggled), once per browser session
FindLocation First click/tap on a link to Google Maps anywhere on the site (a "Get Directions" link, an embedded map's "View larger map" link, a goo.gl/maps/maps.app.goo.gl short link, etc.), once per browser session
Lead A Gravity Forms submission (gform_after_submission), for the forms selected in Lead's settings (all active forms by default)

AddToCart and ajax carts

WooCommerce's default ajax add-to-cart doesn't reload the page, so there's no page for the browser Pixel call to run on. MetaTrac handles this the way GTM/analytics plugins typically do: it injects a `