Description
Stop paying $30–150/month for a GTM Server Container. Send Conversions API events to Meta, Pinterest, and TikTok directly from your WordPress server. Free, no premium tier, no SaaS subscription.
Three platforms in one plugin. Most competitors handle Meta only, or sell Pinterest and TikTok as separate add-ons. This one ships Meta + Pinterest + TikTok server-side dispatch + a clean GTM dataLayer in a single install. The same event_id flows everywhere, so each platform deduplicates browser + server events instead of double-counting.
Real customers aren’t filtered as bots. Behavioral bot detection + ~9,500-CIDR datacenter IP filter (daily auto-refresh) keeps Lighthouse audits, scrapers, and ad-fraud bots out of your Events Manager — without blocking VPN shoppers, Apple iCloud Private Relay users, logged-in customers, or paid-ad clickers. Purchase events are never blocked. Pre-Purchase events that do get filtered are replayed on eventual purchase, preserving the full funnel.
What it does
- Meta + Pinterest + TikTok CAPI — 14 event types, classic + block checkout, HPOS compatible. Per-platform retry: only the failing side is retried.
- GTM dataLayer — Standards-compliant pushes for GA4, Meta Pixel, Pinterest Tag, TikTok Pixel.
- Datacenter IP filter + Blocked Traffic tab — Paginated audit log (IP masked to /24), per-provider breakdown, one-click «Block this CIDR» on Event Log rows.
- CCPA / Limited Data Use — Honors CMP opt-out signals; tags Meta + TikTok payloads with LDU. Optional GDPR strict mode strips PII when consent is denied.
- Cache-safe — Works with LiteSpeed, WP Rocket, Varnish, Cloudflare full-page cache. Click IDs captured client-side into 1st-party cookies; landing pages stay fully cacheable.
- Debug log + Dashboard widget — Per-event delivery status, date/type filters, retention 1–90 days.
This plugin is free. Not «free with limits» — just free. Every feature works, no pro version behind a paywall.
If it helps your store, please leave a review — it genuinely helps other merchants find this plugin.
External Services
This plugin connects your website to external services to send event data.
- Service Used: Meta Conversion API (graph.facebook.com)
- Purpose: To send user interaction and e-commerce event data from your server to Meta’s servers for ad performance measurement, optimization, and audience building.
- Data Sent: Event details (product ID, price) and user parameters (IP address, user agent, hashed email/name/phone, Facebook cookies) are sent when a user performs a key action.
- Service Used: TikTok Events API (business-api.tiktok.com)
- Purpose: Same as Meta CAPI, providing server-side conversion tracking for TikTok Ads optimization and attribution.
- Data Sent: Event details (product ID, price, currency) and user parameters (IP address, user agent, hashed email/phone/external_id, ttp / ttclid cookies) are sent upon user action. Optional under the merchant’s TikTok credentials — the plugin only sends to TikTok if the credentials are configured.
- Service Used: Pinterest Conversions API (api.pinterest.com)
- Purpose: Same as the Meta CAPI, providing reliable tracking for ad performance and audience building on Pinterest.
- Data Sent: Event details and hashed user parameters are sent upon user action.
- Service Used: Google Tag Manager (googletagmanager.com)
- Purpose: To load a JavaScript container from Google’s servers that allows you to manage and deploy marketing and analytics tags.
- Data Sent: The plugin provides your GTM Container ID to Google to fetch the correct script. GTM itself may collect data based on how you configure your tags.
- Service Used: Cloud-provider IP range list —
raw.githubusercontent.com/rezmoss/cloud-provider-ip-addresses- Purpose: Used by the optional Datacenter IP filter to keep the bot blocklist current. Daily background fetch downloads CIDR ranges for AWS, Google Cloud, Azure, Cloudflare, DigitalOcean, Linode, Vultr, Oracle Cloud, and Fastly so events from those ranges can be filtered out before reaching Meta / Pinterest / TikTok.
- Data Sent: None. The plugin only downloads public IP-range manifests; no visitor data is sent to GitHub.
- License: Source repository is CC0-licensed.
- Service Used: Apple iCloud Private Relay egress IP list — same
raw.githubusercontent.com/rezmoss/cloud-provider-ip-addressessource (folderapple_private_relay/)- Purpose: Used by the optional Datacenter IP filter to whitelist real Apple visitors who exit through Apple’s relay infrastructure. Daily background fetch downloads the merged CIDR list so iOS Safari users on Private Relay aren’t mistaken for datacenter bots.
- Data Sent: None. The plugin only downloads the public manifest; no visitor data is sent.
Shared hosting note. Some restrictive shared hosts block outbound HTTPS by default. If event delivery silently fails after install, ask your host to whitelist the following domains for outgoing connections: graph.facebook.com, business-api.tiktok.com, api.pinterest.com, and raw.githubusercontent.com (only needed if you keep «Auto-fetched» enabled on the Blocked Traffic tab — covers both the datacenter blocklist and the Apple Private Relay whitelist).
Advanced Configuration
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.
Consent Mode v2 Setup (GDPR / EU Compliance)
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:
- Cookiebot — Settings «Enable Google Consent Mode» (v2 is default in current versions)
- CookieYes — Site Settings «Google Consent Mode» enable
- Complianz — Integrations Google Consent Mode enable
- Iubenda — Cookie Solution Advanced settings «Enable Consent Mode» «v2 (advanced)»
- Termly — Settings Google Consent Mode enable
- OneTrust — Geolocation Rules Consent Mode enable + map categories
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):
- In GTM, open the tag.
- Click the pause icon to enable it.
- Change its trigger from
CE - PageView Metato the built-in «Consent Initialization – All Pages» trigger (visible in the trigger picker dropdown — guarantees this fires before any other tag). - Submit and publish.
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
- GTM Preview Mode — Open a page with the GTM Preview, click on
Consent Initialization(top of timeline). Confirmdefaultconsent values appear for all four categories. After accepting in your CMP, clickConsentevents lower in the timeline; you should seeupdatecalls flipping the relevant categories togranted. - Browser DevTools — Network tab, filter for
g/collect(GA4) ortr(Meta Pixel). Each request should include agcs=query parameter.gcs=G100means denied,G111means granted,G101means analytics-only. If you seegcs=you have Consent Mode active. If you do not, the CMP wiring is incomplete. - Tag Assistant (tagassistant.google.com) — Connect to your site, fire any event, click on it, scroll to the «Consent» panel. Should show the current state and any updates within the session.
Strict server-side consent mode (PII gating for CAPI)
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:
- Cookiebot —
CookieConsentcookie, looks formarketing:true|false - CookieYes —
cookieyes-consentcookie, looks foradvertisement:yes|no - Complianz —
cmplz_marketingcookie, valueallow/deny - Other CMPs — supply state via the
mcapi_marketing_consent_grantedfilter (returntrue/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.
CMP Auto-Blocking and the Plugin’s Inline Scripts
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-blocking
These 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"'; } );
WooCommerce Subscriptions Integration
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):
- Default — send renewals as regular
Purchaseevents. No change in behavior; existing setups keep working. - Skip — do not send renewals to Meta CAPI at all. Cleanest path for ROAS hygiene; you lose the LTV signal Meta could derive from renewals (most stores using value-based bidding don’t rely on this anyway).
- Tag — still send a
Purchase, but includecustom_data.customer_status = "subscription_renewal"so you can filter renewals out in Events Manager / Custom Audiences / Custom Conversions. - Subscribe / SubscriptionRenewal events — send Meta’s standard
Subscribeevent for new sign-ups and aSubscriptionRenewalcustom event for recurring orders. Renewals do not pollute thePurchasemetric; 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.
Installation
Quick start (3 steps)
- Install and activate the plugin. WooCommerce must already be active.
- Open CAPI Suite Main Settings and paste your Meta Pixel ID + Access Token. Add TikTok and/or Pinterest credentials if you use them. Empty fields for platforms you don’t use are fine.
- (If you use GTM) Download the bundled
gtm-template.jsonfrom the GTM Container ID box, import it into your GTM container in Merge mode, set the pixel-code constants to your real IDs, and publish.
Server-side events start flowing on the next page view. Send a test from Event Management Test Modes to verify credentials before going live.
Recommended GTM dedup configuration
To prevent duplicate browser+server events:
- In Meta Events Manager your Pixel Settings Event Setup, turn off «Track Events Automatically Without Code». This plugin handles all event sending.
- In your GTM container, pause or delete any auto-created tags starting with
FB_.
The bundled GTM template ships GA4 + Meta tags pre-wired to the GA4 ecommerce dataLayer, plus TikTok tags that read from a CONST - TikTok Pixel Code variable. Pinterest tags are added manually because the Community Template can fail to import inside container exports.
If you cannot import the JSON template (locked container, workspace permissions) or want to set up GTM manually, the full step-by-step walkthrough ships with the plugin at wp-content/plugins/easy-meta-capi/docs/GTM-MANUAL-SETUP.txt.
Page-cache plugins
If your JS optimizer (LiteSpeed, WP Rocket, Autoptimize) defers inline scripts, add these IDs to its «exclude from defer / combine» list:
mcapi-pageview-initmcapi-viewcontent-eventsmcapi-viewcategory-eventsmcapi-frontend-events
Cloudflare Rocket Loader is handled automatically via data-cfasync="false".
Verify
Open CAPI Suite Event Log after browsing your store. Events should appear with «Success (Meta)» / «Success (TikTok)» / «Success (Pinterest)» status. The Dashboard widget also shows queue health at a glance.
For Consent Mode v2 wiring, the strict server-side consent toggle, CMP auto-block compatibility, and the WooCommerce Subscriptions integration, see Advanced Configuration below.
FAQ
-
Does this plugin replace the Meta Pixel?
-
No, it works alongside it. The plugin sends server-side (CAPI) events, while GTM handles the browser-side Pixel. Both use the same
event_id, so Meta merges them automatically without counting anything twice. -
What is the difference between this and a GTM Server Container?
-
A GTM Server Container runs on Google Cloud and costs money every month. This plugin does the same job directly from your WordPress server — no extra infrastructure, no extra bill.
-
Does it work with page caching plugins (WP Rocket, LiteSpeed, etc.)?
-
Yes. PageView and ViewCategory events fire from JavaScript, so they work even on fully cached pages. Cart, checkout, and purchase pages are not cached by default.
-
What plugins are required?
-
WooCommerce. That’s it. If you use other GTM plugins (like Google Site Kit), disable their e-commerce features to avoid conflicts.
-
Is there a pro version?
-
No. Everything is included.
-
My events aren’t showing in Meta Events Manager. What’s wrong?
-
Check these in order:
1. Open your Event Log tab in the plugin settings. If events appear there with «Success (Meta)», the plugin is sending them. If Meta isn’t receiving them, the problem is on Meta’s end — usually Pixel ID or Access Token mismatch.
2. If the log is empty after visiting your store, you likely have a JS optimizer (LiteSpeed / WP Rocket / Autoptimize) deferring the plugin’s tracking scripts. See next answer.
3. Check the admin notice on the plugin settings page — the plugin auto-detects your cache setup and shows exclude-list instructions. -
I use LiteSpeed Cache. How do I configure it?
-
Go to LiteSpeed Cache Page Optimization JS Settings JS Defer Excludes and add these script IDs (one per line):
mcapi-pageview-init
mcapi-viewcontent-events
mcapi-viewcategory-events
mcapi-frontend-events
Then purge all cache. -
I use WP Rocket. How do I configure it?
-
Go to WP Rocket File Optimization JavaScript Excluded JavaScript Files and add the same script IDs listed above for LiteSpeed. Then clear WP Rocket cache.
-
I use Autoptimize. How do I configure it?
-
Go to Autoptimize JS, CSS & HTML Exclude scripts from Autoptimize and add the same script IDs.
-
What about Cloudflare Rocket Loader?
-
The plugin adds
data-cfasync="false"to its inline scripts, which Cloudflare Rocket Loader respects. No configuration needed. -
Does it work with a block-based theme (e.g. Twenty Twenty-Five)?
-
Yes. The plugin’s tracking works with the WooCommerce Products block used by FSE themes.
-
GTM tags firing means your dataLayer pushes work — but your CMP’s auto-blocker may be stopping the plugin’s inline scripts from running, so no event ever reaches the server. Open browser DevTools Elements, search for
mcapi-pageview-init, and check the script tag’stypeattribute. If it readstype="text/plain"(or anything other thantext/javascript/ no type), your CMP has blocked it. The plugin ships CMP exemption attributes (data-cookieconsent="ignore",data-cookieyes="cookieyes-necessary",data-cmplz-no-cookielaw="1") on every inline script — Cookiebot, CookieYes, Complianz are handled out of the box. For less common CMPs (OneTrust, in-house) use themcapi_inline_script_attrsfilter — see the CMP Auto-Blocking section in the Advanced Configuration tab. -
I sell subscriptions and Meta is over-attributing revenue to old ad campaigns.
-
WooCommerce Subscriptions auto-renewals would be sent to Meta CAPI as fresh
Purchaseevents by default, so Meta would credit the original ad with the renewal value. The plugin auto-detects WooCommerce Subscriptions and adds a settings section with four behavior modes — most subscription stores pick Skip or Subscribe / SubscriptionRenewal events to keep theirPurchasemetric clean. See the WooCommerce Subscriptions Integration section in the Advanced Configuration tab. -
By default, no — the server-side CAPI calls fire from PHP and never see your CMP’s browser-side
gtag('consent', ...)signals. The Privacy & Consent (Server-side) settings section has an opt-in «Strict server-side consent mode» toggle. When enabled, the plugin reads your CMP’s cookie (Cookiebot, CookieYes, Complianz auto-detected; others via themcapi_marketing_consent_grantedfilter) and, if the visitor explicitly denied marketing consent, strips the hashed PII (email, phone, name, billing address, fbp/fbc) from the CAPI payload. The event still ships withevent_idand non-PII context so Meta’s browserCAPI dedup and conversion modeling keep working — the data simply no longer carries personally identifying fields. Default OFF preserves backward compatibility; recommended ON for EU stores. See Strict server-side consent mode in Advanced Configuration for the full mechanism. -
Will the datacenter IP filter block my real customers behind a VPN?
-
No, in almost every case. The filter has multiple bypass conditions for real users: visitors who clicked an ad (fbclid / gclid / ttclid in URL or 1st-party cookie), Apple iCloud Private Relay egress IPs (whitelisted from Apple’s published list), logged-in WooCommerce customers, and visitors with
_fbp(Meta Pixel) or_ga(Google Analytics) cookies set from a previous visit. Purchase events are NEVER blocked. The one remaining edge case — a brand-new organic visitor on a VPN with no cookies whatsoever — has their first PageView blocked, but if they go on to purchase, the plugin replays the full funnel chain (PageView ViewContent AddToCart InitiateCheckout) so Meta gets the complete journey. Cross-device shoppers (mobile click desktop purchase) lose per-device funnel granularity but Meta’s email-hash matching at Purchase time bridges the journey for ROAS attribution. You can review every blocked request in the Blocked Traffic tab to verify the filter isn’t catching legitimate traffic. -
Why does the **Blocked Traffic** tab show IPs as `192.168.1.x` instead of the full address?
-
GDPR-friendly auditing. The plugin masks the last octet of every blocked IP at record-time, so wp-admin browse and DB exports never reveal raw visitor IPs. The unmasked IP only ever lives in the request-scoped local variable that decides whether to block — nothing raw is persisted to disk.
Reviews
Contributors & Developers
“CAPI Suite: Meta, Pinterest, TikTok, GTM” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “CAPI Suite: Meta, Pinterest, TikTok, GTM” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
3.6.0
- TikTok CAPI integration. Server-side dispatch alongside Meta and Pinterest. Pixel Code, Access Token, Advertiser ID, and a dedicated TikTok Test Mode. Re-import the GTM template to get TikTok Pixel tags.
- Behavioral bot detection. Datacenter IP visitors are briefly observed before forwarding events. Real-browser activity (mouse/scroll, _fbp cookie, click IDs, Apple Private Relay, logged-in customers) graduates the visitor instantly; confirmed bots are dropped. Purchase events are never blocked.
- Blocklist redesign. Pre-bundled ~9,500 cloud-provider CIDR ranges with daily auto-refresh. IPv4 + IPv6 support, O(log N) lookup via binary index seek. New Blocked Traffic admin tab with per-source toggle (bundled / auto-fetched / custom), paginated table, and one-click «Block this CIDR» on Event Log rows.
- Funnel-chain recovery. Held pre-Purchase events are replayed on the next Purchase from the same visitor (PageView ViewContent AddToCart InitiateCheckout), so Meta sees the full attribution path instead of a lone Purchase.
- Apple Private Relay whitelist. Daily-fetched egress IPs bypass the datacenter filter, preserving iOS shopper events.
- CCPA / Limited Data Use toggle. Honors visitor opt-out via cookie or filter.
- Synchronous / Asynchronous sending modes. Synchronous (3-second per-platform timeout) for shared hosts where cron is unreliable.
- WP Dashboard widget. Queue health at a glance: size, oldest pending age, last successful dispatch, datacenter blocks today.
- Per-platform retry. When Meta succeeds but Pinterest or TikTok transiently fails, only the failing platform is retried next cron tick.
- Critical fix: queue processor no longer leaks rows when an event’s
send_totargets a platform with no credentials configured. Previously such rows could accumulate indefinitely (tens of thousands over days). Now correctly dropped on the first cycle. - Security: REST endpoint requires an HMAC-rotated token with a 25-hour tolerance window covering HTML page caches. Checkout-funnel honeypot rejects empty-cart fake POSTs. IP hashes salted with
wp_salt('auth')for GDPR/KVKK compliance. Proxy headers trusted only when REMOTE_ADDR is in a known proxy range. - Performance: chunked DELETE for log/queue cleanup. Composite B-tree index for binary blocklist seek. Negative cache on visitor lookups. REST rate limiter skipped on installs without a persistent object cache. Ad-click landing pages no longer force-create a WooCommerce session.
- Plugin renamed to «CAPI Suite: Meta, Pinterest, TikTok, GTM». Settings UI reorganized: Sending Method + Test Modes moved to Event Management tab.
- GTM template updated to modern API schema with TikTok Pixel tags. Re-import required.
3.5.3
- Fix: spurious AJAX
add_to_cartevents from WooCommerce sessionStorage fragment replay. - Fix: per-platform retry tracking — when one platform transiently fails, only the failing side retries.
- New: Event Log captures User Agent, supports date-range filtering, and retention is configurable (1–90 days, default 15).
- Hardening: third-party autoloader protection extended to all
class_exists()calls.
3.5.2
- Critical: GTM template re-import required. Full migration to modern GTM API schema (older templates rejected with «File format invalid» / «Unknown entity type» in fresh workspaces). Plugin runtime unchanged.
3.5.1
- Critical hotfix: CMP detection helper triggered third-party autoloader fatals (CookieYes / Cookie Law Info). All detection
class_exists()calls now passfalseto suppress autoload.
3.5.0
- Fix: GTM container template imports cleanly (was rejected with «Unrecognized value [customEvent]»).
- New: Consent Mode v2 support, CMP auto-block exemption (CookieYes / Cookiebot / Complianz), and a CMP detection admin notice.
- New: Strict server-side consent mode — strips hashed PII when consent denied; still ships
event_id+ non-PII context for dedup. - New: WooCommerce Subscriptions integration — Subscription Renewal Behavior + customer_status tagging keep Purchase ROAS clean for subscription stores.
- Fix:
_fbp/_fbccookie domain strips leadingwww.to match Pixel JS.
3.4.2
- Fix: GTM template adds two CJS variables converting GA4-schema dataLayer into the
contents[]shape Meta Pixel and Pinterest Tag expect. - Fix: Pinterest event-name typos in manual setup; correct catalog
content_idsparameter.
3.4.1
- Fix: dataLayer items include
item_idalongsideidso GA4’s Items report no longer shows «(not set)» for products.
3.4.0
- Fix: Event log timestamps stable across hosts with mismatched PHP/WordPress timezones (stored UTC, displayed via
wp_date()). - Fix: GTM template no longer fails import with «Unrecognized value [EVENT]».
- New: bot/crawler UA filter before queue insert. Purchase events exempt. Filterable via
mcapi_is_bot_request. - New: Action Scheduler used for recurring tasks when available — more reliable than WP-Cron on low-traffic sites.
3.3.0
- New: REST API endpoint
/wp-json/mcapi/v1/eventfor cache-safe browser tracking — no nonce needed (works behind 7-day page caches). Secured by same-origin, per-IP rate limit, body cap, event whitelist. - Improvement: reliable retries on transient API failures (5xx, 429, network).
- Improvement: real client IP via
CF-Connecting-IP/X-Forwarded-For/X-Real-IP(sites behind Cloudflare / LB no longer hit rate limits prematurely). - Improvement: Safari ITP bypass —
_fbp/_fbccookies rewritten server-side with 90-day TTL. - Improvement: phone numbers normalized to E.164 using billing country;
external_idSHA-256 hashed; cron lock on queue processor; guest external_id is a cookie-backed UUID.
For older versions (3.2.x and below), see the SVN repository history at https://plugins.svn.wordpress.org/easy-meta-capi/tags/.
