Cross-Domain Tracking in GA4 for OpenCart with Payment Gateway Redirects

Standard

One of the most common pitfalls in eCommerce GA4 setups is loss of attribution due to payment gateway redirects. Platforms like Razorpay, PayPal, CCAvenue, Stripe, etc., often take users offsite and redirect backโ€”causing GA4 to assign the conversion to “referral” or “direct.”

๐Ÿงฐ Prerequisites

Tool Purpose
OpenCart 3.x / 4.x eCommerce platform
GTM Installed Web container across store
GA4 Config Tag With cross-domain support enabled
Payment Gateway URL Known return domain (e.g., razorpay.com)


โš ๏ธ Problem Overview

Before:

  1. User visits OpenCart โ†’ Adds to cart
  2. Goes to Razorpay (redirect)
  3. Returns to /checkout/success
  4. GA4 reports the sale as (referral) / razorpay.com


โœ… Goal

Ensure the GA4 session persists through the redirect so that the original source/medium (e.g., google / cpc) is preserved when the user returns post-payment.


๐Ÿ“ฆ Step 1: Modify GA4 Config Tag in GTM for Cross-Domain Support

In Google Tag Manager:

  1. Open your GA4 Config Tag.
  2. Under Fields to Set, click “Add Row”.

Field Name Value
linker true

  1. Under Cross-Domain Tracking, expand the settings:
    • Check โœ… โ€œEnable linking across domainsโ€
    • Add your gateway domains:

razorpay.com, paypal.com, secure.2checkout.com, stripe.com

These are the domains where users temporarily leave and return.


๐Ÿงฑ Step 2: Modify Outbound Payment Links to Include Linker Parameters

To ensure GA4 passes the gl linker parameter (e.g., _gl=...), decorate outbound links.

In OpenCartโ€™s template or JS files where gateways are invoked (e.g., in Razorpay iframe/JS SDK or form actions):

Option A: Using Auto Linker (preferred)

Add this in the head section of your header.twig:

<script>
window.gtag = window.gtag || function() {};
gtag('set', 'linker', {
'domains': ['razorpay.com', 'paypal.com']
});
</script>


Option B: Manual Linker Injection (if form posts)

If using form redirects, modify your form:

<form id="payment-form" action="https://secure.razorpay.com/checkout" method="POST">
<!-- Fields -->
</form>

<script>
gtag('get', 'GA_MEASUREMENT_ID', 'linker_param', function(linkerParam) {
const form = document.getElementById('payment-form');
if (form) {
form.action += (form.action.includes('?') ? '&' : '?') + linkerParam;
}
});
</script>

Replace GA_MEASUREMENT_ID with your actual GA4 property ID (e.g., G-XXXXXXX).


๐Ÿ›ฌ Step 3: Add Referral Exclusions in GA4

In GA4 Admin:

  1. Go to Data Streams > Web Stream > More Tagging Settings
  2. Click List unwanted referrals
  3. Add domains such as:

razorpay.com
paypal.com
stripe.com

This ensures GA4 doesnโ€™t consider the return from these domains as a new referral.


๐Ÿงช Step 4: Debug and Validate

Use GA4 DebugView:

  • Go to DebugView in GA4 โ†’ Watch the full funnel
  • Validate that source/medium (e.g. google / cpc) persists across redirect

Chrome DevTools:

  • Inspect if _gl= parameter is appended to the redirect URL
  • Use GTM Preview mode to confirm linker settings


๐Ÿง  Pro Tips

Tip Benefit
Use server-side GTM Further hardens attribution on the backend
Send session_id from GA4 Used for BigQuery attribution stitching
Add hidden input for UTM Persist through redirect if needed
GA4 audiences Build segments like โ€œusers who dropped after gateway redirectโ€


๐Ÿงญ Attribution Scenarios Without Cross-Domain Setup

Case Outcome
User comes from Google Ads, converts after Razorpay Shows as referral / razorpay.com unless handled
User from Meta ad returns post-payment Appears as new session, original source lost


๐ŸŽฏ After Setup: What You Unlock

  • Correct source / medium attribution for paid and organic
  • Reliable conversion path reports
  • Lower (direct) and (referral) attribution anomalies
  • Better modeled conversion attribution in GA4 reports


Using GA4 Custom Event Parameters to Track Promo Code Usage in OpenCart

Standard

Promo code tracking is crucial for understanding what drives conversions, repeat purchases, and ROAS efficiency. With GA4 and GTM, you can track promo code usage during checkout in OpenCart using custom event parametersโ€”even without modifying the checkout flow too heavily.

๐Ÿงฐ Prerequisites

Tool/Platform Purpose
OpenCart 3.x or 4.x eCommerce platform
Google Tag Manager Installed sitewide
Google Analytics 4 Configured and linked with GTM
GA4 Admin Access To register custom dimensions


๐ŸŽฏ Goal

Track when a promo code is used in OpenCart, and pass that value to GA4 in the purchase event using a custom event parameter (e.g., promo_code).


๐Ÿ“‹ Step 1: Extract Promo Code from Order (Server-Side)

OpenCart stores the promo/discount code in the order_total table when the coupon is applied. Weโ€™ll expose this to the front-end.

Edit success.twig:

In catalog/view/theme/YOUR_THEME/template/checkout/success.twig, add this snippet where you prepare your purchase event:

<script>
window.dataLayer = window.dataLayer || [];

dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: '{{ order_id }}',
value: {{ total }},
currency: '{{ currency }}',
items: [
{% for product in products %}
{
item_id: '{{ product.product_id }}',
item_name: '{{ product.name }}',
price: '{{ product.price }}',
quantity: '{{ product.quantity }}'
}{% if not loop.last %},{% endif %}
{% endfor %}
],
coupon: '{{ coupon if coupon else "" }}' // This assumes your controller is passing `coupon`
}
});
</script>

โœ… If coupon isnโ€™t available, you can extract it in the success() controller (catalog/controller/checkout/success.php) and pass it to the view:

$data['coupon'] = $this->session->data['coupon'] ?? '';


๐Ÿ› ๏ธ Step 2: Configure Data Layer Variable in GTM

  1. Go to GTM > Variables
  2. Add a new Data Layer Variable
    • Name: DLV - ecommerce.coupon
    • Data Layer Variable Name: ecommerce.coupon

