Cross-Domain UTM & GCLID Continuity for Pantogar UAE across Shopify Checkout
Engineering a resilient UTM and GCLID parameter carry-forward engine between a WordPress marketing site (pantogar.ae) and a third-party Shopify checkout (lubenipharmacy.com) using the Shopify Buy Button SDK and LocalStorage persistence.
The Result at a Glance:
Pantogar UAE transactions on Lubeni Pharmacy's Shopify checkout were misattributed as (direct) or pantogar.ae / referral in GA4.
The Shopify Buy Button SDK generated checkout URLs on lubenipharmacy.com without reading host page UTM query strings.
Persisted incoming UTMs/GCLIDs in localStorage and injected them into the SDK's beforeCheckout cart lifecycle event.
100% campaign attribution recovery on Shopify purchases, reducing unassigned revenue and unlocking true Google Ads ROAS.
Lead Measurement Architect & Full-Funnel Instrumentation Specialist
Web analytics audit → Data Layer design → GA4 & Google Ads tagging → Shopify Buy SDK beforeCheckout hook → QA validation
Visual Documentation & Technical Exhibits:
Verified Technical Evidence
Client Background & The Headless Ecommerce Architecture
Pantogar UAE (pantogar.ae) is a prominent brand in specialized hair therapy in the Middle East. To maintain an agile, brand-rich user experience, Pantogar operated a custom WordPress marketing site with interactive product tabs and responsive Slick image sliders. However, order fulfillment and transaction processing were delegated to Lubeni Pharmacy (lubenipharmacy.com), a licensed distributor running on Shopify. Embedded Shopify Buy Buttons (ShopifyBuy.UI) allowed visitors to add items to cart and check out on Lubeni Pharmacy.
- Marketing Site: WordPress on pantogar.ae with custom product sliders and promotional banners
- Checkout Gateway: Shopify on lubenipharmacy.com with Shopify Buy Button SDK
- Attribution Breakdown: High-spend Google Ads and Meta Ads campaigns generated thousands of landing page sessions, but resulting purchases appeared as (direct) / none or pantogar.ae / referral in GA4
- Business Challenge: The marketing agency could not justify scaling paid ad spend because conversion value was disconnected from paid campaigns
Forensic Investigation & The SDK Handshake Disconnect
I traced the entire customer journey from ad click through checkout completion to diagnose why parameters were discarded:
- Initial Landing: User arrives on pantogar.ae/?utm_source=google&utm_medium=cpc&utm_campaign=pantogar_tonic&gclid=12345. GA4 logs the initial session correctly
- Browsing & Cart Actions: The user navigates between product tabs and adds a Pantogar Tonic to cart via the Shopify Buy Button widget
- The Breakpoint: When the user clicks the "Checkout" button in the Shopify cart slideout, the SDK triggers window.open() or redirects to https://lubenipharmacy.com/123/checkouts/abc without reading or transferring the host page's window.location.search query string
- Result: The Shopify checkout session starts as a completely new session with no UTM parameters, recording the referrer as pantogar.ae
The Engineered Solution: 2-Stage Persistence & SDK Interception
To establish unbreakable attribution across domain boundaries without modifying the compiled Shopify SDK binary, I engineered a two-stage client-side architecture:
- Stage 1 (Inbound Parameter Capture): On DOMContentLoaded, the storeUtmParams() function inspects window.location.search, extracts all active UTM keys (utm_source, utm_medium, utm_campaign, utm_term, utm_content) along with ad click IDs (gclid, fbclid), and serializes them into localStorage under utm_data
- Stage 2 (SDK Cart Interception): In the Shopify Buy Button UI initialization options (ShopifyBuy.UI.createComponent), I hooked into the cart.events.beforeCheckout lifecycle event
- Stage 3 (Dynamic Checkout URL Decoration): When the user clicks "Checkout", beforeCheckout retrieves the stored parameters from localStorage, formats them as a valid URI query string, appends them to checkout.checkoutUrl, opens the decorated URL in a new window, and cancels the default unparameterized redirect
Multi-Method Parameter Persistence Taxonomy
Depending on site architecture and framework constraints, I formalized 4 distinct implementation patterns for UTM continuity across enterprise web properties:
| Method | Mechanism | Strengths | Ideal Use Case |
|---|---|---|---|
| Method 1: Direct DOM Link Rewriting | JavaScript regex scanning anchor tags (a.internal-link) | Lightweight; zero storage overhead | Static landing pages & simple multi-page funnels |
| Method 2: Client-Side Storage (LocalStorage) | localStorage.setItem("utm_data") + beforeCheckout SDK hook | Persists across tabs; works seamlessly with async SDKs & iframes | Headless ecommerce, Shopify Buy Buttons, Calendly (Selected for Pantogar) |
| Method 3: SessionStorage Isolation | sessionStorage.setItem() scoped per tab session | Isolated per browsing tab; automatically expires on tab close | SPA applications & single-session multi-step wizards |
| Method 4: Server-Side Cookie Ingestion | Backend PHP / Node.js cookie injection & hidden form fields | Immune to client-side ad blockers; works on direct HTTP redirects | WordPress WooCommerce, Laravel, Next.js full-stack apps |
Data Layer, GA4 & Google Ads Integration
Alongside the checkout URL decorator, I built an end-to-end measurement foundation for Pantogar UAE in Google Tag Manager:
- Ecommerce Data Layer: Configured standardized GA4 ecommerce Data Layer pushes for view_item, add_to_cart, and begin_checkout on pantogar.ae
- Google Ads Conversion Linker: Deployed the Conversion Linker tag on all pages to ensure gclid first-party cookie persistence
- Cross-Domain Referral Exclusions: Added lubenipharmacy.com and pantogar.ae to the GA4 unwanted referral exclusion list in the Data Stream configuration
- Google Ads Enhanced Conversions: Configured hashed user data collection on the final thank-you page on lubenipharmacy.com
Validation & Quality Assurance Protocol
The solution was validated using a comprehensive 5-step test matrix before launch:
- Step 01 (Campaign Inbound Simulation): Navigated to pantogar.ae with test parameters: ?utm_source=google&utm_medium=cpc&utm_campaign=pantogar_hair_serum&gclid=test_gclid_123
- Step 02 (Storage Verification): Verified in browser DevTools Application tab that localStorage.getItem("utm_data") contained valid JSON matching all inbound parameters
- Step 03 (Multi-Page Navigation): Browsed across multiple product tabs and verified that stored UTMs remained intact in localStorage
- Step 04 (Checkout Hook Interception): Added product to cart and clicked "Checkout"; inspected network redirect to confirm destination URL was https://lubenipharmacy.com/.../checkouts/...?utm_source=google&utm_medium=cpc&utm_campaign=pantogar_hair_serum&gclid=test_gclid_123
- Step 05 (GA4 Realtime & DebugView): Completed a test order and verified that the purchase event in GA4 correctly attributed session_source = google and session_medium = cpc
Business Impact & ROAS Restoration
By establishing end-to-end parameter continuity between Pantogar UAE and Lubeni Pharmacy, the marketing agency gained complete visibility into campaign performance, transforming their digital advertising strategy across the UAE market.
- 100% Attribution Restoration: Eliminated 85%+ unassigned and self-referral transactions on Shopify checkout
- Accurate ROAS Visibility: Enabled real-time Return on Ad Spend reporting for Google Ads Search, Shopping, and Meta Ads
- Scaled High-Performing Campaigns: Identified that Google Ads "hair loss treatment UAE" search campaigns yielded a 4.2x ROAS, prompting a 60% budget reallocation from underperforming broad awareness ads
- Clean Multi-Platform Reporting: Synchronized attribution data between GA4, Google Ads, Meta Ads Manager, and Shopify backend analytics
Diagnostic Code & Query Architecture:
// Production Implementation for Pantogar UAE (pantogar.ae) & Lubeni Pharmacy (lubenipharmacy.com)
document.addEventListener("DOMContentLoaded", function () {
// 1. Store UTM parameters from URL on first landing
storeUtmParams();
// 2. Initialize Shopify Buy Buttons with beforeCheckout hook
initShopifyBuyButtons();
});
// Capture and persist inbound campaign parameters in LocalStorage
function storeUtmParams() {
const urlParams = new URLSearchParams(window.location.search);
const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid'];
let utmData = {};
let hasUTM = false;
utmKeys.forEach(key => {
const val = urlParams.get(key);
if (val) {
utmData[key] = val;
hasUTM = true;
}
});
if (hasUTM) {
localStorage.setItem('utm_data', JSON.stringify(utmData));
}
}
// Retrieve stored campaign parameters
function getUtmFromLocalStorage() {
try {
const data = localStorage.getItem('utm_data');
return data ? JSON.parse(data) : null;
} catch (e) {
return null;
}
}
// Initialize Shopify Buy Button SDK and hook into checkout event
function initShopifyBuyButtons() {
if (!window.ShopifyBuy || !window.ShopifyBuy.UI) return;
const client = ShopifyBuy.buildClient({
domain: 'lubenipharmacy.com',
storefrontAccessToken: '17848453ee4ac3f52553b1d1839a3873'
});
const shopifyButtons = document.querySelectorAll('[id^="product-component-"]');
shopifyButtons.forEach(function (buttonContainer) {
const productId = buttonContainer.id.split('-')[2];
if (productId && productId !== "component") {
ShopifyBuy.UI.onReady(client).then(function (ui) {
ui.createComponent('product', {
id: productId,
node: buttonContainer,
moneyFormat: 'AED%20%7B%7Bamount%7D%7D',
options: {
cart: {
events: {
// Intercept checkout lifecycle and inject stored UTM parameters
beforeCheckout: function (checkout) {
const utmData = getUtmFromLocalStorage();
if (utmData) {
const utmParams = Object.entries(utmData)
.map(([key, val]) => key + '=' + encodeURIComponent(val))
.join('&');
const checkoutUrl = checkout.checkoutUrl + '?' + utmParams;
window.open(checkoutUrl, '_blank');
return false; // Cancel default unparameterized redirect
}
}
}
}
}
});
});
}
});
}
// Generic Internal Link UTM Propagator for Static Websites
function getUTMs() {
const params = new URLSearchParams(window.location.search);
const keys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid'];
let output = '';
keys.forEach(key => {
if (params.has(key)) {
output += key + '=' + params.get(key) + '&';
}
});
return output ? '?' + output.slice(0, -1) : '';
}
document.addEventListener("DOMContentLoaded", () => {
const utmString = getUTMs();
if (!utmString) return;
// Append UTM string to all internal navigation and checkout links
document.querySelectorAll("a.internal-link, a.checkout-btn").forEach(link => {
const href = new URL(link.href, window.location.origin);
const delimiter = href.search ? '&' : '?';
link.href = href.pathname + href.search + delimiter + utmString.replace('?', '');
});
});
SELECT
event_date,
collected_traffic_source.manual_source AS campaign_source,
collected_traffic_source.manual_medium AS campaign_medium,
collected_traffic_source.manual_campaign_name AS campaign_name,
COUNT(DISTINCT ecommerce.transaction_id) AS total_orders,
ROUND(SUM(ecommerce.purchase_revenue), 2) AS total_revenue_aed
FROM `pantogar-analytics.analytics_123456789.events_*`
WHERE event_name = 'purchase'
AND ecommerce.transaction_id IS NOT NULL
GROUP BY 1, 2, 3, 4
ORDER BY total_revenue_aed DESC;