The Problem: Your GA4 Revenue is Missing
You’ve set up GA4 e-commerce tracking on Kajabi. Your begin_checkout events are firing. But your purchase events? Silent. Nothing in GA4.
You check Kajabi — the order is there. The customer paid. But GA4 shows zero revenue.
This is happening to dozens of Kajabi course creators right now. And it’s not because your GA4 setup is wrong.
It’s because Kajabi disconnects Google Tag Manager at the worst possible moment.
The Kajabi Checkout Flow (And Where It Breaks)
Here’s how a Kajabi purchase flow works:
Step 1: Offer Page https://my.yourdomain.com/offers/abc123/checkout GTM: Active ✅ ↓ Step 2: Account Creation Page https://my.yourdomain.com/settings/member_setup GTM: DISCONNECTED ❌ ← This is the problem ↓ Step 3: Thank You / Library Page https://my.yourdomain.com/library GTM: Active ✅
On Step 2, Kajabi completely disconnects Google Tag Manager. Not partially — completely.
This means any data you captured on the checkout page is still there, but GTM has no way to access it or push it to GA4 from the thank you page.
Why This Breaks Standard Purchase Tracking
A typical GTM purchase implementation looks like this:
Approach 1: Capture on Checkout, Read on Thank You Page
Checkout Page:
Tag fires → captures product data → stores it temporarily
Thank You Page:
Tag fires → reads the data → pushes purchase event to GA4
The problem: Where do you store that temporary data?
Most people use:
- dataLayer variables — Lost when GTM disconnects
- Session storage — Can be wiped between navigations
- URL parameters — Kajabi’s redirect strips them
None survive the GTM disconnect on the account creation page.
The Solution: 3 Tag Architecture
There is a way to track Kajabi purchases reliably. It requires a specific architecture that works around the GTM disconnect.
The solution uses browser-level storage (which survives GTM disconnects) combined with a purchase intent flag (which prevents false purchase events on the /library page).
Here’s the concept:
TAG 1 (Checkout Page — Button Click) ├─ Scrapes product data from page UI ├─ Stores in browser-level storage (survives disconnect) └─ Sets a purchase intent flag [GTM DISCONNECTS HERE] [Data and flag still available in browser] TAG 2 (Thank You Page — Page Load) ├─ Reads the stored data ├─ Validates the intent flag ├─ Pushes purchase event to dataLayer TAG 3 (Thank You Page) ├─ Receives the purchase event └─ Sends to GA4
What We’re Solving For
This architecture solves three critical problems:
Problem 1: Data Survives the GTM Disconnect Data is stored at the browser level, not in GTM, so it persists even when GTM disappears.
Problem 2: Coupon & Free Orders Work The validation logic handles $0 prices (100% discount coupons) correctly.
Problem 3: No False Purchase Events An intent flag prevents purchase events from firing when users visit the /library page from their dashboard (which they can do anytime, not just after purchase).
The Implementation Concept
Tag 1 fires on: Pay button click (or equivalent on your checkout)
What it does:
1. Extracts product ID from the URL path
2. Scrapes product name from the page HTML
3. Scrapes product price from the page HTML
4. Stores all three values + a purchase flag
5. Logs to console for testing
Tag 2 fires on: Thank you page load
What it does:
1. Retrieves the stored values
2. Validates all data is present + flag is set
3. Builds a GA4-formatted purchase event
4. Pushes to dataLayer
5. Clears the stored data (prevents duplicates)
The Code Structure (Partial)
Here’s the concept of Tag 1 (the data capture tag):
// Pseudo-code structure — not production ready
(function() {
// Extract product ID from URL
var productId = extractFromURL(); // /offers/{id}/checkout
// Scrape product name and price from HTML elements
var productName = document.querySelector("#offer-title").innerText;
var productPrice = document.querySelector("#offer-price").innerText;
// Store in browser-level storage
store('product_id', productId);
store('product_name', productName);
store('product_price', productPrice);
store('from_checkout', 'true'); // Purchase intent flag
console.log('Data captured and stored');
})();
Tag 2 (the thank you page tag) retrieves and validates:
// Pseudo-code — not production ready
(function() {
var productId = retrieve('product_id');
var productName = retrieve('product_name');
var productPrice = retrieve('product_price');
var intentFlag = retrieve('from_checkout');
// Validation
if (!productId || !productName || !productPrice || !intentFlag) {
console.log('Missing data — event blocked');
return;
}
// If validation passes, build and push the purchase event
var purchaseEvent = {
event: 'purchase',
ecommerce: {
value: productPrice,
currency: 'USD',
items: [{ item_id: productId, item_name: productName, price: productPrice }]
}
};
dataLayer.push(purchaseEvent);
clear_all_stored_data(); // Prevent duplicates
})();
The Critical Implementation Details (That Matter)
There are three specific things that determine whether this actually works:
1. Which browser-level storage mechanism to use There’s a specific type of storage that survives GTM disconnects and Kajabi redirects. Using the wrong one = data loss.
2. The validation logic for $0 prices JavaScript has a quirk where !0 evaluates to true, which breaks validation for free/coupon orders. The fix is one specific function, but it’s easy to get wrong.
3. The purchase intent flag logic The /library page is accessible to all logged-in users anytime. A simple flag isn’t enough — you need a second layer of protection to prevent false events. This is what separates a working setup from one that fires purchase events for dashboard visits.
Why You Can’t Just Copy Paste This
If you try to build this from the pseudo-code above, you’ll run into:
- GTM ES5 validation errors if you use modern JavaScript syntax
- localStorage clearing prematurely if the timing isn’t right
- Duplicate purchase events if the validation doesn’t account for page reloads
- Failed coupon tracking if the price validation uses the wrong conditional
- PayPal orders missing if your trigger doesn’t account for different payment methods
Each of these looks like a small detail until you hit it on a live site and have to debug why purchases aren’t firing.
Testing — How You’ll Know It Works
Once implemented, here’s exactly what you’ll see:
In the browser console (after clicking Pay button):
✅ Data captured and stored
In the browser storage (DevTools → Application → Local Storage):
product_id: "abc123xyz" product_name: "120hr TEFL Course" product_price: "199" from_checkout: "true"
In GA4 DebugView (after completing the full purchase):
Event: purchase
transaction_id: TXN-{timestamp}
value: 199
currency: USD
items: [{item_id: "abc123xyz", item_name: "120hr TEFL Course", ...}]
The PayPal Complication
There’s one more wrinkle: PayPal orders.
PayPal uses its own button (in an iframe), so it doesn’t trigger the standard click event. The solution requires a different approach — hooking into PayPal’s SDK directly.
This is a separate implementation that most tutorials don’t cover.
What Kajabi Doesn’t Tell You
Kajabi’s documentation doesn’t mention the GTM disconnect. Their support will tell you “we don’t officially support custom GA4 tracking” — which means you’re on your own to figure it out.
Most course creators either:
- Give up and assume GA4 tracking on Kajabi is impossible
- Implement it incorrectly and wonder why their data is broken
- Hire a consultant to fix it
Next Steps
If you want to implement this yourself:
You now understand the root cause and the architectural solution. You can research the specific implementation details (which storage mechanism, which validation function, etc.) and build it.
It’s doable, but there are enough gotchas that most people get stuck on one of them.
If you want this implemented correctly:
This is exactly the kind of problem Adflix Consulting specializes in. We’ve built this exact setup on multiple Kajabi accounts, tested it thoroughly, and documented it completely.
We handle:
- The full 3-tag architecture setup
- Coupon and $0 price validation
- PayPal order tracking
- Complete documentation so your team can extend it
- Testing and validation in GA4
If you have questions about your specific setup, or want to discuss whether this is the right approach for your business, let’s talk. Reach out with details about your Kajabi checkout.
Want the complete implementation? Contact Adflix Consulting to discuss your specific setup.
📩 Feel free to reach out:
Book A Call: https://adflix.net/contact/ Email: arafat@adflix.net LinkedIn: https://www.linkedin.com/in/adflixconsulting/ WhatsApp: https://wa.link/w83l5u