This variable will pick up the promo code value from the purchase dataLayer.


๐Ÿ“จ Step 3: Modify GA4 Purchase Event Tag in GTM

  1. Go to Tags > GA4 Event Tag > purchase
  2. In Event Parameters, add:

Parameter Name Value
coupon {{DLV - ecommerce.coupon}}

  1. Make sure ecommerce object is passed in the GA4 tagโ€™s advanced configuration if using Enhanced Ecommerce-style payloads.


๐Ÿงพ Step 4: Register coupon as a Custom Dimension in GA4

  1. Go to GA4 Admin > Custom Definitions
  2. Click Create Custom Dimension
    • Dimension Name: Coupon Code
    • Scope: Event
    • Event Parameter: coupon

This will enable coupon reporting across GA4 Explorations and Reports.


๐Ÿ” Step 5: QA the Data

Use the following tools to debug:

Tool Use
GTM Preview Mode Check if ecommerce.coupon is set correctly
GA4 DebugView Ensure the coupon parameter appears
Dev Console Run console.log(dataLayer) on thank you page


๐Ÿง  Pro Tips

Tip Benefit
Hash promo codes (optional) Prevent competitor scraping in payloads
Send coupon with add_to_cart too For abandoned cart recovery logic
Use coupon != null in GA4 filters To build promo-based segments
Compare coupon usage vs. AOV Identify discount-based value behavior


๐Ÿ“ˆ Strategic Uses

  • Create GA4 audiences: Users who used SUMMER20 or any code
  • Measure ROAS of specific promos
  • Compare cart abandonment rate of promo vs. non-promo users
  • Trigger remarketing based on coupon behavior


OpenCart Multi-Step Checkout Funnel Tracking with Custom GA4 Events

Standard

Understanding where users drop off during the checkout process is critical to improving conversion rates. OpenCartโ€™s native checkout flow (or even third-party modules like Journal, OnePage Checkout, Quick Checkout) doesnโ€™t track each step by default.

๐Ÿงฐ Prerequisites

Tool / Platform Purpose
OpenCart 3.x or 4.x Your store with a multi-step or tabbed checkout
Google Tag Manager Installed on all pages
GA4 Properly set up with GTM
Consent Management Optional but recommended


๐Ÿงฑ Step 1: Define Your Checkout Steps

Weโ€™ll track each meaningful touchpoint as a custom event in GA4:

Checkout Step GA4 Event Name
Checkout Started begin_checkout
Billing Info Submitted add_billing_info
Shipping Method Selected add_shipping_info
Payment Method Selected add_payment_info
Order Completed purchase

These steps can vary based on your theme or checkout extension (e.g. Journal 3, QuickCheckout, etc.).


๐Ÿ› ๏ธ Step 2: Inject dataLayer.push() Calls into OpenCart Checkout

Option A: OpenCart Default Checkout (AJAX-Based)

Use GTM’s DOM/JS listeners to capture form state changes.

Option B: Modify .twig Templates (more reliable)

A. When Checkout Begins (Cart โ†’ Checkout button click):

In cart.twig or common/header.twig:

<script>
document.querySelector('.btn-checkout')?.addEventListener('click', function() {
window.dataLayer = window.dataLayer || [];
dataLayer.push({ event: 'begin_checkout' });
});
</script>


B. When Billing Info is Completed

In checkout.twig (after billing details form):

<script>
document.querySelector('#button-payment-address')?.addEventListener('click', function() {
dataLayer.push({ event: 'add_billing_info' });
});
</script>


C. When Shipping is Selected

<script>
document.querySelector('#button-shipping-method')?.addEventListener('click', function() {
dataLayer.push({ event: 'add_shipping_info' });
});
</script>


D. When Payment Method is Selected

<script>
document.querySelector('#button-payment-method')?.addEventListener('click', function() {
dataLayer.push({ event: 'add_payment_info' });
});
</script>


E. On Order Confirmation (success.twig)

<script>
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: '{{ order_id }}',
value: {{ total }},
currency: '{{ currency }}',
items: [
{% for product in products %}
{
item_id: '{{ product.product_id }}',
item_name: '{{ product.name }}',
price: '{{ product.price }}',
quantity: '{{ product.quantity }}'
}{% if not loop.last %},{% endif %}
{% endfor %}
]
}
});
</script>


๐Ÿงฐ Step 3: Configure GTM Triggers for Each Event

In GTM:

  1. Create Custom Event Triggers for:
    • begin_checkout
    • add_billing_info
    • add_shipping_info
    • add_payment_info
    • purchase
  2. Set Trigger Type: Custom Event
    • Event Name: add_billing_info (and so on)


๐ŸŽฏ Step 4: Create GA4 Event Tags

Create 4 separate GA4 Event Tags, one per step:

Example: GA4 Tag for add_shipping_info

  • Event Name: add_shipping_info
  • Parameters:
    • checkout_step: 'Shipping'
    • step_number: 3
    • Optionally send user_id, cart_value, products[] if available

Repeat for each of the checkout stages.


๐Ÿ” Step 5: Add Consent-Based Conditions (Optional)

Wrap each dataLayer.push() with:

if (window.Cookiebot && Cookiebot.consents.given.marketing) {
dataLayer.push({ event: 'add_payment_info' });
}

Or use Consent Settings in GTM โ†’ “Require ad_storage” and “analytics_storage”.


๐Ÿงช Step 6: Debug & Validate

Tool Purpose
GTM Preview Mode Confirm dataLayer pushes + tag firing
GA4 DebugView Realtime event monitoring
DevTools Console Inspect dataLayer content + event timing


๐Ÿง  Pro Tips

Tip Reason
Use event_callback in GA4 tags For accurate event sequencing
Send checkout_step parameter Enhances funnel reporting in GA4 Explorations
Include user_id if logged in Enables cross-device attribution
Combine with GA4 funnel path Visualize drop-off rate per stage


๐Ÿ“ˆ Strategic Value

  • Precise funnel drop-off metrics inside GA4
  • CRO prioritization via step-level abandonment rates
  • Privacy-ready tracking with Consent Mode
  • Enables retargeting users who drop off before final step


Implementing First-Party Attribution Tracking in OpenCart Using GTM + GA4

