Passing OpenCart Checkout Events Server-Side for Ads & Analytics Accuracy

Standard

In a privacy-first era of ad tracking and analytics, client-side tracking alone is no longer enough. OpenCart stores often suffer from lost conversion data, especially due to:

  • Cookie restrictions (iOS, browsers)
  • Ad blockers
  • Delayed pixel firing

Server-side tracking of checkout events solves these issues by passing key signals like begin_checkout, add_payment_info, and purchase directly from your server to platforms like Google Ads, GA4, Meta, etc.

โœ… What Youโ€™ll Achieve

Event Tracked Server-Side
begin_checkout Yes
add_payment_info Yes
purchase Yes
Conversion Value Accurate and secure
Email/Phone Hashed PII for matching
Deduplication Using event_id


๐Ÿงฐ Prerequisites

Requirement Notes
OpenCart (3.x / 4.x) Theme + controller access
Web & Server GTM Installed and connected
GA4, Google Ads, Meta Pixel Ready with Measurement ID / Tag ID
HTTPS Domain Required for sending hashed data
Optional: Consent Layer To handle PII lawfully in the EU/US


๐Ÿ“ฆ Step 1: Add Checkout Step Events in Controller

Edit: catalog/controller/checkout/checkout.php

Add a push for begin_checkout when user lands on the checkout page:

$data['ss_begin_checkout'] = json_encode([
'event' => 'begin_checkout',
'event_id' => uniqid('ss_checkout_', true)
]);

Then in checkout.twig, inject:

{% if ss_begin_checkout %}
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({{ ss_begin_checkout|raw }});
</script>
{% endif %}

Repeat similarly in catalog/controller/checkout/confirm.php:

$data['ss_add_payment_info'] = json_encode([
'event' => 'add_payment_info',
'event_id' => uniqid('ss_payment_', true)
]);

And inject into the appropriate confirmation step view template:

{% if ss_add_payment_info %}
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({{ ss_add_payment_info|raw }});
</script>
{% endif %}


๐Ÿงพ Step 2: Finalize purchase Event in success.php

In catalog/controller/checkout/success.php:

$order_id = $this->session->data['order_id'];
$order_info = $this->model_checkout_order->getOrder($order_id);
$products = $this->model_checkout_order->getOrderProducts($order_id);

$email = strtolower(trim($order_info['email']));
$phone = preg_replace('/\D/', '', $order_info['telephone']);

$items = [];
foreach ($products as $product) {
$items[] = [
'item_id' => $product['model'],
'item_name' => $product['name'],
'price' => $product['price'],
'quantity' => $product['quantity']
];
}

$data['ss_purchase'] = json_encode([
'event' => 'purchase',
'transaction_id' => $order_id,
'currency' => $order_info['currency_code'],
'value' => $order_info['total'],
'email' => hash('sha256', $email),
'phone' => hash('sha256', $phone),
'items' => $items,
'event_id' => uniqid('ss_purchase_', true)
]);

In success.twig:

{% if ss_purchase %}
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({{ ss_purchase|raw }});
</script>
{% endif %}


๐Ÿš€ Step 3: Forward Checkout Events to ssGTM

In Web GTM, add a Custom HTML Tag:

<script>
fetch('https://gtm.yourdomain.com/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event_name: '{{DL - event}}',
event_id: '{{DL - event_id}}',
email: '{{DL - email}}',
phone: '{{DL - phone}}',
transaction_id: '{{DL - transaction_id}}',
value: '{{DL - value}}',
currency: '{{DL - currency}}',
items: {{DL - items}}
})
});
</script>

Trigger: All Custom Events matching begin_checkout, add_payment_info, or purchase.


๐Ÿ›ฐ๏ธ Step 4: Setup ssGTM Tags for GA4 & Google Ads

GA4 Event Tag (in Server GTM)

  • Event Name: purchase, begin_checkout, or add_payment_info
  • Measurement ID: From GA4
  • Parameters:
    • event_id, transaction_id, value, currency, items

Google Ads Conversion Tag (Server)

  • Conversion ID / Label
  • Email / Phone (hashed)
  • Event ID
  • Value / Currency / Transaction ID

Deduplication: Use event_id across both web and server tags.


๐Ÿ” Step 5: Optional โ€” Consent Compliance

In Web GTM, conditionally fire fetch tag only if consent is granted using:

if (window.gtag && gtag.get('consent', 'ad_storage') === 'granted') {
// send fetch
}


โœ… Step 6: Testing

Tool Check
GTM Preview Ensure event pushes occur
Server GTM Preview Confirm forwarded data
GA4 DebugView Look for real-time hits
Google Ads Tag Diagnostics Check deduplication
Meta Events Manager (if implemented) For CAPI validation


๐Ÿ“Š Benefits Recap

Feature Benefit
Server-Side Purchase Tracking Higher attribution accuracy
Hashed PII Matches even when cookies fail
Event Deduplication Prevents inflated metrics
Checkout Stage Monitoring Funnel drop-off analysis
Ads Platform Integration Better optimization and ROAS


Leave a Reply

Your email address will not be published. Required fields are marked *