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:
- Create Custom Event Triggers for:
begin_checkout
add_billing_info
add_shipping_info
add_payment_info
purchase
- Set Trigger Type: Custom Event
- Event Name:
add_billing_info
(and so on)
- Event Name:
🎯 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