Standard

Traditional client-side tracking increasingly suffers from cookie loss, ITP restrictions, and blocked third-party JavaScript. The solution? Leverage first-party attribution tracking using Google Tag Manager (GTM) and Google Analytics 4 (GA4)โ€”fully powered by your own OpenCart site.

๐Ÿงฐ Prerequisites

Component Description
OpenCart 3.x or 4.x With editable Twig templates
Google Tag Manager Installed across all pages
Google Analytics 4 Setup with active Config Tag
Consent Mode v2 Recommended for legal compliance


๐Ÿ” Goal

  • Capture UTM parameters (source, medium, campaign, content, term)
  • Store them in first-party cookies or localStorage
  • Reuse values on checkout/purchase events
  • Send them to GA4 for accurate attribution


๐Ÿ“ฆ Step 1: Capture & Store UTM Parameters in Cookie/LocalStorage

Add this script to the header of your OpenCart layout (header.twig):

<script>
(function() {
function getParameter(name) {
const match = new RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
let data = {};

utmParams.forEach(function(param) {
const value = getParameter(param);
if (value) {
localStorage.setItem(param, value);
data[param] = value;
}
});

if (Object.keys(data).length) {
console.log('Stored UTM Params:', data);
}
})();
</script>

โœ… This will persist UTM values for future page loadsโ€”even if the user buys 2 days later.


๐Ÿ“‹ Step 2: Read Stored UTM Values into dataLayer

Place this just below the script above (in header.twig or footer.twig):

<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'utm_capture',
utm_source: localStorage.getItem('utm_source') || 'direct',
utm_medium: localStorage.getItem('utm_medium') || 'none',
utm_campaign: localStorage.getItem('utm_campaign') || '(not set)',
utm_content: localStorage.getItem('utm_content') || '',
utm_term: localStorage.getItem('utm_term') || ''
});
</script>

๐Ÿ” This makes UTM values available as Data Layer Variables in GTM.


๐Ÿ›’ Step 3: Inject UTM Values on Purchase Page (success.twig)

In your success.twig file:

<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: '{{ order_id }}',
value: {{ order_total }},
currency: '{{ currency }}',
items: [
{% for product in products %}
{
item_id: '{{ product.product_id }}',
item_name: '{{ product.name }}',
price: '{{ product.price }}',
quantity: '{{ product.quantity }}'
}
{% if not loop.last %},{% endif %}
{% endfor %}
]
},
attribution: {
utm_source: localStorage.getItem('utm_source'),
utm_medium: localStorage.getItem('utm_medium'),
utm_campaign: localStorage.getItem('utm_campaign'),
utm_content: localStorage.getItem('utm_content'),
utm_term: localStorage.getItem('utm_term')
}
});
</script>


๐ŸŽฏ Step 4: Send Attribution Data to GA4 via GTM

In GTM:

  1. Create Variables:
    • DLV - attribution.utm_source
    • DLV - attribution.utm_medium
    • DLV - attribution.utm_campaign
    • DLV - attribution.utm_content
    • DLV - attribution.utm_term
  2. Create GA4 Event Tag (Purchase):
    • Event Name: purchase
    • Parameters:
      • utm_source: {{DLV - attribution.utm_source}}
      • utm_medium: {{DLV - attribution.utm_medium}}
      • utm_campaign: {{DLV - attribution.utm_campaign}}
      • (Include product info via ecommerce object)

โœ… These values will now appear under User Acquisition and Traffic Source in GA4โ€”even if the user bought days after their initial visit.


๐Ÿ” Step 5: Optional โ€“ Respect Consent

Wrap attribution logic inside a consent check:

if (window.Cookiebot && Cookiebot.consents.given.marketing) {
// push dataLayer or store UTM values
}

Or configure GTM tags to require additional consent signals (ad_storage, analytics_storage).


๐Ÿงช Step 6: QA & Debugging

Tool Use Case
GTM Preview Check if UTM values pass into variables
GA4 DebugView Confirm values are attached to events
Network > collect Inspect payloads to GA4 server endpoint
DevTools > Application Confirm localStorage values


๐Ÿง  Pro Tips

Strategy Benefit
Use localStorage (not cookies) Avoids cookie blocking by ITP
Fallback to direct/none Prevents missing attribution
Persist values for 30+ days Extend attribution windows manually
Use in BigQuery exports Analyze attribution across touchpoints


๐Ÿ“ˆ Benefits of First-Party Attribution

  • Survives cross-session journeys
  • Complies with cookie laws & privacy requirements
  • Avoids reliance on 3rd-party cookies (blocked on Safari/Firefox)
  • Empowers GA4โ€™s audience & conversion modeling


TikTok Conversion API Setup via Server-Side GTM for osCommerce

Standard

๐ŸŽฏ Why Use TikTok CAPI?

TikTok Conversion API allows you to:

  • Track conversions even when users block cookies or JavaScript
  • Improve ad performance and ROAS
  • Deduplicate server and browser events with event_id
  • Enable event matching with hashed user data (like email)

๐Ÿงฐ Requirements

Tool Purpose
TikTok Pixel To link browser and server events
TikTok Events API Token For authenticating CAPI requests
Google Tag Manager Web + Server Containers For client-server event flow
Access to osCommerce Inject dataLayer and PHP
Cloud hosting (App Engine or Cloud Run) Host sGTM

๐Ÿงฑ Step-by-Step Implementation


๐Ÿ”น 1. Create TikTok Events API Access

  1. Go to TikTok Events Manager
  2. Select your Pixel
  3. Click on โ€œSet up manually via Events APIโ€
  4. Note down:
    • Access Token
    • Pixel ID

๐Ÿ”น 2. Set Up GTM Server Container (if not already done)

  • Create Server container in GTM
  • Deploy to GCP:
gcloud app deploy

Note your endpoint: https://gtm.yourstore.com

๐Ÿ”น 3. Inject Purchase Data into dataLayer in checkout_success.php

