Server-side tracking for your WooCommerce store — without a GTM Server Container, without a premium plugin, without a monthly bill.
This plugin sends Meta (Facebook) and Pinterest Conversions API events from your WordPress server, and sets up a clean GTM dataLayer so your browser-side tags (Pixel, GA4, Pinterest Tag) work alongside it. Same event ID on both sides, so Meta merges them into one event instead of double-counting.
What it does:
What you don’t need:
Please check the installation page for the recommended GTM settings for deduplication.
When a visitor clicks “Deny” on your cookie banner, most tracking plugins simply shut down. You lose the conversion data, your ads fly blind, and your ROAS artificially drops. Other “aggressive” plugins ignore the banner and send personal data (PII) to Meta anyway, risking massive GDPR fines.
We do something smarter.
When combined with Google Consent Mode v2, this plugin uses an advanced technique called Server-Side Consent Gating with Event ID Deduplication:
event_id to both. Meta’s machine learning connects the anonymous browser ping with your server’s exact order value.The result. Meta and Google’s modeling algorithms can now accurately model your “lost” conversions. You recover up to 50% of your missing ROAS data, feed your ad optimization with real purchase values, and remain 100% GDPR compliant.
Most other free plugins fall into one of two camps: the “timid” approach (shuts CAPI off entirely when consent is denied — your ads go blind), or the “reckless” approach (sends hashed PII to Meta regardless of consent — direct GDPR violation). This plugin is the only free option we know of that does the harder, correct thing: keep the signal flowing without sending the data the visitor refused. Enable it from Settings Privacy & Consent (Server-side) Strict server-side consent mode.
This plugin is free. Not “free with limits” — just free. Every feature works, no pro version behind a paywall.
I built it because setting up server-side tracking shouldn’t require a cloud engineering degree or a monthly bill. If it helps your store, that’s good enough.
This plugin connects your website to external services to send event data.
Setup details for Consent Mode v2, the strict server-side consent mode (GDPR PII gating), CMP auto-block compatibility, and the WooCommerce Subscriptions integration. None of these are required for a basic CAPI setup — turn them on as your store needs them.
If you serve EU visitors, GA4 and Meta browser tags will not fire when a visitor refuses or has not yet acted on the cookie banner. The GTM tags wait for a gtag('consent', 'update', ...) signal that grants the relevant categories. Without Google Consent Mode v2 wired up, this typically costs a store 20–50% of its measured event volume in GA4 and Meta Events Manager. The data does not become “untrackable” — Google models it back, but only if you tell GTM that consent management is in play.
How Consent Mode v2 actually recovers the lost data
When a visitor denies consent, GA4 and Google Ads tags do not stop firing — they switch to cookieless pings: small anonymous beacons that carry no client identifier (no _ga, no _fbp, no IP retention) but include enough conversion context (event name, value, currency, timestamp) for Google’s machine learning to perform conversion modeling. Modeled conversions appear in your standard reports, mixed with directly-observed ones, with a “modeled” footnote. Google publicly reports that Consent Mode users recover, on average, 20–50% of the conversions they would otherwise have lost to consent denial. The Meta Pixel GTM template reads the same ad_storage / ad_user_data / ad_personalization signals that Consent Mode v2 sets — so a single CMP integration repairs both GA4 and Meta attribution at once. Server-side CAPI continues to operate independently.
This plugin’s job is to push events to the dataLayer regardless of consent state. The CMP’s job is to tell GTM which categories the visitor allowed. GTM does the actual gating and signals back to the vendors.
Step 1: Enable Consent Mode v2 in your CMP
Most popular CMP plugins have native Consent Mode v2 support. Find the toggle in your CMP plugin’s settings:
Once enabled, your CMP will automatically call gtag('consent', 'default', {...denied}) before GTM loads, then gtag('consent', 'update', {...granted}) after the visitor accepts.
Step 2: (Optional) Enable the Consent Defaults tag in GTM
If you imported the GTM container template, it includes a paused Custom HTML tag named “Consent Defaults (Pre-CMP) — Disabled, see readme”. Enable this tag only if your CMP does not call gtag('consent', 'default', ...) on its own (rare with modern CMPs):
CE - PageView Meta to the built-in “Consent Initialization – All Pages” trigger (visible in the trigger picker dropdown — guarantees this fires before any other tag).The tag sets all four consent types (ad_storage, ad_user_data, ad_personalization, analytics_storage) to denied with a 500 ms wait_for_update window. Your CMP’s gtag('consent', 'update', ...) call then grants the categories the visitor approved.
Step 3: Verify it is working
Consent Initialization (top of timeline). Confirm default consent values appear for all four categories. After accepting in your CMP, click Consent events lower in the timeline; you should see update calls flipping the relevant categories to granted.g/collect (GA4) or tr (Meta Pixel). Each request should include a gcs= query parameter. gcs=G100 means denied, G111 means granted, G101 means analytics-only. If you see gcs= you have Consent Mode active. If you do not, the CMP wiring is incomplete.Consent Mode v2 controls the browser tags. The plugin’s server-side CAPI calls do not see gtag('consent', ...) signals — they fire from PHP, hash the visitor’s email/phone/address, and POST directly to graph.facebook.com. By default this happens regardless of cookie-banner choice, which is fine for non-EU stores but a GDPR concern for European traffic.
The Privacy & Consent (Server-side) section in the plugin settings adds a “Strict server-side consent mode” checkbox (default OFF). When enabled, the plugin reads your CMP’s cookie before queuing each event:
CookieConsent cookie, looks for marketing:true|falsecookieyes-consent cookie, looks for advertisement:yes|nocmplz_marketing cookie, value allow / denymcapi_marketing_consent_granted filter (return true / false / null)If marketing consent is explicitly denied, identifying PII fields (em, ph, fn, ln, ct, st, zp, country, external_id, fbp, fbc, Pinterest click ID) are stripped from the CAPI payload. The event still ships — IP, user-agent, event_id, value, currency, content_ids, contents are retained — so Meta still receives a deduplicated server signal it can fold into conversion modeling, but the data is no longer personally identifying. If the cookie state is unknown (no recognized CMP) or consent is granted, behavior is unchanged.
How this complements Consent Mode v2. When a visitor denies marketing consent, your browser-side GA4 / Meta Pixel switches to cookieless pings — small anonymous beacons that Google’s ML uses to model the conversions you would have measured. That recovers some of the data, but it’s modeled, not observed. With Strict server-side consent mode enabled, your server-side CAPI continues to fire alongside the cookieless ping — it ships the same event_id the browser ping carries, with value / currency / contents filled in from the order, just without the PII. Meta deduplicates the two events by event_id and now has a full server-side observed signal feeding the same conversion record the cookieless ping created. That is a cleaner input than what either browser-only or naïve “send everything” CAPI provides — and it is GDPR-defensible because no identifying user data is transmitted without consent.
The toggle is OFF by default so existing setups don’t see a sudden drop in CAPI matching once they update; turn it on after you’ve configured Consent Mode v2 in your CMP.
Some CMPs (especially CookieYes and Cookiebot when “auto-blocking” is enabled) scan every <script> tag on page load and convert any tag they suspect of tracking into type="text/plain" until consent is granted. The plugin’s inline scripts (mcapi-pageview-init, mcapi-viewcontent-events, mcapi-viewcategory-events, mcapi-inline-bootstrap) only POST first-party events to your own /wp-json/mcapi/v1/event endpoint — they do not directly track the visitor — but a generic auto-blocker cannot tell the difference. If they get blocked, no events reach the queue, and the plugin’s Event Log stays empty.
To prevent this, every plugin-rendered inline script carries CMP exemption attributes:
data-cookieconsent="ignore" — Cookiebot’s documented opt-outdata-cookieyes="cookieyes-necessary" — categorizes the script as essential for CookieYesdata-cmplz-no-cookielaw="1" — excludes from Complianz auto-blockingThese attributes are added automatically. If you use a CMP not listed above (OneTrust, Quantcast Choice, in-house CMPs), you can append more attributes via the mcapi_inline_script_attrs filter:
add_filter( 'mcapi_inline_script_attrs', function( $attrs ) { return $attrs . ' data-your-cmp="ignore"'; } );
If your store sells subscriptions via WooCommerce Subscriptions, by default Meta CAPI receives a fresh Purchase event every time a subscription auto-renews. Meta then attributes the renewal revenue to the original ad campaign that brought the customer in, so your reported ROAS keeps climbing month after month from the same conversion. Most subscription advertisers want to keep their Purchase metric clean of recurring-revenue contamination so optimization signals stay honest.
The plugin auto-detects WooCommerce Subscriptions and adds a “WooCommerce Subscriptions Integration” section to the settings page with two controls:
Subscription Renewal Behavior (radio):
Purchase events. No change in behavior; existing setups keep working.Purchase, but include custom_data.customer_status = "subscription_renewal" so you can filter renewals out in Events Manager / Custom Audiences / Custom Conversions.Subscribe event for new sign-ups and a SubscriptionRenewal custom event for recurring orders. Renewals do not pollute the Purchase metric; advertisers who use Meta’s LTV-bidding can opt into both events.Tag every Purchase with customer_status (checkbox):
When enabled, every Purchase event (subscription or not) carries a custom_data.customer_status field with value new_customer, returning_customer, or subscription_renewal. Meta’s Advantage+ Shopping Campaigns can use this signal to bid differently for new-customer acquisition vs. retention. The classification uses the customer’s prior completed-or-processing order count; for guest checkouts it falls back to billing email lookup so a returning shopper without an account is still recognized.