Direct GA4 Integration (No GTM)
Overview
Section titled “Overview”This guide shows how to send Campaign Cart SDK events directly to Google Analytics 4 without using Google Tag Manager by using an event transformer script.
When to Use This
Section titled “When to Use This”Use the GA4 Bridge when:
- You want to send events directly to GA4 without GTM
- You’re already using GA4 and don’t want to set up GTM
- You need simpler setup with fewer moving parts
- You want to avoid GTM’s additional layer
-
Add Google Analytics 4
Add the GA4 tracking code to your page:
<!-- Google Analytics 4 --><script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script><script>window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'G-XXXXXXXXXX');</script>Replace
G-XXXXXXXXXXwith your GA4 Measurement ID. -
Add the Bridge Script
Add the NextDataLayer GA4 Bridge script after the Campaign Cart SDK:
<!-- Campaign Cart SDK --><script src="https://cdn.jsdelivr.net/gh/NextCommerceCo/[email protected]/dist/loader.js" type="module"></script><!-- NextDataLayer GA4 Bridge --><script src="/path/to/NextDataLayer_GA4.js"></script> -
Enable Analytics in SDK Config
window.nextConfig = {apiKey: 'your-api-key',analytics: {enabled: true,mode: 'auto'}};
That’s it! Events will automatically flow from Campaign Cart SDK → NextDataLayer → GA4.
How It Works
Section titled “How It Works”The bridge script:
- Waits for NextDataLayer to be available
- Intercepts events pushed to
window.NextDataLayer - Converts event names from
dl_*format to standard GA4 format - Formats ecommerce data according to GA4 specification
- Pushes to window.dataLayer for GA4 to consume
- Prevents duplicates using event deduplication
- Handles upsells by converting them to purchase events
Event Conversion Flow
Section titled “Event Conversion Flow”Campaign Cart SDK Event ↓NextDataLayer (dl_add_to_cart) ↓GA4 Bridge Script (converts) ↓window.dataLayer (add_to_cart) ↓Google Analytics 4Event Mapping
Section titled “Event Mapping”The bridge automatically converts SDK events to GA4 standard events:
E-commerce Events
Section titled “E-commerce Events”| SDK Event | GA4 Event | Description |
|---|---|---|
dl_view_item | view_item | Product viewed |
dl_view_item_list | view_item_list | Product list viewed |
dl_add_to_cart | add_to_cart | Item added to cart |
dl_remove_from_cart | remove_from_cart | Item removed from cart |
dl_view_cart | view_cart | Cart page viewed |
dl_begin_checkout | begin_checkout | Checkout started |
dl_add_shipping_info | add_shipping_info | Shipping info added |
dl_add_payment_info | add_payment_info | Payment info added |
dl_purchase | purchase | Order completed |
Upsell Events
Section titled “Upsell Events”| SDK Event | GA4 Event | Special Handling |
|---|---|---|
dl_viewed_upsell | view_item | Upsell viewed as product view |
dl_accepted_upsell | purchase | Upsell converted to purchase with same transaction_id |
User Events
Section titled “User Events”| SDK Event | GA4 Event |
|---|---|
dl_sign_up | sign_up |
dl_login | login |
Features
Section titled “Features”1. Duplicate Prevention
Section titled “1. Duplicate Prevention”The bridge tracks processed events and prevents duplicates:
// Events are deduplicated using:// - Event name// - Sequence number// - Item ID// - Order ID2. Upsell Tracking
Section titled “2. Upsell Tracking”Upsells are automatically converted to purchase events with the original transaction ID:
// Original purchase{ event: 'purchase', transaction_id: 'ORD-12345', value: 99.99}
// Upsell (automatically uses same transaction_id){ event: 'purchase', transaction_id: 'ORD-12345', // Same as original! value: 29.99, items: [{ item_category: 'Upsell', ... }]}This allows GA4 to track total order value including upsells.
3. Ecommerce Object Clearing
Section titled “3. Ecommerce Object Clearing”The bridge follows GA4 best practices by clearing the ecommerce object before each event:
// Clear ecommerce firstwindow.dataLayer.push({ ecommerce: null });
// Then push new eventwindow.dataLayer.push({ event: 'add_to_cart', ecommerce: { ... }});4. Memory Management
Section titled “4. Memory Management”Automatically cleans up old data to prevent memory leaks:
- Keeps last 500 processed events
- Keeps last 50 transaction IDs
- Runs cleanup every 60 seconds
5. Debug Mode
Section titled “5. Debug Mode”Debug logging is automatically enabled on:
localhost- URLs with
?debug=true
View logs in browser console:
[GA4 Bridge] Initializing dataLayer bridge[GA4 Bridge] Converted dl_add_to_cart → add_to_cart[GA4 Bridge] Upsell converted to purchase with transaction_id: ORD-12345Bridge API
Section titled “Bridge API”The bridge exposes debugging utilities on window.GA4Bridge:
Get Processed Event Count
Section titled “Get Processed Event Count”const count = window.GA4Bridge.getProcessedCount();console.log(`Processed ${count} events`);View Event Mapping
Section titled “View Event Mapping”const mapping = window.GA4Bridge.getEventMap();console.log(mapping);// {// 'dl_add_to_cart': 'add_to_cart',// 'dl_purchase': 'purchase',// ...// }View Transaction Map
Section titled “View Transaction Map”const transactions = window.GA4Bridge.getTransactionMap();console.log(transactions);// {// '123': { transaction_id: 'ORD-12345', order_number: '12345' },// ...// }Check Bridge Status
Section titled “Check Bridge Status”const isActive = window.GA4Bridge.isActive();console.log(`Bridge active: ${isActive}`);Example Event Flow
Section titled “Example Event Flow”Cart Event
Section titled “Cart Event”SDK fires:
window.NextDataLayer.push({ event: 'dl_add_to_cart', event_id: '1234567890_abc123', ecommerce: { currency: 'USD', value: 99.99, items: [{ item_id: 'SKU-123', item_name: 'Product Name', price: 99.99, quantity: 1 }] }});Bridge converts to:
window.dataLayer.push({ ecommerce: null }); // Clear firstwindow.dataLayer.push({ event: 'add_to_cart', event_id: '1234567890_abc123', ecommerce: { currency: 'USD', value: 99.99, items: [{ item_id: 'SKU-123', item_name: 'Product Name', price: 99.99, quantity: 1 }] }});Purchase Event
Section titled “Purchase Event”SDK fires:
window.NextDataLayer.push({ event: 'dl_purchase', ecommerce: { transaction_id: 'ORD-12345', order_number: '12345', value: 159.99, currency: 'USD', tax: 9.99, shipping: 10.00, items: [...] }});Bridge stores transaction ID and converts to:
window.dataLayer.push({ ecommerce: null });window.dataLayer.push({ event: 'purchase', ecommerce: { transaction_id: 'ORD-12345', order_number: '12345', value: 159.99, currency: 'USD', tax: 9.99, shipping: 10.00, items: [...] }});Upsell Event
Section titled “Upsell Event”SDK fires:
window.NextDataLayer.push({ event: 'dl_accepted_upsell', order_id: '123', upsell: { package_id: 'warranty-extended', package_name: 'Extended Warranty', price: 29.99, quantity: 1 }});Bridge converts to:
window.dataLayer.push({ ecommerce: null });window.dataLayer.push({ event: 'purchase', // Converted to purchase! ecommerce: { transaction_id: 'ORD-12345', // Same as original purchase order_number: '12345', value: 29.99, currency: 'USD', items: [{ item_id: 'warranty-extended', item_name: 'Extended Warranty', price: 29.99, quantity: 1, item_category: 'Upsell' }] }});Troubleshooting
Section titled “Troubleshooting”Events Not Appearing in GA4
Section titled “Events Not Appearing in GA4”-
Check GA4 is loaded
console.log(typeof gtag); // Should be 'function' -
Check bridge is active
console.log(window.GA4Bridge.isActive()); // Should be true -
Check events are being converted
- Open browser console
- Add
?debug=trueto URL - Look for
[GA4 Bridge]log messages
-
Verify NextDataLayer exists
console.log(window.NextDataLayer); // Should be an array
Duplicate Events
Section titled “Duplicate Events”The bridge automatically prevents duplicates, but if you see duplicates:
- Make sure you’re only loading the bridge script once
- Check that you’re not also pushing events to
window.dataLayermanually - Verify the bridge is loaded after the SDK
Upsells Not Tracking
Section titled “Upsells Not Tracking”If upsells aren’t showing up as purchases:
-
Check transaction map
console.log(window.GA4Bridge.getTransactionMap()); -
Verify purchase event fired first
- The initial purchase must fire before upsells
- Transaction ID is stored from the purchase event
-
Check order_id is present
- Upsell events need
order_idto look up transaction_id
- Upsell events need
Missing Transaction IDs
Section titled “Missing Transaction IDs”If upsells show undefined transaction_id:
- The initial
dl_purchaseevent must includeecommerce.transaction_id - The upsell event must include
order_idmatching the purchase - Check the transaction map:
window.GA4Bridge.getTransactionMap()
Performance
Section titled “Performance”The bridge is lightweight and efficient:
- ~5KB minified
- Processes events in <1ms
- Memory-safe with automatic cleanup
- No external dependencies
Comparison: Bridge vs GTM
Section titled “Comparison: Bridge vs GTM”| Feature | GA4 Bridge | Google Tag Manager |
|---|---|---|
| Setup complexity | Simple (1 script) | Complex (container setup) |
| Event conversion | Automatic | Manual triggers/tags |
| Upsell handling | Built-in | Manual configuration |
| Deduplication | Automatic | Must configure |
| Additional tracking | Limited | Unlimited |
| Tag management | None | Full tag management |
| Best for | Direct GA4 | Multiple platforms |
When NOT to Use This
Section titled “When NOT to Use This”Don’t use the GA4 Bridge if:
- You’re already using GTM successfully
- You need to send data to multiple platforms (Facebook, TikTok, etc.)
- You need complex tag management and triggering
- You want to manage tags without code deployments
In these cases, use Google Tag Manager instead. See Google Tag Manager Setup.
Build Your Own Transformer
Section titled “Build Your Own Transformer”Want to adapt this pattern for other platforms (TikTok, Snapchat, Pinterest)?
See Event Transformers for:
- Generic transformer template
- Examples for TikTok, Snapchat, Pinterest
- Multi-platform routing
- Best practices and patterns
Related Documentation
Section titled “Related Documentation”- Event Transformers - General pattern for any platform
- Google Tag Manager Setup - Alternative using GTM
- Analytics Overview - Main analytics documentation
- Event Reference - All available events
- Configuration - SDK configuration options