<?php
$order_query = tep_db_query("SELECT orders_id, order_total, customers_email_address FROM " . TABLE_ORDERS . " WHERE customers_id = '" . (int)$customer_id . "' ORDER BY orders_id DESC LIMIT 1");
$order = tep_db_fetch_array($order_query);
$order_id = $order['orders_id'];
$order_total = $order['order_total'];
$customer_email = $order['customers_email_address'];
$event_id = bin2hex(random_bytes(16));
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
  event: 'purchase',
  transaction_id: '<?= $order_id ?>',
  value: <?= $order_total ?>,
  currency: 'USD',
  email: '<?= $customer_email ?>',
  event_id: '<?= $event_id ?>'
});
</script>

๐Ÿ”น 4. GTM Web Container โ€“ HTTP Request Tag to Server

a. Trigger:

  • Custom Event = purchase

b. Tag Type: HTTP Request

  • URL: https://gtm.yourstore.com/collect
  • Method: POST
  • Body:
{
"event_name": "Purchase",
"event_id": "{{DLV - event_id}}",
"transaction_id": "{{DLV - transaction_id}}",
"value": {{DLV - value}},
"currency": "{{DLV - currency}}",
"email": "{{DLV - email}}",
"user_agent": "{{User-Agent}}",
"ip_override": "{{Client IP}}"
}

๐Ÿ”น 5. GTM Server Container โ€“ TikTok CAPI Tag

a. Variables Needed in sGTM:

  • event_name
  • event_id
  • transaction_id
  • value
  • currency
  • email
  • user_agent
  • ip_override

b. Create Custom Template for TikTok CAPI in sGTM

const sendHttpRequest = require('sendHttpRequest');
const log = require('logToConsole');
const JSON = require('JSON');

// TikTok Pixel Info
const access_token = 'YOUR_TIKTOK_ACCESS_TOKEN';
const pixel_id = 'YOUR_TIKTOK_PIXEL_ID';

// Gather Event Data
const payload = {
  pixel_code: pixel_id,
  event: data.event_name,
  event_id: data.event_id,
  timestamp: new Date().toISOString(),
  context: {
    ad: {},
    page: {},
    user: {
      email: [sha256(data.email.trim().toLowerCase())],
      ip: data.ip_override,
      user_agent: data.user_agent
    }
  },
  properties: {
    value: data.value,
    currency: data.currency,
    order_id: data.transaction_id
  }
};

// Send to TikTok CAPI
sendHttpRequest(
  'https://business-api.tiktok.com/open_api/v1.2/pixel/track/',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Access-Token': access_token
    }
  },
  JSON.stringify(payload)
);

log("โœ… TikTok CAPI Event Sent: " + data.event_name);

๐Ÿ”น 6. Add SHA256 Email Hashing Utility

If your template doesnโ€™t support built-in hashing, add:

function sha256(str) {
  return Utilities.computeDigest(
    Utilities.DigestAlgorithm.SHA_256,
    str,
    Utilities.Charset.UTF_8
  ).map(b => ('0' + (b & 0xFF).toString(16)).slice(-2)).join('');
}

๐Ÿ”น 7. Validate CAPI Events

  1. Go to TikTok Ads Manager > Events Manager
  2. Select your Pixel
  3. Go to Test Events
  4. Trigger a test purchase on your site
  5. Look for event_id and verify matched events

๐Ÿง  Best Practices for Attribution Accuracy

Technique Description
๐Ÿ” Use event_id Deduplicate between browser & CAPI
๐Ÿ” Hash PII Hash email addresses with SHA256
๐Ÿ“ก Include IP/User Agent Boost event match quality
๐ŸŽฏ Use consistent Pixel ID Link all data to the same source
โœ… Fire events only on confirmed orders Prevent false tracking

๐Ÿ”„ Optional: Add Client-Side Pixel Tag for Deduplication

In GTM Web:

<script>
ttq.track('CompletePayment', {
value: {{DLV - value}},
currency: '{{DLV - currency}}',
order_id: '{{DLV - transaction_id}}',
event_id: '{{DLV - event_id}}'
});
</script>

Both Pixel and CAPI will send the same event_id, allowing TikTok to deduplicate automatically.


โœ… Summary

Step Action
1 Get TikTok Pixel ID + Access Token
2 Add dataLayer to osCommerce
3 Fire Pixel + forward data to sGTM
4 Send deduplicated events via TikTok CAPI
5 Hash emails, include IP & user agent
6 Validate in TikTok Events Manager

TikTok Pixel Implementation for osCommerce with Event Matching

Standard

TikTok Ads can drive massive traffic, but without precise tracking, conversions and remarketing opportunities are lost. This guide walks you through installing the TikTok Pixel with event matching in osCommerce using GTM.


โœ… Why Use Event Matching?

TikTokโ€™s Advanced Matching uses hashed personal identifiers (like email) to:

  • Improve conversion attribution
  • Recover conversions lost due to cookie blockers
  • Enhance audience building

๐Ÿ”ง Tools Required

Tool Purpose
TikTok Pixel Track user actions
GTM Web Manage tracking tags
osCommerce Access Inject dataLayer + templates
TikTok Ads Manager Create events + get Pixel ID
TikTok Pixel Helper Debug implementation

๐Ÿงฑ Step-by-Step Implementation


๐Ÿ”น 1. Create a TikTok Pixel

  1. Log in to TikTok Ads Manager
  2. Go to Assets > Event > Website Pixel
  3. Click Create Pixel
  4. Choose โ€œManually install Pixel codeโ€
  5. Copy your Pixel ID

๐Ÿ”น 2. Add GTM to osCommerce

Add GTM script in:

  • Header: includes/template_top.php
  • Body: Insert noscript GTM snippet right after <body>

๐Ÿ”น 3. Add TikTok Pixel Base Code in GTM

a. Tag Configuration

  • Tag Type: Custom HTML
  • Trigger: All Pages

b. HTML Code

