=== Datalayer Tracking via DATA Reshape for WooCommerce === Contributors: rwky Donate link: https://www.paypal.me/eduardvd Tags: datareshape, first-party-tracking, datalayer-tracking, woocommerce-tracking Requires at least: 6.0 Tested up to: 7.0 Requires PHP: 7.4 WC requires at least: 8.2 WC tested up to: 11.0 Stable tag: 1.0.0 Requires Plugins: woocommerce WC HPOS compatible: yes License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Official WooCommerce integration for DATA Reshape — first-party ecommerce event tracking delivered from your own subdomain. == Description == DATA Reshape for WooCommerce is a bridge between your WooCommerce store and the DATA Reshape platform. It emits structured ecommerce events (`product_viewed`, `product_added_to_cart`, `cart_viewed`, `checkout_started`, `checkout_completed`, plus the mid-funnel checkout steps) into DATA Reshape's `reshape.push()` queue, and DATA Reshape's loader — served from a tracking subdomain you control — handles delivery and routing onward to GA4, Meta, TikTok, and every other destination you have connected. Because the loader is served first-party, events are not blocked by ad blockers, ITP, or the usual third-party-script defences that break conventional `gtag`/`fbq`/`ttq` setups. You do not need to fire those calls in parallel — DATA Reshape routes a single event to every connected destination with the correct platform-specific name and field mapping. This plugin does not replace analytics tools like Google Analytics or Meta Pixel; it replaces the *fragile transport layer* underneath them. Event processing, routing, and deduplication all happen inside DATA Reshape. An active [DATA Reshape](https://datareshape.ro) plan is required to use this plugin. All tracking logic, integrations, and event delivery are managed through the DATA Reshape platform. = Server-side order webhook (API Events) = The "API Events" tab sends a server-to-server order webhook straight from your store to DATA Reshape. It exists to cover what the browser physically can't: off-site payment gateways that confirm the order minutes or hours later (or where the shopper never returns to the thank-you page), and phone/admin-created orders that never had a browser session. The `checkout_completed` webhook uses the order number as its event ID, so DATA Reshape reconciles it with the browser purchase event — if one signal is missing the other fills in, with no double counting. An `order_canceled` event covers cancellations and refunds, and a Test mode validates real order payloads against DATA Reshape's `/test` endpoint before you go live. == Features == = Core Features = - Global enable/disable for the integration - DATA Reshape library integration - Subdomain tracking support - Fully compatible with WooCommerce HPOS (High-Performance Order Storage) = Events = - Product Viewed - Product Added to Cart (AJAX + POST + GET fallbacks) - Product Removed from Cart - Cart Viewed - Checkout Started - Checkout Steps (Billing Address Added, Shipping Detail Added, Payment Method Selected — legacy checkout only) - Checkout Completed - Consent integration — DATA Reshape natively detects most CMPs (Cookiebot, OneTrust, Termly, etc.) and Google Consent Mode v2, with no plugin-side wiring required - Single "Grant consent by default" toggle for stores that don't run a CMP — fires DATA Reshape's native `consent_updated` push at session start so events process immediately - `drswc_consent_payload` filter for stores that want to drive the consent object explicitly from PHP - Plain user data in reshape payloads (DATA Reshape hashes server-side) = API Events (Server-side) = - Server-to-server order webhook to DATA Reshape's `/webhooks/wordpress/event` endpoint - Fires on a configurable order status (default Processing; pick any status your flow reaches, including custom statuses) - Covers off-site gateway returns (confirmed minutes/hours later, or the shopper never returns) and phone/admin orders with no browser session - `checkout_completed` uses the order number as event ID so DATA Reshape deduplicates it against the browser purchase event - `order_canceled` event on Cancelled / Refunded orders - Relays DATA Reshape's first-party `drespa` cookie captured on the order at checkout - Test mode routes payloads to the `/test` validation endpoint and surfaces errors/warnings in the admin - Optional activity log (WooCommerce-native, source `drswc-webhook`) with an in-admin Logs tab for setup debugging - `drswc_webhook_payload` filter to customize the outgoing envelope = Advanced Tracking = - Spec-shaped products with `price_base` + `price`; `tax_included` / `tax_percent` only when WooCommerce tax is enabled - Variations carry `parent_id` / `parent_name` / `parent_sku` / `parent_url` - Order-level and product-level coupons emitted in dedicated `coupons[]` arrays - Shipping methods and payment methods emitted as structured arrays on Checkout Completed - Categories emitted as both `category` (primary) and `categories[]` with `name`+`id` - Stock status, product type, creation timestamp, image, and gallery images = Extensibility = - `drswc_event_payload` — filter the full event envelope before push - `drswc_product_payload` — inject GTIN/MPN/EAN, predicted values, custom properties per product - `drswc_user_payload` — augment user identity (`pre_purchase` or `purchase` source) - `drswc_consent_payload` — replace or inject the consent object - `drswc_webhook_payload` — customize the server-side order webhook envelope = Reliability Enhancements = - Handles non-AJAX add-to-cart flows - Handles redirect-based add-to-cart (?add-to-cart=) - Cache-safe identity hydration — PII never inlined into cacheable HTML - Sticky user identity model (loader caches first-seen user, subsequent events inherit) - Safe execution timing for low overhead == Installation == 1. Upload the plugin to the `/wp-content/plugins/` directory 2. Activate the plugin through the 'Plugins' screen in WordPress 3. Ensure WooCommerce is installed and active 4. Open the settings from either **WooCommerce → Settings → DATA Reshape** or **Marketing → DATA Reshape** (the page lives under WooCommerce Settings; the Marketing entry is a shortcut) 5. Fill in your tracking subdomain and library ID (provided by DATA Reshape), enable the integration, and turn on the events you want emitted == Configuration == = Integration Setup = - Enable Integration (master switch) - Tracking Subdomain (the first-party host serving DATA Reshape's loader) - Library ID - Built-in "Check tracking endpoint" health check - Access token (credential for the API Events order webhook; the webhook reuses your Tracking subdomain and Library ID) = Events = - Master switch for browser-delivered events - Per-event toggles (so events you handle via custom code can be disabled individually) - "Grant consent by default" toggle — off by default (let DATA Reshape auto-detect your CMP / Google Consent Mode); on if you don't run a CMP and want events processed immediately = API Events = - Enable order webhook (server-to-server checkout_completed) - Send order when status becomes … (default Processing; choose the status your payment flow reaches) - Sends order_canceled automatically on Cancelled / Refunded orders - Test mode (validate real payloads against the /test endpoint without delivering to destinations) - Log webhook activity (adds a Logs tab showing WooCommerce's native drswc-webhook logs, scrolled to the latest) - Requires your Tracking subdomain, Library ID, and Access token under Integration setup == Frequently Asked Questions == = Does this plugin support GA4? = Indirectly — events are pushed to DATA Reshape's `window.reshape` queue, and DATA Reshape routes them to GA4 and every other connected destination with the correct platform-specific event name and field mapping. You do not need to fire `gtag`, `fbq`, or `ttq` calls in parallel. = Does it work without AJAX add-to-cart? = Yes. It includes fallback mechanisms for redirect-based add-to-cart flows (native WooCommerce redirect to cart after adding a product). = Does it support the block-based Cart/Checkout? = The plugin's core events (Product Viewed, Add to Cart, Cart Viewed, Checkout Started, Checkout Completed) work on both legacy and block checkouts. The mid-funnel events (Billing Address Added, Shipping Detail Added, Payment Method Selected) currently fire on the legacy (shortcode-based) checkout only — block-based checkout support is planned for a later release. = Does it support server-side event tracking? = Yes — the "API Events" tab sends a server-to-server order webhook to DATA Reshape. It is not a blind CAPI mirror of the browser events; because the tracking library is first-party, browser events already get through reliably. The webhook instead covers what the browser can't: off-site payment gateways that confirm the order later (or where the shopper never returns to the thank-you page) and phone/admin orders with no browser session. DATA Reshape reconciles the webhook with the browser purchase by order number, so the two complement each other without double counting. = Will this slow down my website? = No. The plugin is designed with performance in mind and uses lightweight, conditional execution; if anything, your setup should see a boost in speed compared to classic integrations (Meta, TikTok and Google). = Is deduplication handled? = Deduplication is handled by DATA Reshape. The plugin focuses on exposing accurate and complete data for DATA Reshape to pickup and process onward. == Screenshots == 1. Initial dashboard with general settings (Integration setup tab) 2. Events configuration tab == Changelog == = 1.0.0 = - New: Server-side order webhook (API Events tab). Sends a `checkout_completed` event server-to-server to DATA Reshape when an order reaches a configurable status (default Processing). It covers what the browser can't — off-site payment gateways that confirm minutes or hours later (or where the shopper never returns to the thank-you page) and phone/admin orders that never had a browser session. Uses the order number as the event ID so DATA Reshape deduplicates it against the browser purchase event; if one signal is missing the other fills in, with no double counting. - New: `order_canceled` event sent on Cancelled / Refunded orders. - New: The webhook reuses your existing Tracking subdomain and Library ID; the only new credential is an Access token (the former "API key" field, relabeled). An admin error notice appears if the webhook is enabled without an Access token. - New: Relays DATA Reshape's first-party `drespa` cookie, captured on the order at checkout so it survives gateway callbacks and admin actions. - New: The webhook sends the customer's IP (from the WooCommerce order, which resolves the real visitor IP behind proxies/CDNs such as Cloudflare) so events aren't attributed to the store server. - New: Test mode routes webhooks to DATA Reshape's `/test` validation endpoint (nothing delivered to destinations) and surfaces the returned errors and warnings as an admin notice. - New: Optional "Log webhook activity" toggle records each request and response in the WooCommerce logs (source `drswc-webhook`) and reveals a Logs tab in the settings for setup debugging. - New: `drswc_webhook_payload` filter to customize the outgoing webhook envelope. - New: Staging/local safety guard. If the site address no longer matches where DATA Reshape was set up (e.g. a database copied to a staging or local site), tracking is paused automatically and an admin bar offers to resume live tracking, keep it in test mode (events sent as "dev", not delivered), or dismiss — so a copy can't pollute your production data. - New: A one-time welcome notice after activation prompts you to review every settings tab and configure it as needed. - New: A "Realtime Analytics" tab that opens the DATA Reshape realtime dashboard in a new browser tab. - Change: `stock_status` is now emitted as a string ("in stock" / "out of stock") instead of a boolean, matching DATA Reshape's stored format and avoiding a coercion warning. - Internal: the admin CSS and the static frontend JS were moved out of PHP into real `assets/css` and `assets/js` files, enqueued with the plugin version for cache-busting. No functional change. - Internal: the plugin was reorganized from one large file into a thin bootstrap plus focused trait files under `includes/`. It remains a single class/singleton; no functional change. - Compatibility: tested up to WordPress 7.0 and WooCommerce 11.0. = 0.9.1 = - Fix: Add-to-cart now tracks reliably on stores where another plugin or theme intercepts the product-page button click before the standard handlers can run (volume-discount widgets, bundle plugins, one-click upsells, and similar). - Fix: Add-to-cart no longer silently drops when `/wp-admin/admin-ajax.php` is unreachable (security-plugin allow-lists, expired nonces, ad-blocker rules, network drops). The product-page event payload now ships pre-built with the page, so the push happens synchronously. = 0.9 = - Fix: Add-to-cart now tracks reliably on themes that hijack the single-product form with their own AJAX (Woodmart, custom builders, etc.). A new product-page click handler on the standard `.single_add_to_cart_button` fires the event before the theme's submit logic runs, regardless of which AJAX library or endpoint the theme uses. Built-in 3-second JS dedup prevents double-fire when both this path and the legacy AJAX-listener path would trigger. - Fix: Listing add-to-cart with WooCommerce's "Redirect to cart page after successful addition" option enabled — the `?add-to-cart=` link redirected to the cart page before any client-side hook could fire, so the event was lost. A new server-side `woocommerce_add_to_cart` action hook now stashes the pending event in session so it emits on the cart page after the redirect. - Fix: Variable products on classic (non-AJAX) single-product pages now emit the chosen variation as `products[0].id` instead of the parent product id. The POST capture path was previously ignoring `variation_id`. - Internal: the new server-side hook is intentionally gated on non-AJAX, non-REST, non-admin contexts so AJAX flows (already covered client-side) don't double-fire. = 0.8 = - Consent integration overhauled. The legacy "Google Consent Mode granted by default" toggle (emitted a `gtag('consent', 'update', ...)` block) and the per-event envelope `consent_default_grant` toggle have both been removed. A single new "Grant consent by default" toggle now fires DATA Reshape's native `consent_updated` push at session start — DATA Reshape detects most CMPs and Google Consent Mode v2 on its own, so this toggle defaults to OFF. - Tax fields (`tax_included`, `tax_percent`) are now omitted entirely from product, coupon, and shipping payloads when WooCommerce tax is disabled (previously emitted as `tax_included: false`). - Settings tabs renamed for clarity: "Browser events" → "Events", "Server-side events" → "API Events". The API Events tab is reserved for admin-recorded events (e.g. phone-call orders) and historical customer/order backfill — not a CAPI-style server-side mirror of browser events. - Settings also reachable under Marketing → DATA Reshape (shortcut to the canonical WooCommerce → Settings → DATA Reshape page). - Field labels simplified: "Server-side API endpoint" / "Server-side API key" → "API endpoint" / "API key". - Internal: narrative inline comments moved to CLAUDE.md; no functional impact. = 0.7 = - Hard cutover from `window.dataLayer` to DATA Reshape's `window.reshape` API. Event names updated to the new spec (product_viewed, product_added_to_cart, cart_viewed, checkout_started, checkout_completed, etc.). - Mid-funnel checkout events on legacy checkout: billing_address_added, shipping_detail_added, payment_method_selected. - "Grant consent by default" and "Track checkout steps" toggles added. - Identity emission tightened — `user` object sent only when logged in or in checkout with confirmed contact data. - Variations carry parent_* fields; products emit categories[], stock status, type, created_at, image, gallery. - Pricing decoupled from coupons — `price` / `price_base` are the buyer-visible regular / sale prices; coupons land in dedicated `coupons[]` arrays. - New filters: `drswc_event_payload`, `drswc_product_payload`, `drswc_user_payload`, `drswc_consent_payload`. = 0.6 = - PII cache leak fix extended to cart/checkout pages (in addition to thankyou). - HPOS and Cart/Checkout Blocks compatibility declared. = 0.5 = - Fixed PII leak on page-cached thankyou pages (LiteSpeed et al.) — identity now hydrated client-side from cookies. - Removed browser-side SHA256 hashing — DATA Reshape hashes server-side. - On-save tracking endpoint health check plus on-demand re-check button. - wp.org update-available pill in the settings header. - Loader URL tags the installed plugin version (`&wp=`). = 0.4 = - Fresh-install checkbox defaults flipped to off. - Admin warning notice when the plugin is active but not configured. = 0.3 = - AJAX add-to-cart detection works with third-party plugins (QuadLayers etc.) and themes whose buttons don't expose `data-product_id`. - Removed the in-page dataLayer debug overlay. = 0.1 = - Initial release. == Upgrade Notice == = 1.0.0 = Adds the server-side order webhook under the API Events tab — reliable coverage for off-site payment gateways and phone/admin orders the browser can't capture. Off by default; enable it and add your Access token under Integration setup (the webhook reuses your Tracking subdomain and Library ID). Existing browser tracking is unchanged. Also adds a staging/local safety guard that auto-pauses tracking when a copied database is served from a different address, so test sites can't pollute your production data. = 0.9.1 = Fixes add-to-cart tracking on stores where another plugin or theme intercepts the product-page button click, and on stores where `/wp-admin/admin-ajax.php` is unreachable for any reason. No configuration required. = 0.9 = Fixes three add-to-cart tracking gaps: (a) themes that wrap the single-product submit in their own AJAX (Woodmart, custom builders); (b) listing add-to-cart with the "Redirect to cart page" WooCommerce option enabled; (c) variable products on classic single-product pages now emit the chosen variation instead of the parent. No configuration required. = 0.8 = **Have your technician roll this update out.** It changes the datalayer structure and the consent integration in ways that affect downstream destinations and any custom code reading from `window.reshape` / `window.drswcConsent`. Specifically: the old "Google Consent Mode granted by default" toggle no longer exists — sites that had it on must enable the new "Grant consent by default" toggle (Events tab) if they want events processed without waiting for a CMP signal; otherwise DATA Reshape's native CMP / Google Consent Mode v2 detection takes over. The `tax_included` / `tax_percent` fields are absent entirely (instead of `false`) when WooCommerce tax is disabled. After upgrade, verify in DATA Reshape that events still arrive as expected. = 0.7 = Breaking: migrates from `window.dataLayer` + `wc_*` event names to DATA Reshape's `window.reshape.push()` API with spec-defined names. Custom GTM tags reading the old `wc_*` events from this plugin's dataLayer will need updating. Verify in DATA Reshape that events are arriving after upgrade. = 0.6 = Extends the 0.5 PII cache-leak fix to cart/checkout pages and declares HPOS + Cart/Checkout Blocks compatibility. = 0.5 = Fixes a PII cache leak on page-cached thankyou pages (notably LiteSpeed). Identity is now hydrated client-side from cookies so cached HTML carries no PII. = 0.4 = Fresh-install checkbox defaults flipped to off (existing sites unaffected). Admin warning notice when the integration is active but not configured. = 0.3 = AJAX add-to-cart detection improved (QuadLayers et al.); in-page debug overlay removed. = 0.1 = Initial release.