{"id":249247,"date":"2025-09-05T05:59:24","date_gmt":"2025-09-05T05:59:24","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/easy-meta-capi\/"},"modified":"2026-05-16T17:50:38","modified_gmt":"2026-05-16T17:50:38","slug":"easy-meta-capi","status":"publish","type":"plugin","link":"https:\/\/de.wordpress.org\/plugins\/easy-meta-capi\/","author":23356298,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"3.7.0","stable_tag":"3.7.0","tested":"6.9.4","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"CAPI Suite: Meta, Pinterest, TikTok, GTM","header_author":"Suhan Duman","header_description":"Injects GTM and sends server-side events to the Meta Conversion API with a unified Data Layer.","assets_banners_color":"1c3462","last_updated":"2026-05-16 17:50:38","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/profiles.wordpress.org\/suhanduman\/","rating":5,"author_block_rating":0,"active_installs":30,"downloads":1366,"num_ratings":1,"support_threads":5,"support_threads_resolved":5,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"3.1.0":{"tag":"3.1.0","author":"suhanduman","date":"2025-09-29 10:48:49"},"3.1.1":{"tag":"3.1.1","author":"suhanduman","date":"2025-09-29 11:54:37"},"3.2.0":{"tag":"3.2.0","author":"suhanduman","date":"2026-04-16 13:47:32"},"3.2.1":{"tag":"3.2.1","author":"suhanduman","date":"2026-04-16 14:42:02"},"3.2.2":{"tag":"3.2.2","author":"suhanduman","date":"2026-04-18 14:18:43"},"3.2.3":{"tag":"3.2.3","author":"suhanduman","date":"2026-04-21 07:52:09"},"3.2.4":{"tag":"3.2.4","author":"suhanduman","date":"2026-04-21 08:01:43"},"3.2.5":{"tag":"3.2.5","author":"suhanduman","date":"2026-04-22 18:29:08"},"3.2.6":{"tag":"3.2.6","author":"suhanduman","date":"2026-04-22 18:37:43"},"3.3.0":{"tag":"3.3.0","author":"suhanduman","date":"2026-04-22 19:18:11"},"3.4.0":{"tag":"3.4.0","author":"suhanduman","date":"2026-05-04 15:41:27"},"3.4.1":{"tag":"3.4.1","author":"suhanduman","date":"2026-05-04 16:01:56"},"3.4.2":{"tag":"3.4.2","author":"suhanduman","date":"2026-05-04 16:29:53"},"3.5.0":{"tag":"3.5.0","author":"suhanduman","date":"2026-05-06 15:43:10"},"3.5.1":{"tag":"3.5.1","author":"suhanduman","date":"2026-05-06 17:53:08"},"3.5.2":{"tag":"3.5.2","author":"suhanduman","date":"2026-05-06 19:19:51"},"3.5.3":{"tag":"3.5.3","author":"suhanduman","date":"2026-05-07 10:41:35"},"3.6.0":{"tag":"3.6.0","author":"suhanduman","date":"2026-05-11 14:49:25"},"3.7.0":{"tag":"3.7.0","author":"suhanduman","date":"2026-05-16 17:50:38"}},"upgrade_notice":{"3.7.0":"<p>Event Log gains a By-IP grouped view and customer-protection badges that prevent excluding real buyers by mistake. AI crawlers (GPTBot, PerplexityBot, ClaudeBot, etc.) classified separately from bots with their own counter on the Dashboard. Block-list terminology clarified to Exclude (it filters CAPI dispatch, not site access). Google Ads Enhanced Conversions and Pinterest <code>_epik<\/code> capture continue from earlier work \u2014 re-import the GTM template if you haven&#039;t yet. One additive DB column on upgrade (instant DDL on InnoDB 5.7+ \/ MariaDB 10.3+).<\/p>","3.6.0":"<p>TikTok CAPI added. Plugin renamed to CAPI Suite. Behavioral bot detection (VPN shoppers no longer misclassified). Blocklist DB tables (IPv4+IPv6) with per-source toggle and one-click CIDR block on Event Log rows. CCPA toggle. Re-import the GTM template for TikTok tags.<\/p>","3.5.3":"<p>Reliability fixes. (1) Spurious AJAX add_to_cart events from sessionStorage fragment replay eliminated. (2) Per-platform queue retry: only the failing side is retried. (3) Event Log captures User Agent, supports date-range filtering, retention configurable. No GTM template change.<\/p>","3.5.2":"<p><strong>Critical: GTM template re-import required.<\/strong> Bundled template migrated to modern GTM API schema. Older templates rejected with &quot;File format invalid&quot;\/&quot;Unknown entity type&quot;. Re-download and re-import in Merge mode. Plugin runtime unchanged.<\/p>","3.5.1":"<p><strong>Critical hotfix.<\/strong> v3.5.0&#039;s CMP detection helper called class_exists() without disabling autoload, triggering CookieYes \/ Cookie Law Info fatal errors (white screen). Update immediately if you have either plugin installed.<\/p>","3.5.0":"<p><strong>GTM template re-import required.<\/strong> Fixes import-error bug (&quot;Unrecognized value [customEvent]&quot;). Adds Consent Mode v2, CMP auto-block exemptions (CookieYes\/Cookiebot\/Complianz), and WooCommerce Subscriptions integration. Server-side CAPI unchanged.<\/p>","3.4.2":"<p><strong>Action required for existing installs.<\/strong> Fixes a GA4-schema bug causing Meta Events Manager to reject browser-tag parameters. Re-import the GTM template (&quot;Merge&quot; mode) OR add two new Custom JavaScript variables manually.<\/p>"},"ratings":{"1":0,"2":0,"3":0,"4":0,"5":1},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3528853,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3528853,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3528853,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3528853,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["3.1.0","3.1.1","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","3.2.5","3.2.6","3.3.0","3.4.0","3.4.1","3.4.2","3.5.0","3.5.1","3.5.2","3.5.3","3.6.0","3.7.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[262246],"plugin_tags":[194928,207498,167802,179062,286],"plugin_category":[45],"plugin_contributors":[247430],"plugin_business_model":[],"class_list":["post-249247","plugin","type-plugin","status-publish","hentry","plugin_section-dashboard-widgets","plugin_tags-facebook-conversions-api","plugin_tags-meta-pixel","plugin_tags-pinterest-tag","plugin_tags-tiktok-pixel","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-suhanduman","plugin_committers-suhanduman"],"banners":{"banner":"https:\/\/ps.w.org\/easy-meta-capi\/assets\/banner-772x250.png?rev=3528853","banner_2x":"https:\/\/ps.w.org\/easy-meta-capi\/assets\/banner-1544x500.png?rev=3528853","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/easy-meta-capi\/assets\/icon-128x128.png?rev=3528853","icon_2x":"https:\/\/ps.w.org\/easy-meta-capi\/assets\/icon-256x256.png?rev=3528853","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>Stop paying $30\u2013150\/month for a GTM Server Container.<\/strong> Send Conversions API events to Meta, Pinterest, and TikTok directly from your WordPress server. Free, no premium tier, no SaaS subscription.<\/p>\n\n<p><strong>Three CAPI platforms + Google Ads in one plugin.<\/strong> Most competitors handle Meta only, or sell Pinterest and TikTok as separate add-ons. This one ships Meta + Pinterest + TikTok server-side dispatch + Google Ads Enhanced Conversions + a clean GTM dataLayer in a single install. The same <code>event_id<\/code> flows everywhere, so each platform deduplicates browser + server events instead of double-counting.<\/p>\n\n<p><strong>Real customers aren't filtered as bots.<\/strong> Behavioral bot detection + ~9,500-CIDR datacenter IP filter + AI-crawler classification (GPTBot, PerplexityBot, ClaudeBot, Google-Extended, etc.) keeps Lighthouse audits, scrapers, and ad-fraud bots out of your Events Manager \u2014 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.<\/p>\n\n<p><strong>What it does<\/strong><\/p>\n\n<ul>\n<li><strong>Meta + Pinterest + TikTok CAPI<\/strong> \u2014 14 event types, classic + block checkout, HPOS compatible. Per-platform retry: only the failing side is retried.<\/li>\n<li><strong>Google Ads Enhanced Conversions<\/strong> \u2014 GTM template ships Conversion Linker + Purchase Conversion tag (EC enabled). Captures <code>gclid<\/code>\/<code>gbraid<\/code>\/<code>wbraid<\/code> \u2014 recovers iOS Safari attribution post-ITP.<\/li>\n<li><strong>GTM dataLayer<\/strong> \u2014 Pushes for GA4, Meta Pixel, Pinterest Tag, TikTok Pixel, Google Ads.<\/li>\n<li><strong>Datacenter IP filter + Excluded Traffic tab<\/strong> \u2014 Paginated audit log (IP masked to \/24), per-provider breakdown, one-click exclude on Event Log rows. By-IP grouped view surfaces worst-offender IPs at a glance; customer-protection badges prevent excluding real buyers by mistake.<\/li>\n<li><strong>CCPA \/ Limited Data Use<\/strong> \u2014 Honors CMP opt-out signals; tags Meta + TikTok payloads with LDU. Optional GDPR strict mode strips PII when consent is denied.<\/li>\n<li><strong>Cache-safe<\/strong> \u2014 Works with LiteSpeed, WP Rocket, Varnish, Cloudflare full-page cache. Click IDs captured client-side into 1st-party cookies; landing pages stay fully cacheable.<\/li>\n<li><strong>Debug log + Dashboard widget<\/strong> \u2014 Per-event delivery status, date\/type filters, retention 1\u201390 days.<\/li>\n<\/ul>\n\n<p>This plugin is free. Not \"free with limits\" \u2014 just free. Every feature works, no pro version behind a paywall.<\/p>\n\n<p>If it helps your store, please <a href=\"https:\/\/wordpress.org\/support\/plugin\/easy-meta-capi\/reviews\/#new-post\">leave a review<\/a> \u2014 it genuinely helps other merchants find this plugin.<\/p>\n\n<h3>External Services<\/h3>\n\n<p>This plugin connects your website to external services to send event data.<\/p>\n\n<ul>\n<li><strong>Service Used:<\/strong> Meta Conversion API (graph.facebook.com)\n\n<ul>\n<li><strong>Purpose:<\/strong> To send user interaction and e-commerce event data from your server to Meta's servers for ad performance measurement, optimization, and audience building.<\/li>\n<li><strong>Data Sent:<\/strong> 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.<\/li>\n<\/ul><\/li>\n<li><strong>Service Used:<\/strong> TikTok Events API (business-api.tiktok.com)\n\n<ul>\n<li><strong>Purpose:<\/strong> Same as Meta CAPI, providing server-side conversion tracking for TikTok Ads optimization and attribution.<\/li>\n<li><strong>Data Sent:<\/strong> 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 \u2014 the plugin only sends to TikTok if the credentials are configured.<\/li>\n<\/ul><\/li>\n<li><strong>Service Used:<\/strong> Pinterest Conversions API (api.pinterest.com)\n\n<ul>\n<li><strong>Purpose:<\/strong> Same as the Meta CAPI, providing reliable tracking for ad performance and audience building on Pinterest.<\/li>\n<li><strong>Data Sent:<\/strong> Event details and hashed user parameters are sent upon user action.<\/li>\n<\/ul><\/li>\n<li><strong>Service Used:<\/strong> Google Tag Manager (googletagmanager.com)\n\n<ul>\n<li><strong>Purpose:<\/strong> To load a JavaScript container from Google's servers that allows you to manage and deploy marketing and analytics tags.<\/li>\n<li><strong>Data Sent:<\/strong> 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.<\/li>\n<\/ul><\/li>\n<li><strong>Service Used:<\/strong> Cloud-provider IP range list \u2014 <code>raw.githubusercontent.com\/rezmoss\/cloud-provider-ip-addresses<\/code>\n\n<ul>\n<li><strong>Purpose:<\/strong> Used by the optional <strong>Datacenter IP filter<\/strong> 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.<\/li>\n<li><strong>Data Sent:<\/strong> None. The plugin only downloads public IP-range manifests; no visitor data is sent to GitHub.<\/li>\n<li><strong>License:<\/strong> Source repository is CC0-licensed.<\/li>\n<\/ul><\/li>\n<li><strong>Service Used:<\/strong> Apple iCloud Private Relay egress IP list \u2014 same <code>raw.githubusercontent.com\/rezmoss\/cloud-provider-ip-addresses<\/code> source (folder <code>apple_private_relay\/<\/code>)\n\n<ul>\n<li><strong>Purpose:<\/strong> Used by the optional <strong>Datacenter IP filter<\/strong> 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.<\/li>\n<li><strong>Data Sent:<\/strong> None. The plugin only downloads the public manifest; no visitor data is sent.<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<p><strong>Shared hosting note.<\/strong> 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: <code>graph.facebook.com<\/code>, <code>business-api.tiktok.com<\/code>, <code>api.pinterest.com<\/code>, and <code>raw.githubusercontent.com<\/code> (only needed if you keep \"Auto-fetched\" enabled on the Blocked Traffic tab \u2014 covers both the datacenter blocklist and the Apple Private Relay whitelist).<\/p>\n\n<h3>Advanced Configuration<\/h3>\n\n<p>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 \u2014 turn them on as your store needs them.<\/p>\n\n<h3>Consent Mode v2 Setup (GDPR \/ EU Compliance)<\/h3>\n\n<p>If you serve EU visitors, GA4 and Meta browser tags don't fire when consent is denied \u2014 typically losing <strong>20\u201350% of measured event volume<\/strong>. Google Consent Mode v2 recovers this: when consent is denied, GA4 \/ Meta tags switch to <strong>cookieless pings<\/strong> (anonymous beacons carrying event name, value, currency, timestamp but no client identifier). Google's ML models the conversions from these pings and shows them mixed with observed ones in your reports. A single CMP integration repairs both GA4 and Meta attribution because the Meta Pixel template reads the same consent signals.<\/p>\n\n<p><strong>How to enable.<\/strong> Popular CMP plugins (Cookiebot, CookieYes, Complianz, Iubenda, Termly, OneTrust) all have a native Consent Mode v2 toggle in their settings \u2014 find and enable it. The CMP then calls <code>gtag('consent', 'default', {denied})<\/code> before GTM loads and <code>gtag('consent', 'update', {granted})<\/code> after the visitor accepts.<\/p>\n\n<p>The bundled GTM template includes a paused <strong>\"Consent Defaults (Pre-CMP)\"<\/strong> tag. Enable it only if your CMP doesn't set <code>gtag('consent', 'default', ...)<\/code> on its own (rare with modern CMPs).<\/p>\n\n<h3>Strict server-side consent mode (PII gating for CAPI)<\/h3>\n\n<p>Consent Mode v2 only controls <strong>browser<\/strong> tags. Server-side CAPI fires from PHP, never sees <code>gtag('consent', ...)<\/code> signals \u2014 so it transmits hashed PII regardless of cookie-banner choice. Fine outside the EU; a GDPR concern inside it.<\/p>\n\n<p>The <strong>Privacy &amp; Consent (Server-side)<\/strong> section has a Strict server-side consent toggle (default OFF). When enabled and the visitor has denied marketing consent in your CMP, identifying PII (<code>em<\/code>, <code>ph<\/code>, <code>fn<\/code>, <code>ln<\/code>, address, <code>fbp<\/code>, <code>fbc<\/code> \u2026) is stripped from the CAPI payload. The event still ships with <code>event_id<\/code>, <code>value<\/code>, <code>currency<\/code>, <code>contents<\/code> \u2014 Cookiebot, CookieYes, and Complianz cookies are read automatically; other CMPs supply state via the <code>mcapi_marketing_consent_granted<\/code> filter.<\/p>\n\n<p><strong>Why this matters alongside Consent Mode v2.<\/strong> Denied-consent browser pixels switch to cookieless pings \u2014 modeled, not observed. With Strict server-side consent ON, your server-side CAPI ships alongside that ping carrying the same <code>event_id<\/code>. Meta dedupes by <code>event_id<\/code> and now has an <strong>observed<\/strong> server signal feeding the same conversion record the cookieless ping created \u2014 cleaner Event Match Quality than browser-only or na\u00efve \"send everything\" CAPI, and GDPR-defensible because no identifying data leaves your server.<\/p>\n\n<p>Default OFF preserves match quality for existing non-EU setups. Recommended ON once Consent Mode v2 is configured in your CMP.<\/p>\n\n<h3>CMP Auto-Blocking and the Plugin's Inline Scripts<\/h3>\n\n<p>CMPs with \"auto-blocking\" (Cookiebot, CookieYes, others) scan every <code>&lt;script&gt;<\/code> tag on load and convert anything they suspect of tracking to <code>type=\"text\/plain\"<\/code> until consent. The plugin's inline scripts only POST first-party events to your own REST endpoint \u2014 but a generic auto-blocker can't tell. To avoid a silent break, every plugin-rendered inline script ships with opt-out attributes for Cookiebot (<code>data-cookieconsent=\"ignore\"<\/code>), CookieYes (<code>data-cookieyes=\"cookieyes-necessary\"<\/code>), and Complianz (<code>data-cmplz-no-cookielaw=\"1\"<\/code>). For other CMPs (OneTrust, Quantcast, in-house), append your own attribute via the <code>mcapi_inline_script_attrs<\/code> filter.<\/p>\n\n<h3>WooCommerce Subscriptions Integration<\/h3>\n\n<p>By default, every WooCommerce Subscriptions auto-renewal sends a fresh <code>Purchase<\/code> to Meta CAPI \u2014 credited to the original acquisition ad. Reported ROAS keeps climbing month after month from the same conversion, polluting optimization signals.<\/p>\n\n<p>The plugin auto-detects WooCommerce Subscriptions and exposes:<\/p>\n\n<p><strong>Subscription Renewal Behavior<\/strong> (radio):<\/p>\n\n<ul>\n<li><strong>Default<\/strong> \u2014 renewals send as regular <code>Purchase<\/code>. Existing setups unchanged.<\/li>\n<li><strong>Skip<\/strong> \u2014 renewals not sent. Cleanest ROAS hygiene; you forfeit Meta's LTV signal from renewals.<\/li>\n<li><strong>Tag<\/strong> \u2014 renewals still send <code>Purchase<\/code> but with <code>custom_data.customer_status = \"subscription_renewal\"<\/code> so you can filter them in Events Manager.<\/li>\n<li><strong>Subscribe \/ SubscriptionRenewal events<\/strong> \u2014 Meta's standard <code>Subscribe<\/code> for sign-ups + a <code>SubscriptionRenewal<\/code> custom event for renewals. <code>Purchase<\/code> stays clean, advertisers using LTV-bidding can opt into both.<\/li>\n<\/ul>\n\n<p><strong>Tag every Purchase with customer_status<\/strong> (checkbox): adds <code>custom_data.customer_status<\/code> (<code>new_customer<\/code> \/ <code>returning_customer<\/code> \/ <code>subscription_renewal<\/code>) to every <code>Purchase<\/code> so Meta Advantage+ can bid acquisition vs. retention differently. Guest checkouts fall back to billing-email lookup.<\/p>\n\n<h3>Disclaimer<\/h3>\n\n<p>This plugin is an independent, community-driven implementation of server-side Conversions API protocols. It is not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc., TikTok Ltd., Pinterest, Inc., Google LLC, Automattic Inc., or any other trademark holder referenced herein.<\/p>\n\n<p>\"Meta\", \"Facebook\", and the Meta Pixel are trademarks of Meta Platforms, Inc. \"TikTok\" is a trademark of TikTok Ltd. \"Pinterest\" is a trademark of Pinterest, Inc. \"Google Tag Manager\", \"Google Ads\", and \"GA4\" are trademarks of Google LLC. \"WooCommerce\" is a trademark of Automattic Inc. All trademark references are used solely for descriptive interoperability purposes \u2014 to indicate which platforms this plugin can transmit data to under the merchant's own configured credentials.<\/p>\n\n<p>No user data is transmitted to any external service until the merchant explicitly configures their own platform credentials in the plugin settings. The plugin does not \"phone home\" or contact any developer-controlled server. The only outbound HTTP calls are: (1) merchant-configured CAPI endpoints, (2) the public CIDR manifests at raw.githubusercontent.com used by the optional Datacenter IP filter \u2014 no visitor data is sent in those manifest fetches.<\/p>\n\n<!--section=installation-->\n<h3>Quick start (3 steps)<\/h3>\n\n<ol>\n<li>Install and activate the plugin. WooCommerce must already be active.<\/li>\n<li>Open <strong>CAPI Suite \u2192 Main Settings<\/strong> and paste your <strong>Meta Pixel ID + Access Token<\/strong>. Add <strong>TikTok<\/strong> and\/or <strong>Pinterest<\/strong> credentials if you use them. Empty fields for platforms you don't use are fine.<\/li>\n<li><em>(If you use GTM)<\/em> Download the bundled <code>gtm-template.json<\/code> from the <strong>GTM Container ID<\/strong> box, import it into your GTM container in <strong>Merge<\/strong> mode, set the pixel-code constants to your real IDs, and publish.<\/li>\n<\/ol>\n\n<p>Server-side events start flowing on the next page view. Send a test from <strong>Event Management \u2192 Test Modes<\/strong> to verify credentials before going live.<\/p>\n\n<h3>Recommended GTM dedup configuration<\/h3>\n\n<p>To prevent duplicate browser+server events:<\/p>\n\n<ol>\n<li>In <strong>Meta Events Manager \u2192 your Pixel \u2192 Settings \u2192 Event Setup<\/strong>, turn <strong>off<\/strong> \"Track Events Automatically Without Code\". This plugin handles all event sending.<\/li>\n<li>In your GTM container, pause or delete any auto-created tags starting with <code>FB_<\/code>.<\/li>\n<\/ol>\n\n<p>The bundled GTM template ships GA4 + Meta tags pre-wired to the GA4 ecommerce dataLayer, plus TikTok tags that read from a <code>CONST - TikTok Pixel Code<\/code> variable. Pinterest tags are added manually because the Community Template can fail to import inside container exports.<\/p>\n\n<p>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 <code>wp-content\/plugins\/easy-meta-capi\/docs\/GTM-MANUAL-SETUP.txt<\/code>.<\/p>\n\n<h3>Verify<\/h3>\n\n<p>Open <strong>CAPI Suite \u2192 Event Log<\/strong> after browsing your store. Successful dispatches show as \"Success (Meta)\" \/ \"Success (TikTok)\" \/ \"Success (Pinterest)\". The Dashboard widget shows queue health at a glance.<\/p>\n\n<p>If the log stays empty, a JS optimizer is probably deferring the plugin's inline scripts \u2014 see the cache-plugin FAQ. Detailed GTM setup, Google Ads Enhanced Conversions, and other platform tags live in <code>docs\/GTM-MANUAL-SETUP.txt<\/code>. Consent Mode v2, Strict server-side consent, CMP auto-block, and WC Subscriptions are documented under <strong>Advanced Configuration<\/strong> below.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20plugin%20replace%20the%20meta%20pixel%3F\"><h3>Does this plugin replace the Meta Pixel?<\/h3><\/dt>\n<dd><p>No, it works alongside it. The plugin sends server-side (CAPI) events, while GTM handles the browser-side Pixel. Both use the same <code>event_id<\/code>, so Meta merges them automatically without counting anything twice.<\/p><\/dd>\n<dt id=\"what%20is%20the%20difference%20between%20this%20and%20a%20gtm%20server%20container%3F\"><h3>What is the difference between this and a GTM Server Container?<\/h3><\/dt>\n<dd><p>A GTM Server Container runs on Google Cloud and costs money every month. This plugin does the same job directly from your WordPress server \u2014 no extra infrastructure, no extra bill.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20page%20caching%20plugins%20%28wp%20rocket%2C%20litespeed%2C%20etc.%29%3F\"><h3>Does it work with page caching plugins (WP Rocket, LiteSpeed, etc.)?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n<dt id=\"what%20plugins%20are%20required%3F\"><h3>What plugins are required?<\/h3><\/dt>\n<dd><p>WooCommerce. That's it. If you use other GTM plugins (like Google Site Kit), disable their e-commerce features to avoid conflicts.<\/p><\/dd>\n<dt id=\"is%20there%20a%20pro%20version%3F\"><h3>Is there a pro version?<\/h3><\/dt>\n<dd><p>No. Everything is included.<\/p><\/dd>\n<dt id=\"my%20events%20aren%27t%20showing%20in%20meta%20events%20manager.\"><h3>My events aren't showing in Meta Events Manager.<\/h3><\/dt>\n<dd><p>Open the <strong>Event Log<\/strong> tab. If events appear there with \"Success (Meta)\", the plugin is sending \u2014 anything missing on Meta's end is a Pixel ID \/ Access Token mismatch. If the log is empty, your JS optimizer is likely deferring the inline scripts (see next answer) or your CMP auto-blocker converted them to <code>type=\"text\/plain\"<\/code> (see the CMP question below).<\/p><\/dd>\n<dt id=\"js%20optimizer%20%28litespeed%20%2F%20wp%20rocket%20%2F%20autoptimize%29%20%E2%80%94%20what%20do%20i%20configure%3F\"><h3>JS optimizer (LiteSpeed \/ WP Rocket \/ Autoptimize) \u2014 what do I configure?<\/h3><\/dt>\n<dd><p>Add these four IDs to your optimizer's \"exclude from defer \/ combine\" list: <code>mcapi-pageview-init<\/code>, <code>mcapi-viewcontent-events<\/code>, <code>mcapi-viewcategory-events<\/code>, <code>mcapi-frontend-events<\/code>. Cloudflare Rocket Loader is handled automatically via <code>data-cfasync=\"false\"<\/code>.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20a%20block-based%20theme%20%28twenty%20twenty-five%20etc.%29%3F\"><h3>Does it work with a block-based theme (Twenty Twenty-Five etc.)?<\/h3><\/dt>\n<dd><p>Yes.<\/p><\/dd>\n<dt id=\"gtm%20preview%20shows%20my%20browser%20tags%20firing%2C%20but%20the%20plugin%27s%20event%20log%20is%20empty.\"><h3>GTM Preview shows my browser tags firing, but the plugin's Event Log is empty.<\/h3><\/dt>\n<dd><p>Your CMP's auto-blocker is converting the plugin's inline scripts to <code>type=\"text\/plain\"<\/code>. The plugin already carries opt-out attributes for Cookiebot, CookieYes, and Complianz; less common CMPs (OneTrust etc.) need the <code>mcapi_inline_script_attrs<\/code> filter \u2014 see <strong>CMP Auto-Blocking<\/strong> in Advanced Configuration.<\/p><\/dd>\n<dt id=\"i%20sell%20subscriptions%20%E2%80%94%20meta%20is%20over-attributing%20renewals%20to%20old%20ads.\"><h3>I sell subscriptions \u2014 Meta is over-attributing renewals to old ads.<\/h3><\/dt>\n<dd><p>The plugin auto-detects WooCommerce Subscriptions and offers four behavior modes (Default \/ Skip \/ Tag \/ Subscribe + SubscriptionRenewal). Pick Skip or the dedicated-events mode to keep <code>Purchase<\/code> clean. See <strong>WooCommerce Subscriptions<\/strong> in Advanced Configuration.<\/p><\/dd>\n<dt id=\"eu%20traffic%20%E2%80%94%20does%20the%20plugin%20respect%20cookie-banner%20consent%20for%20capi%3F\"><h3>EU traffic \u2014 does the plugin respect cookie-banner consent for CAPI?<\/h3><\/dt>\n<dd><p>Not by default \u2014 server-side CAPI fires from PHP, doesn't see your <code>gtag('consent', ...)<\/code> signals. The Privacy &amp; Consent section has a <strong>Strict server-side consent mode<\/strong> toggle: when consent is denied, hashed PII is stripped from the CAPI payload but the event still ships with its <code>event_id<\/code>, so Meta's browser\u2194CAPI dedup keeps working without identifying data. Recommended ON for EU stores. See <strong>Strict server-side consent mode<\/strong> in Advanced Configuration.<\/p><\/dd>\n<dt id=\"will%20the%20datacenter%20ip%20filter%20block%20my%20real%20vpn%20customers%3F\"><h3>Will the datacenter IP filter block my real VPN customers?<\/h3><\/dt>\n<dd><p>Rarely. Visitors with click IDs (fbclid \/ gclid \/ ttclid), Apple Private Relay IPs, logged-in customers, or prior-visit <code>_fbp<\/code> \/ <code>_ga<\/code> cookies all bypass the filter. Purchase events are never blocked. A brand-new VPN visitor with no cookies has their first PageView held; if they purchase, the full funnel is replayed so Meta sees the complete journey. Every blocked request is auditable in the <strong>Excluded Traffic<\/strong> tab.<\/p><\/dd>\n<dt id=\"why%20does%20the%20excluded%20traffic%20tab%20show%20ips%20as%20%60192.168.1.x%60%3F\"><h3>Why does the Excluded Traffic tab show IPs as `192.168.1.x`?<\/h3><\/dt>\n<dd><p>GDPR-friendly auditing \u2014 the last octet is masked at record-time, so wp-admin and DB exports never reveal raw visitor IPs.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>3.7.0<\/h4>\n\n<ul>\n<li><strong>Event Log: By-IP grouped view.<\/strong> New toggle on the Event Log tab switches between detail rows and a per-IP aggregate (<code>IP | Events | User Agent | Event types | Action<\/code>) sorted by hit count descending. Repeat-offender IPs surface immediately \u2014 bulk-exclude with one click instead of scrolling through hundreds of individual rows. Filter form preserves the active view + page anchor on submit.<\/li>\n<li><strong>Customer-protection badges in the Event Log.<\/strong> Before excluding an IP, the plugin checks for real-visitor signals: Purchase events (financial transaction \u2014 bots can't complete a real checkout), checkout-flow events (InitiateCheckout \/ AddShippingInfo \/ AddPaymentInfo), behavioral filter graduation, and funnel-event diversity. Multi-signal scoring: a Purchase alone qualifies, otherwise 2+ signals are required. Real buyers show a \ud83d\uded2 Customer badge and the Exclude button is suppressed; if a customer was previously excluded by mistake, a \u26a0\ud83d\uded2 warning appears so you can undo it.<\/li>\n<li><strong>AI-crawler classification (separate from generic bots).<\/strong> GPTBot, ChatGPT-User, OAI-SearchBot, PerplexityBot, ClaudeBot, anthropic-ai, Google-Extended, GoogleOther, Applebot-Extended, FacebookBot, Amazonbot, CCBot, Bytespider, and other LLM training \/ answer-engine crawlers are now classified as <code>ai_agent<\/code> instead of <code>bot<\/code>. Requests to <code>\/.well-known\/<\/code> discovery endpoints (UCP \/ llms.txt \/ ai-plugin.json) are also treated as AI agents. They are skipped from CAPI dispatch like bots, but tracked in a separate daily counter on the Dashboard widget so you can see how much LLM-driven traffic reaches your store. Never added to the IP exclusion list. Extendable via the <code>mcapi_ai_agent_user_agents<\/code> filter.<\/li>\n<li><strong>\"Block\" \u2192 \"Exclude\" UI rename.<\/strong> The Blocked Traffic tab is now Excluded Traffic, the exclusion-list buttons are clearer, and a banner at the top of the tab spells out that this is a CAPI-event-level exclusion, not a firewall \u2014 your site stays accessible to everyone, only the plugin's analytics dispatch is filtered for those IPs. Manage-list rows use Disable \/ Enable toggles instead of Exclude \/ Re-include (less terminology collision). Internal hook names and DB option keys unchanged \u2014 backward compatible.<\/li>\n<li><strong>Flagged-IP indicator.<\/strong> IPs that tripped the behavioral filter (honeypot, abnormal velocity, or no engagement after observation) now show a \ud83d\udea9 indicator on the Exclude button with a confidence-aware tooltip. Mostly catches bots that disguised their User Agent to slip past the upstream filter.<\/li>\n<li><strong>EU consent admin notice.<\/strong> When a CMP plugin is detected (CookieYes \/ Cookiebot \/ Complianz \/ Iubenda \/ Termly) and Strict server-side consent mode is OFF, the settings page now shows a one-time dismissable prompt explaining the GDPR posture and pointing to the toggle.<\/li>\n<li><strong>Trademark disclaimer.<\/strong> Added a Disclaimer section to the readme covering independent \/ not-affiliated status for Meta, TikTok, Pinterest, Google, and Automattic \u2014 descriptive interoperability use only.<\/li>\n<li><strong>Schema migration: <code>mcapi_logs.ip_hash<\/code>.<\/strong> New salted-SHA256 column (matches <code>mcapi_ip_state.ip_hash<\/code>) lets the Event Log JOIN against the behavioral-state table for real-time customer \/ flagged classification. Legacy rows have <code>ip_hash=''<\/code> and fall back to event-based signals. Single dbDelta ALTER TABLE on upgrade \u2014 instant DDL on InnoDB 5.7+ \/ MariaDB 10.3+.<\/li>\n<li><strong>Readme cleanup.<\/strong> Cookie-plugin setup, CMP auto-block, Strict consent, and WC Subscriptions sections de-duplicated and condensed. Two-thirds shorter without losing any why-this-matters context.<\/li>\n<li><strong>Google Ads Enhanced Conversions.<\/strong> Bundled GTM template now includes a Google Ads Conversion Linker tag (All Pages) and a Google Ads Purchase Conversion tag (CE - Purchase trigger) with Enhanced Conversions enabled in AUTO mode. The plugin captures <code>gclid<\/code>, <code>gbraid<\/code>, and <code>wbraid<\/code> from ad-click URLs into 1st-party cookies (<code>_mcapi_gclid<\/code> etc.) at landing; the Conversion Linker transfers these to <code>_gcl_aw<\/code> for Google Ads attribution. Recovers conversions that iOS Safari ITP would otherwise drop. Edit two new CONST variables in GTM after importing (<code>Google Ads Conversion ID<\/code>, <code>Google Ads Purchase Label<\/code>) \u2014 see <code>docs\/GTM-MANUAL-SETUP.txt<\/code> for full setup.<\/li>\n<li><strong>Pinterest EMQ improvements.<\/strong> Now captures both Pinterest's persistent <code>_epik<\/code> cookie (set by Pinterest's tag.js on real visitors) and the <code>epik<\/code> URL parameter. Improves Event Match Quality on Pinterest tag installs running the current (2024+) version, where the legacy <code>pina_id<\/code> flow is being phased out.<\/li>\n<li><strong>Stronger real-user signals in datacenter bypass.<\/strong> Beyond <code>_fbp<\/code> and <code>_ga<\/code>, the IP filter now also accepts <code>_epik<\/code> (Pinterest tag), <code>__cf_bm<\/code> (Cloudflare Bot Management actively-validated browsers), <code>_gcl_au<\/code> (gtag.js ran), and <code>_ttp<\/code> (TikTok Pixel) as proof of human browsing. Reduces false-positive blocking of VPN\/Apple-Relay shoppers who already have one of these tag cookies set.<\/li>\n<li><strong>Improved bot \/ human differentiation.<\/strong> Behavioral signals (mousemove, scroll, checkout-form interaction) are now gated against the most common scripted-automation patterns. Combined with the existing datacenter IP filter and funnel-event history, this reduces false-positive bot scores from real shoppers and false-negative human scores from low-effort scrapers. Not a 100% bot block \u2014 it raises the cost for an attacker to look human, not eliminates the possibility \u2014 but it filters out the bulk of the cheap traffic that pollutes Events Manager.<\/li>\n<li><strong>gbraid \/ wbraid capture.<\/strong> Google Ads iOS Safari click variants are now captured into 1st-party cookies alongside <code>gclid<\/code>. Without this, post-ITP iOS Safari ad clicks lose attribution within minutes.<\/li>\n<li><strong>GTM template re-import recommended.<\/strong> The bundled template now includes Google Ads tags. Re-download <code>gtm-template.json<\/code> from Main Settings and re-import in Merge mode.<\/li>\n<\/ul>\n\n<h4>3.6.0<\/h4>\n\n<ul>\n<li><strong>TikTok CAPI integration.<\/strong> 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.<\/li>\n<li><strong>Behavioral bot detection.<\/strong> 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.<\/li>\n<li><strong>Blocklist redesign.<\/strong> 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.<\/li>\n<li><strong>Funnel-chain recovery.<\/strong> Held pre-Purchase events are replayed on the next Purchase from the same visitor (PageView \u2192 ViewContent \u2192 AddToCart \u2192 InitiateCheckout), so Meta sees the full attribution path instead of a lone Purchase.<\/li>\n<li><strong>Apple Private Relay whitelist.<\/strong> Daily-fetched egress IPs bypass the datacenter filter, preserving iOS shopper events.<\/li>\n<li><strong>CCPA \/ Limited Data Use<\/strong> toggle. Honors visitor opt-out via cookie or filter.<\/li>\n<li><strong>Synchronous \/ Asynchronous sending modes.<\/strong> Synchronous (3-second per-platform timeout) for shared hosts where cron is unreliable.<\/li>\n<li><strong>WP Dashboard widget.<\/strong> Queue health at a glance: size, oldest pending age, last successful dispatch, datacenter blocks today.<\/li>\n<li><strong>Per-platform retry.<\/strong> When Meta succeeds but Pinterest or TikTok transiently fails, only the failing platform is retried next cron tick.<\/li>\n<li><strong>Critical fix:<\/strong> queue processor no longer leaks rows when an event's <code>send_to<\/code> targets a platform with no credentials configured. Previously such rows could accumulate indefinitely (tens of thousands over days). Now correctly dropped on the first cycle.<\/li>\n<li><strong>Security:<\/strong> 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 <code>wp_salt('auth')<\/code> for GDPR\/KVKK compliance. Proxy headers trusted only when REMOTE_ADDR is in a known proxy range.<\/li>\n<li><strong>Performance:<\/strong> 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.<\/li>\n<li><strong>Plugin renamed<\/strong> to \"CAPI Suite: Meta, Pinterest, TikTok, GTM\". Settings UI reorganized: Sending Method + Test Modes moved to Event Management tab.<\/li>\n<li><strong>GTM template<\/strong> updated to modern API schema with TikTok Pixel tags. Re-import required.<\/li>\n<\/ul>\n\n<h4>3.5.3<\/h4>\n\n<ul>\n<li>Fix: spurious AJAX <code>add_to_cart<\/code> events from WooCommerce sessionStorage fragment replay.<\/li>\n<li>Fix: per-platform retry tracking \u2014 when one platform transiently fails, only the failing side retries.<\/li>\n<li>New: Event Log captures User Agent, supports date-range filtering, and retention is configurable (1\u201390 days, default 15).<\/li>\n<li>Hardening: third-party autoloader protection extended to all <code>class_exists()<\/code> calls.<\/li>\n<\/ul>\n\n<h4>3.5.2<\/h4>\n\n<ul>\n<li>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.<\/li>\n<\/ul>\n\n<h4>3.5.1<\/h4>\n\n<ul>\n<li>Critical hotfix: CMP detection helper triggered third-party autoloader fatals (CookieYes \/ Cookie Law Info). All detection <code>class_exists()<\/code> calls now pass <code>false<\/code> to suppress autoload.<\/li>\n<\/ul>\n\n<h4>3.5.0<\/h4>\n\n<ul>\n<li>Fix: GTM container template imports cleanly (was rejected with \"Unrecognized value [customEvent]\").<\/li>\n<li>New: Consent Mode v2 support, CMP auto-block exemption (CookieYes \/ Cookiebot \/ Complianz), and a CMP detection admin notice.<\/li>\n<li>New: Strict server-side consent mode \u2014 strips hashed PII when consent denied; still ships <code>event_id<\/code> + non-PII context for dedup.<\/li>\n<li>New: WooCommerce Subscriptions integration \u2014 Subscription Renewal Behavior + customer_status tagging keep Purchase ROAS clean for subscription stores.<\/li>\n<li>Fix: <code>_fbp<\/code> \/ <code>_fbc<\/code> cookie domain strips leading <code>www.<\/code> to match Pixel JS.<\/li>\n<\/ul>\n\n<h4>3.4.2<\/h4>\n\n<ul>\n<li>Fix: GTM template adds two CJS variables converting GA4-schema dataLayer into the <code>contents[]<\/code> shape Meta Pixel and Pinterest Tag expect.<\/li>\n<li>Fix: Pinterest event-name typos in manual setup; correct catalog <code>content_ids<\/code> parameter.<\/li>\n<\/ul>\n\n<h4>3.4.1<\/h4>\n\n<ul>\n<li>Fix: dataLayer items include <code>item_id<\/code> alongside <code>id<\/code> so GA4's Items report no longer shows \"(not set)\" for products.<\/li>\n<\/ul>\n\n<h4>3.4.0<\/h4>\n\n<ul>\n<li>Fix: Event log timestamps stable across hosts with mismatched PHP\/WordPress timezones (stored UTC, displayed via <code>wp_date()<\/code>).<\/li>\n<li>Fix: GTM template no longer fails import with \"Unrecognized value [EVENT]\".<\/li>\n<li>New: bot\/crawler UA filter before queue insert. Purchase events exempt. Filterable via <code>mcapi_is_bot_request<\/code>.<\/li>\n<li>New: Action Scheduler used for recurring tasks when available \u2014 more reliable than WP-Cron on low-traffic sites.<\/li>\n<\/ul>\n\n<h4>3.3.0<\/h4>\n\n<ul>\n<li>New: REST API endpoint <code>\/wp-json\/mcapi\/v1\/event<\/code> for cache-safe browser tracking \u2014 no nonce needed (works behind 7-day page caches). Secured by same-origin, per-IP rate limit, body cap, event whitelist.<\/li>\n<li>Improvement: reliable retries on transient API failures (5xx, 429, network).<\/li>\n<li>Improvement: real client IP via <code>CF-Connecting-IP<\/code> \/ <code>X-Forwarded-For<\/code> \/ <code>X-Real-IP<\/code> (sites behind Cloudflare \/ LB no longer hit rate limits prematurely).<\/li>\n<li>Improvement: Safari ITP bypass \u2014 <code>_fbp<\/code> \/ <code>_fbc<\/code> cookies rewritten server-side with 90-day TTL.<\/li>\n<li>Improvement: phone numbers normalized to E.164 using billing country; <code>external_id<\/code> SHA-256 hashed; cron lock on queue processor; guest external_id is a cookie-backed UUID.<\/li>\n<\/ul>\n\n<p>For older versions (3.2.x and below), see the SVN repository history at https:\/\/plugins.svn.wordpress.org\/easy-meta-capi\/tags\/.<\/p>","raw_excerpt":"Free multi-platform server-side CAPI for Meta, Pinterest, TikTok + GTM dataLayer. Cache-safe, theme-agnostic, no cloud server needed.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/249247","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=249247"}],"author":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/suhanduman"}],"wp:attachment":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=249247"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=249247"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=249247"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=249247"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=249247"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=249247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}