<script>
!function (w, d, t) {
w.TiktokAnalyticsObject = t;
var ttq = w[t] = w[t] || [];
ttq.methods = ["page", "track", "identify", "instances", "debug", "on", "off", "once", "ready", "alias", "group", "enableCookie", "disableCookie"],
ttq.setAndDefer = function (t, e) {
t[e] = function () {
t.push([e].concat(Array.prototype.slice.call(arguments, 0)))
}
};
for (var i = 0; i < ttq.methods.length; i++) ttq.setAndDefer(ttq, ttq.methods[i]);
ttq.instance = function (t) {
var e = ttq._i[t] || [];
for (var n = 0; n < ttq.methods.length; n++) ttq.setAndDefer(e, ttq.methods[n]);
return e
};
ttq.load = function (e, n) {
var i = "https://analytics.tiktok.com/i18n/pixel/events.js";
ttq._i = ttq._i || {}, ttq._i[e] = [], ttq._i[e]._u = i, ttq._t = ttq._t || {}, ttq._t[e] = +new Date,
ttq._o = ttq._o || {}, ttq._o[e] = n || {};
var o = document.createElement("script");
o.type = "text/javascript", o.async = !0, o.src = i + "?sdkid=" + e + "&lib=" + t;
var a = document.getElementsByTagName("script")[0];
a.parentNode.insertBefore(o, a)
};

ttq.load('YOUR_PIXEL_ID');
ttq.page();
}(window, document, 'ttq');
</script>

Replace YOUR_PIXEL_ID with your TikTok Pixel ID.


๐Ÿ”น 4. Push AddToCart Event from osCommerce

File: product_info.php

Find the form used for “Add to Cart” and inject the following script before </body>:

<?php
$product_id = $_GET['products_id'];
$product_query = tep_db_query("SELECT products_name, products_price FROM " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p WHERE pd.products_id = p.products_id AND pd.language_id = '" . (int)$languages_id . "' AND p.products_id = '" . (int)$product_id . "'");
$product = tep_db_fetch_array($product_query);
?>
<script>
document.querySelector('form[name="cart_quantity"]').addEventListener('submit', function () {
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'add_to_cart',
tiktok_event_data: {
content_id: '<?= $product_id ?>',
content_name: '<?= addslashes($product['products_name']) ?>',
value: <?= $product['products_price'] ?>,
currency: 'USD'
}
});
});
</script>

๐Ÿ”น 5. Trigger TikTok AddToCart Tag in GTM

a. Trigger:

  • Type: Custom Event
  • Event name: add_to_cart

b. Tag: Custom HTML

<script>
ttq.track('AddToCart', {
  content_id: '{{DLV - tiktok_event_data.content_id}}',
  content_name: '{{DLV - tiktok_event_data.content_name}}',
  value: {{DLV - tiktok_event_data.value}},
  currency: '{{DLV - tiktok_event_data.currency}}'
});
</script>

๐Ÿ”น 6. Push Purchase + Email to dataLayer in checkout_success.php

<?php
$order_query = tep_db_query("SELECT orders_id, order_total, customers_email_address FROM " . TABLE_ORDERS . " WHERE customers_id = '" . (int)$customer_id . "' ORDER BY orders_id DESC LIMIT 1");
$order = tep_db_fetch_array($order_query);
$order_id = $order['orders_id'];
$order_total = $order['order_total'];
$customer_email = $order['customers_email_address'];
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
  event: 'purchase',
  tiktok_event_data: {
    value: <?= $order_total ?>,
    currency: 'USD',
    order_id: '<?= $order_id ?>',
    email: '<?= $customer_email ?>'
  }
});
</script>

๐Ÿ”น 7. GTM Tag โ€“ TikTok Purchase with Advanced Matching

a. Trigger: Custom Event = purchase

b. Tag Code:

<script>
function sha256(str) {
  return crypto.subtle.digest("SHA-256", new TextEncoder().encode(str))
    .then(hash => {
      return Array.from(new Uint8Array(hash))
        .map(b => b.toString(16).padStart(2, '0')).join('');
    });
}

sha256('{{DLV - tiktok_event_data.email}}').then(function(hashedEmail) {
  ttq.track('CompletePayment', {
    value: {{DLV - tiktok_event_data.value}},
    currency: '{{DLV - tiktok_event_data.currency}}',
    order_id: '{{DLV - tiktok_event_data.order_id}}',
    email: hashedEmail
  });
});
</script>

โœ… This sends a CompletePayment event with hashed email and order details for improved attribution.


๐Ÿ” Testing & Validation

  1. Use the TikTok Pixel Helper (Chrome Extension)
  2. Go to TikTok Events Manager > Test Events
  3. Verify:
    • PageView, AddToCart, and CompletePayment fire
    • Events contain matching values and hashed email

๐Ÿ” Privacy & Consent

  • Hash personal data (like emails) before sending to TikTok
  • Integrate Consent Mode or a Cookie Banner (optional but recommended)
  • Respect CCPA/GDPR guidelines if applicable

๐Ÿ” Bonus: Upgrade to TikTok Events API (Server-Side)

For even more accurate attribution:

  • Send events via TikTok Events API from GTM Server container
  • Use event_id to deduplicate with pixel events

Let me know if you want a server-side version next.


โœ… Summary

Step Description
1 Install TikTok Pixel via GTM
2 Inject AddToCart + Purchase data into dataLayer
3 Create GTM Tags for each event
4 Include event matching using email hashing
5 Test with TikTok Pixel Helper

Adobe Analytics Tracking Implementation for OpenCart via GTM and Direct Code

Standard

Integrating Adobe Analytics (AA) with OpenCart can be a powerful way to unlock deep behavioral insights, including cart flow, product engagement, and conversion attribution. This guide provides two methods to implement Adobe Analytics in OpenCart:

  1. Using Google Tag Manager (GTM)
  2. Using Direct Code Injection (fallback or parallel setup)

Weโ€™ll cover tracking essentials: page views, product views, cart actions, checkout events, and purchasesโ€”along with eVars, props, and events.


๐Ÿงฐ Prerequisites

Requirement Purpose
OpenCart 3.x or 4.x Your eCommerce platform
Adobe Analytics Suite With Report Suite & RSID
GTM Installed For scalable tag-based deployment
Adobe Launch (optional) Tag management by Adobe


๐Ÿ“ฆ Step 1: Define Data Layer in OpenCart

Design a clean dataLayer so GTM or direct scripts can use structured data.

Example – Add this to product.twig:

<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'view_item',
ecommerce: {
item_id: '{{ product_id }}',
item_name: '{{ heading_title }}',
item_category: '{{ category }}',
price: {{ price }}
},
user: {
logged_in: {{ customer_id ? 'true' : 'false' }},
customer_id: '{{ customer_id }}'
},
page: {
page_type: 'product',
page_title: '{{ heading_title }}'
}
});
</script>

Repeat similarly for:

  • Cart page: add_to_cart
  • Checkout: begin_checkout
  • Success page: purchase


๐Ÿ“ฅ Step 2: Install Adobe Analytics via GTM

A. Create Adobe Analytics Tag in GTM

  1. Go to Tags > New
  2. Choose Custom HTML
  3. Insert your AppMeasurement.js (you can also host it externally)

<script src="https://assets.adobedtm.com/YOUR_APPMEASUREMENT.js"></script>
<script>
var s = s_gi("YOUR_RSID"); // Replace with Report Suite ID
s.pageName = '{{DL - page.page_title}}';
s.channel = 'OpenCart';
s.prop1 = '{{DL - page.page_type}}';
s.eVar1 = '{{DL - ecommerce.item_name}}';

if ('{{DL - event}}' === 'view_item') {
s.events = 'prodView';
}

s.t(); // Send tracking call
</script>

  1. Set Trigger: Page View or Event (e.g., view_item)

Optional: Use Adobe Launch container in GTM instead

  • Add <script src="https://assets.adobedtm.com/launch-XYZ.min.js"></script> in GTM tag
  • Use Adobe Rules inside Launch to define triggers and data mapping


๐Ÿ”Œ Step 3: Direct Code Injection (Without GTM)

For environments without GTM, insert tracking code directly in Twig templates.

A. Product Page (product.twig)

<script src="https://assets.adobedtm.com/YOUR_APPMEASUREMENT.js"></script>
<script>
var s = s_gi("YOUR_RSID");
s.pageName = "{{ heading_title }}";
s.channel = "product";
s.eVar1 = "{{ product_id }}";
s.events = "prodView";
s.t();
</script>

B. Order Confirmation (success.twig)

<script>
var s = s_gi("YOUR_RSID");
s.pageName = "Order Confirmation";
s.purchaseID = "{{ order_id }}";
s.events = "purchase";
s.products = "{{ product_id }};{{ price }};1";
s.eVar10 = "{{ email | sha256 }}"; // Optional: hashed
s.t();
</script>


๐Ÿ“‹ Step 4: Recommended eVars, Props, and Events

Variable Description
eVar1 Product ID
eVar10 Hashed Email (optional)
prop1 Page Type
prop5 Cart Action
events prodView, scAdd, purchase

You must pre-configure these in your Adobe Admin console.


๐Ÿ” Step 5: Consent-Aware Tag Firing (GTM)

If using a Consent Management Platform (CMP), wrap Adobe firing inside a conditional block:

<script>
if (window.Cookiebot && Cookiebot.consents.given.marketing) {
var s = s_gi("YOUR_RSID");
s.pageName = 'Consent-Based Page';
s.events = 'eventX';
s.t();
}
</script>

Or configure GTM Tag Consent Settings for "ad_storage" and "analytics_storage".


๐Ÿงช Step 6: Debugging Tools

Tool Use Case
Adobe Debugger Chrome Extension See real-time beacon activity
Network Tab Look for requests to b/ss/ URLs
Adobe Experience Platform Debugger End-to-end Launch debugging


๐Ÿง  Pro Tips

  • Use product string format in s.products:
    ";productID;price;quantity;eVar;event"
  • Consider using s.linkTrackVars and s.linkTrackEvents for click tracking
  • Use s.clearVars() to prevent data leakage between pages
  • Hash PII client-side before sending (e.g., email, phone)


๐Ÿ“ˆ Strategic Benefits

  • Granular visibility into product-level interactions
  • Marketing channel attribution via eVars
  • Cart abandonment and checkout funnel insight
  • Future-ready for Adobe CJA integration


Improving Attribution Accuracy for Facebook Ads in osCommerce

Standard

๐ŸŽฏ Objective

Enhance attribution accuracy by:

  • Combining Meta Pixel and CAPI
  • Implementing event_id-based deduplication
  • Capturing richer user data (email, IP, user agent)
  • Mitigating data loss from iOS, ad blockers, and browser restrictions

โœ… Tools & Requirements

Tool Purpose
Facebook Pixel & Business Manager Campaigns & tracking
Facebook Conversions API Access Token For server-side events
Google Tag Manager (Web + Server) Event forwarding & CAPI
osCommerce access Inject dataLayer, product/order data
Cloud Hosting (GCP recommended) Host sGTM

๐Ÿ”ง Implementation Plan

  1. Install GTM Web + Server on osCommerce
  2. Fire Meta Pixel events via GTM Web
  3. Push purchase and lead data into dataLayer
  4. Forward data to sGTM
  5. Send deduplicated events via Facebook CAPI
  6. Add SHA256 email hashing
  7. Validate attribution using Meta Events Manager

๐Ÿงฑ Step-by-Step Implementation


๐Ÿ”น 1. Add GTM Web & Server in osCommerce

a. GTM Web Container

Insert into:

  • <head>: includes/template_top.php
  • <body>: noscript iframe version

b. GTM Server Container

  • Create in GTM
  • Deploy via GCP App Engine or Cloud Run:
gcloud app deploy
  • Save endpoint: https://gtm.yourstore.com

๐Ÿ”น 2. Inject Purchase Data with event_id in checkout_success.php

<?php
$order_query = tep_db_query("SELECT orders_id, order_total, customers_email_address FROM " . TABLE_ORDERS . " WHERE customers_id = '" . (int)$customer_id . "' ORDER BY orders_id DESC LIMIT 1");
$order = tep_db_fetch_array($order_query);
$order_id = $order['orders_id'];
$order_total = $order['order_total'];
$customer_email = $order['customers_email_address'];
$event_id = bin2hex(random_bytes(16)); // Unique event ID
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'purchase',
transaction_id: '<?= $order_id ?>',
value: <?= $order_total ?>,
currency: 'USD',
email: '<?= $customer_email ?>',
event_id: '<?= $event_id ?>'
});
</script>

๐Ÿ”น 3. GTM Web โ€“ Meta Pixel Tag (Client-Side)

a. Trigger: Custom Event = purchase

b. Tag Type: Custom HTML

<script>
fbq('track', 'Purchase', {
  value: {{DLV - value}},
  currency: '{{DLV - currency}}',
  eventID: '{{DLV - event_id}}'
});
</script>

๐Ÿ”น 4. GTM Web โ€“ Forward Data to Server GTM

a. Tag: HTTP Request Tag

  • URL: https://gtm.yourstore.com/collect
  • Method: POST
  • Payload:
{
  "event_name": "Purchase",
  "event_id": "{{DLV - event_id}}",
  "transaction_id": "{{DLV - transaction_id}}",
  "value": {{DLV - value}},
  "currency": "{{DLV - currency}}",
  "email": "{{DLV - email}}",
  "user_agent": "{{User-Agent}}",
  "ip_override": "{{Client IP}}"
}

๐Ÿ”น 5. GTM Server โ€“ Facebook CAPI Tag with Deduplication

a. Variables in sGTM:

  • event_name, event_id, transaction_id, value, currency, email, user_agent, ip_override

b. Tag: Custom Template or Custom JavaScript

const sendHttpRequest = require('sendHttpRequest');
const log = require('logToConsole');
const JSON = require('JSON');

const access_token = 'YOUR_FACEBOOK_ACCESS_TOKEN';
const pixel_id = 'YOUR_PIXEL_ID';

const payload = {
data: [{
event_name: data.event_name,
event_time: Math.floor(Date.now() / 1000),
event_id: data.event_id,
action_source: 'website',
user_data: {
em: [sha256(data.email.trim().toLowerCase())],
client_ip_address: data.ip_override,
client_user_agent: data.user_agent
},
custom_data: {
value: data.value,
currency: data.currency,
order_id: data.transaction_id
}
}]
};

sendHttpRequest(
`https://graph.facebook.com/v18.0/${pixel_id}/events?access_token=${access_token}`,
{
method: 'POST',
headers: {'Content-Type': 'application/json'}
},
JSON.stringify(payload)
);

log("โœ… Facebook CAPI Purchase sent");

๐Ÿ”น 6. Add SHA256 Hash Function (Server-Side)

If using a custom template:

function sha256(str) {
return Utilities.computeDigest(
Utilities.DigestAlgorithm.SHA_256,
str,
Utilities.Charset.UTF_8
).map(b => ('0' + (b & 0xFF).toString(16)).slice(-2)).join('');
}

๐Ÿ”น 7. Test Deduplication & Attribution Accuracy

โœ… Tools:

  • Meta Events Manager > Test Events
  • Meta Pixel Helper
  • Confirm:
    • Pixel fires with eventID
    • CAPI fires with same eventID
    • Only one Purchase counted

๐Ÿ“Š Pro Tips to Improve Attribution Accuracy Further

Technique Description
โœ… Use event_id Enables deduplication between Pixel & CAPI
โœ… Send hashed PII Improves user matching
โœ… Use user IP & user agent Boosts signal quality
โœ… Trigger CAPI even when Pixel is blocked Covers privacy-related loss
โœ… Set up Consent Mode Aligns with regulations like GDPR/CCPA

๐Ÿง  Summary

Step Purpose
Inject dataLayer on purchase Capture transaction data
Fire Pixel + send event_id Track client-side events
Forward data to sGTM Trigger server-side tracking
Post to CAPI with hashed data Improve signal quality
Deduplicate using event_id Avoid double counting

OpenCart Data Layer Design Best Practices for Omnichannel Tracking

Standard

An accurate and well-structured data layer is the foundation of successful omnichannel tracking. Whether you’re firing events to GA4, Meta, TikTok, Mixpanel, or server-side platforms, your tracking strategy in OpenCart should begin with a robust, scalable, and privacy-conscious data layer.

๐Ÿ“ฆ What Is the Data Layer?

A data layer is a JavaScript object (typically window.dataLayer) that acts as a central data hub. You can push user interactions, product data, transaction details, and customer identifiers into itโ€”allowing GTM or other tag managers to access them cleanly.


โœ… Why a Structured Data Layer Matters

Benefit Description
Clean Separation Decouples logic from tags/scripts
Platform Flexibility Enables tracking across GA4, Meta, Ads, Mixpanel
Consent Compatibility Works well with delayed or conditional tracking
Debug-Friendly Easier QA using GTM Preview or browser console


๐Ÿงฐ Prerequisites

  • OpenCart 3.x or 4.x
  • GTM installed across all pages
  • Familiarity with .twig templating
  • Basic JS understanding


๐Ÿงฑ Step 1: Design Your Data Layer Blueprint

Hereโ€™s a scalable structure to cover most use cases:

dataLayer.push({
event: 'EVENT_NAME',
ecommerce: {
currency: 'USD',
value: 120.00,
transaction_id: 'ORDER1234',
items: [
{
item_id: 'SKU_123',
item_name: 'Product A',
item_brand: 'BrandX',
item_category: 'Shoes',
item_variant: 'Red / M',
price: 60.00,
quantity: 2
}
]
},
user: {
user_id: '12345',
email_hash: 'hashed@example.com',
logged_in: true
},
page: {
page_type: 'product',
product_id: 'SKU_123'
},
consent: {
marketing: true,
analytics: true
}
});


๐Ÿ›’ Step 2: Implement Data Layer on Key Pages

A. Product Page (product.twig)

<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'view_item',
ecommerce: {
items: [{
item_id: '{{ product_id }}',
item_name: '{{ heading_title }}',
item_category: '{{ category_name }}',
price: {{ price }},
quantity: 1
}]
},
page: {
page_type: 'product',
product_id: '{{ product_id }}'
}
});
</script>


B. Add-to-Cart (catalog/view/theme/.../template/common/cart.twig)

<script>
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
items: [{
item_id: '{{ product_id }}',
item_name: '{{ name }}',
price: {{ price }},
quantity: 1
}]
}
});
</script>


C. Checkout Start (checkout.twig)

<script>
dataLayer.push({
event: 'begin_checkout',
ecommerce: {
value: {{ cart_total }},
items: {{ json_encode(cart_items) }}
}
});
</script>


D. Purchase Confirmation (success.twig)

<script>
dataLayer.push({
event: 'purchase',
ecommerce: {
currency: '{{ currency }}',
value: {{ total }},
transaction_id: '{{ order_id }}',
items: {{ json_encode(order_items) }}
},
user: {
user_id: '{{ customer_id }}',
email_hash: '{{ email | lower | sha256 }}',
logged_in: true
}
});
</script>


๐Ÿ”’ Step 3: Add Consent Logic

Wrap the data layer push with a check to ensure user consent:

if (window.Cookiebot && Cookiebot.consents.given.marketing) {
dataLayer.push({...});
}


๐Ÿ” Step 4: Reuse Variables in GTM

Map variables in GTM:

  • DLV - ecommerce.items[0].item_name
  • DLV - ecommerce.transaction_id
  • DLV - user.email_hash
  • DLV - page.page_type

This makes your GTM setup modular and platform-agnostic.


๐Ÿ”Ž Step 5: Debugging and QA

Use GTM Preview mode and browser DevTools:

console.log(dataLayer);

Check structure, naming, and timing. Avoid:

  • Pushing empty objects
  • Double-pushing same event
  • Invalid JSON inside Twig variables


๐Ÿง  Pro Tips

Tip Explanation
Always push event first Required to trigger GTM tags
Use ecommerce.items[] format Required by GA4 and Google Ads
Hash emails client-side Avoid exposing raw PII in GTM
Include page.page_type For audience segmentation and GA4 dimensions
Version your dataLayer Add dl_version: 1.0.0 for debugging consistency


๐ŸŽฏ Strategic Value

  • Enables omnichannel attribution across ad platforms
  • Clean base for server-side GTM ingestion
  • Reduces dependency on tag-specific code
  • Future-proofs OpenCart for CAPI, consent, GA4 upgrades


Tracking Facebook Add-to-Cart and Initiate Checkout in osCommerce

Standard

๐ŸŽฏ Objective

Enable accurate tracking of AddToCart and InitiateCheckout Facebook Pixel events for:

  • Optimizing Meta ad performance
  • Building remarketing audiences
  • Measuring drop-off before purchase

โœ… Tools & Requirements

Tool Purpose
Facebook Pixel ID For Meta Ads tracking
Google Tag Manager To manage Pixel firing
osCommerce Access Modify templates to inject dataLayer
Chrome Pixel Helper Debug and validate events

๐Ÿงฑ Implementation Plan

  1. Add dataLayer.push() for AddToCart
  2. Add dataLayer.push() for InitiateCheckout
  3. Set up GTM triggers
  4. Configure Facebook Pixel tags
  5. Test with Meta Pixel Helper

๐Ÿ”น Step 1: Inject AddToCart dataLayer in osCommerce

File to edit: /product_info.php

Find the Add to Cart form โ€” typically a form[name="cart_quantity"]

๐Ÿงฉ Add the following code before </body>:

<?php
if (isset($_GET['products_id'])) {
  $product_id = (int)$_GET['products_id'];
  $product_query = tep_db_query("SELECT products_name, products_price FROM " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p WHERE pd.products_id = p.products_id AND pd.language_id = '" . (int)$languages_id . "' AND p.products_id = '" . (int)$product_id . "'");
  $product = tep_db_fetch_array($product_query);
?>
<script>
window.dataLayer = window.dataLayer || [];

document.querySelector('form[name="cart_quantity"]').addEventListener('submit', function() {
  dataLayer.push({
    event: 'add_to_cart',
    ecommerce: {
      content_ids: ['<?= $product_id ?>'],
      content_name: '<?= addslashes($product['products_name']) ?>',
      value: <?= $product['products_price'] ?>,
      currency: 'USD'
    }
  });
});
</script>
<?php } ?>

โœ… This pushes an event into the data layer when a user adds an item to cart.


๐Ÿ”น Step 2: Inject InitiateCheckout dataLayer on Checkout Start Page

File to edit: /checkout_shipping.php (or first step of your checkout flow)

๐Ÿงฉ Add this code at the bottom:

<?php
$cart_total = $cart->show_total(); // Or use your session-based cart total
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
  event: 'initiate_checkout',
  ecommerce: {
    value: <?= $cart_total ?>,
    currency: 'USD'
  }
});
</script>

โœ… This will push the initiate_checkout event when checkout begins.


๐Ÿ”น Step 3: Configure GTM Triggers

๐Ÿ“Œ a. AddToCart Trigger

  • Type: Custom Event
  • Event name: add_to_cart

๐Ÿ“Œ b. InitiateCheckout Trigger

  • Type: Custom Event
  • Event name: initiate_checkout

๐Ÿ”น Step 4: Configure Facebook Pixel Tags in GTM

๐Ÿท๏ธ a. AddToCart Tag

  • Tag Type: Custom HTML
  • Trigger: add_to_cart
<script>
fbq('track', 'AddToCart', {
content_ids: {{DLV - ecommerce.content_ids}},
content_name: '{{DLV - ecommerce.content_name}}',
value: {{DLV - ecommerce.value}},
currency: '{{DLV - ecommerce.currency}}'
});
</script>

๐Ÿท๏ธ b. InitiateCheckout Tag

  • Tag Type: Custom HTML
  • Trigger: initiate_checkout
<script>
fbq('track', 'InitiateCheckout', {
  value: {{DLV - ecommerce.value}},
  currency: '{{DLV - ecommerce.currency}}'
});
</script>

๐Ÿ” Step 5: Debug and Validate

โœ… Use the Facebook Pixel Helper Chrome Extension

  • Visit a product page
  • Click “Add to Cart” and verify AddToCart fires
  • Start checkout and verify InitiateCheckout fires

โœ… Use Facebook Events Manager

  • Go to Test Events
  • Monitor real-time event flows

๐Ÿ’ก Bonus: Send AddToCart via Facebook CAPI (Optional Advanced)

If you use Server-Side GTM, you can forward AddToCart/InitiateCheckout events as server-side events. Include event_id and send it in both Pixel and CAPI calls to enable deduplication.

Let me know if you want a server-side extension of this article.


๐Ÿ” Privacy Best Practices

  • Only push identifiable data with user consent
  • Hash emails or phone numbers when implementing CAPI
  • Use Consent Mode v2 or a cookie banner before firing pixels

โœ… Summary

Feature Implementation
AddToCart Triggered via form submit listener + GTM
InitiateCheckout Fired on checkout start page load
Facebook Pixel Tags Fired using GTM with dynamic values
Validation Meta Pixel Helper + Test Events
Optional Upgrade to server-side tracking with event deduplication