Created
April 17, 2026 20:38
-
-
Save ceaksan/13e1fc9da6c202a7ccbf26f4bbe97198 to your computer and use it in GitHub Desktop.
Shopify Custom Pixel - Multi-Market GA4 and Google Ads tracking with market-specific measurement and conversion IDs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Shopify Custom Pixel - Multi-Market GA4 & Google Ads Tracking | |
| * | |
| * Routes Shopify Customer Events to market-specific GA4 measurement IDs | |
| * and Google Ads conversion IDs based on the market cookie written by | |
| * the market bridge (for storefront events) and the native localization | |
| * object (for checkout events). | |
| * | |
| * Install via: Shopify Admin > Settings > Customer Events > Add custom pixel. | |
| * | |
| * Edit MARKET_CONFIG to match your markets, GA4 properties and | |
| * Google Ads conversion IDs. Handles are expected to match | |
| * localization.market.handle values. | |
| * | |
| * Pairs with: | |
| * - storageHelper: https://gist.github.com/ceaksan/26c8a59aa8a518732a9a40da967d8cd2 | |
| * - market bridge: reads _shopify_m cookie written by the app embed snippet | |
| * | |
| * @see https://ceaksan.com/tr/shopify-multi-market-ga4-google-ads-olcum-id-eslemesi | |
| * @license MIT | |
| */ | |
| // --- MARKET CONFIG --- | |
| var MARKET_CONFIG = { | |
| netherlands: { | |
| ga4: "G-NL00000001", | |
| adsConversionId: "AW-NL0000001", | |
| adsConversionLabel: "nlLabel123", | |
| currency: "EUR", | |
| }, | |
| germany: { | |
| ga4: "G-DE00000001", | |
| adsConversionId: "AW-DE0000001", | |
| adsConversionLabel: "deLabel456", | |
| currency: "EUR", | |
| }, | |
| _default: { | |
| ga4: "G-XX00000001", | |
| adsConversionId: "AW-XX0000001", | |
| adsConversionLabel: "xxLabel000", | |
| currency: "USD", | |
| }, | |
| }; | |
| // Optional country-code fallback map | |
| var MARKET_CONFIG_BY_COUNTRY = { | |
| NL: MARKET_CONFIG.netherlands, | |
| DE: MARKET_CONFIG.germany, | |
| }; | |
| // --- CONSENT (from init, stable for page lifetime) --- | |
| // visitorConsentCollected is a storefront event, not available in pixel sandbox | |
| var consentGranted = init.customerPrivacy.analyticsProcessingAllowed; | |
| // --- MARKET DATA --- | |
| var cachedMarket = null; | |
| var activeConfig = null; | |
| var gtagLoaded = false; | |
| async function getMarketData() { | |
| if (cachedMarket) return cachedMarket; | |
| var raw = await browser.cookie.get("_shopify_m"); | |
| if (raw) { | |
| try { | |
| cachedMarket = JSON.parse(decodeURIComponent(raw)); | |
| return cachedMarket; | |
| } catch (e) { | |
| console.warn("[pixel] Market cookie parse error:", e); | |
| } | |
| } | |
| return null; | |
| } | |
| async function getMarketDataWithRetry(retries) { | |
| retries = retries || 3; | |
| var data = await getMarketData(); | |
| if (data) return data; | |
| for (var i = 0; i < retries; i++) { | |
| await new Promise(function (r) { | |
| setTimeout(r, 150); | |
| }); | |
| cachedMarket = null; | |
| data = await getMarketData(); | |
| if (data) return data; | |
| } | |
| return null; | |
| } | |
| function getConfig(market) { | |
| if (!market) return MARKET_CONFIG._default; | |
| if (market.market && market.market.handle) { | |
| var handle = market.market.handle; | |
| if (MARKET_CONFIG[handle]) return MARKET_CONFIG[handle]; | |
| } | |
| if (market.country && MARKET_CONFIG_BY_COUNTRY[market.country]) { | |
| return MARKET_CONFIG_BY_COUNTRY[market.country]; | |
| } | |
| return MARKET_CONFIG._default; | |
| } | |
| function getConfigFromLocalization(localization) { | |
| if (!localization) return MARKET_CONFIG._default; | |
| if (localization.market && localization.market.handle) { | |
| var handle = localization.market.handle; | |
| if (MARKET_CONFIG[handle]) return MARKET_CONFIG[handle]; | |
| } | |
| if (localization.country && localization.country.isoCode) { | |
| var code = localization.country.isoCode; | |
| if (MARKET_CONFIG_BY_COUNTRY[code]) return MARKET_CONFIG_BY_COUNTRY[code]; | |
| } | |
| return MARKET_CONFIG._default; | |
| } | |
| // --- GTAG --- | |
| function loadGtag(measurementId) { | |
| if (gtagLoaded) return; | |
| var script = document.createElement("script"); | |
| script.src = "https://www.googletagmanager.com/gtag/js?id=" + measurementId; | |
| script.async = true; | |
| document.head.appendChild(script); | |
| window.dataLayer = window.dataLayer || []; | |
| window.gtag = function () { | |
| dataLayer.push(arguments); | |
| }; | |
| gtag("js", new Date()); | |
| gtagLoaded = true; | |
| } | |
| function ensureGtag(config, marketData) { | |
| if (!gtagLoaded) { | |
| loadGtag(config.ga4); | |
| gtag("config", config.ga4, { | |
| send_page_view: false, | |
| market_handle: | |
| marketData && marketData.market ? marketData.market.handle : "unknown", | |
| market_country: marketData ? marketData.country : "unknown", | |
| market_currency: marketData ? marketData.currency : "unknown", | |
| }); | |
| } | |
| } | |
| // --- INIT --- | |
| async function initTracking() { | |
| if (!consentGranted) return; | |
| var market = await getMarketDataWithRetry(); | |
| activeConfig = getConfig(market); | |
| ensureGtag(activeConfig, market); | |
| } | |
| initTracking(); | |
| // --- STOREFRONT EVENTS --- | |
| analytics.subscribe("page_viewed", async function (event) { | |
| if (!consentGranted || !activeConfig) return; | |
| gtag("event", "page_view", { | |
| send_to: activeConfig.ga4, | |
| page_location: event.context.document.location.href, | |
| page_title: event.context.document.title, | |
| page_referrer: event.context.document.referrer, | |
| }); | |
| }); | |
| analytics.subscribe("product_viewed", async function (event) { | |
| if (!consentGranted || !activeConfig) return; | |
| var product = event.data.productVariant; | |
| gtag("event", "view_item", { | |
| send_to: activeConfig.ga4, | |
| currency: product.price.currencyCode, | |
| value: product.price.amount, | |
| items: [ | |
| { | |
| item_id: product.product.id, | |
| item_name: product.product.title, | |
| item_variant: product.title, | |
| price: product.price.amount, | |
| item_brand: product.product.vendor, | |
| item_category: product.product.type, | |
| quantity: 1, | |
| }, | |
| ], | |
| }); | |
| }); | |
| analytics.subscribe("product_added_to_cart", async function (event) { | |
| if (!consentGranted || !activeConfig) return; | |
| var cartLine = event.data.cartLine; | |
| var m = cartLine.merchandise; | |
| gtag("event", "add_to_cart", { | |
| send_to: activeConfig.ga4, | |
| currency: cartLine.cost.totalAmount.currencyCode, | |
| value: cartLine.cost.totalAmount.amount, | |
| items: [ | |
| { | |
| item_id: m.product.id, | |
| item_name: m.product.title, | |
| item_variant: m.title, | |
| price: m.price.amount, | |
| item_brand: m.product.vendor, | |
| item_category: m.product.type, | |
| quantity: cartLine.quantity, | |
| }, | |
| ], | |
| }); | |
| }); | |
| analytics.subscribe("collection_viewed", async function (event) { | |
| if (!consentGranted || !activeConfig) return; | |
| var collection = event.data.collection; | |
| gtag("event", "view_item_list", { | |
| send_to: activeConfig.ga4, | |
| item_list_id: collection.id, | |
| item_list_name: collection.title, | |
| }); | |
| }); | |
| analytics.subscribe("search_submitted", async function (event) { | |
| if (!consentGranted || !activeConfig) return; | |
| gtag("event", "search", { | |
| send_to: activeConfig.ga4, | |
| search_term: event.data.searchResult.query, | |
| }); | |
| }); | |
| // --- CHECKOUT EVENTS (native localization is authoritative) --- | |
| analytics.subscribe("checkout_started", async function (event) { | |
| if (!consentGranted) return; | |
| var checkout = event.data.checkout; | |
| var config = getConfigFromLocalization(checkout.localization); | |
| ensureGtag(config, null); | |
| var items = checkout.lineItems.map(function (item) { | |
| return { | |
| item_id: item.variant.product.id, | |
| item_name: item.title, | |
| item_variant: item.variant.title, | |
| price: item.variant.price.amount, | |
| item_brand: item.variant.product.vendor, | |
| item_category: item.variant.product.type, | |
| quantity: item.quantity, | |
| }; | |
| }); | |
| gtag("event", "begin_checkout", { | |
| send_to: config.ga4, | |
| currency: checkout.currencyCode, | |
| value: checkout.totalPrice.amount, | |
| items: items, | |
| }); | |
| }); | |
| analytics.subscribe("checkout_completed", async function (event) { | |
| if (!consentGranted) return; | |
| var checkout = event.data.checkout; | |
| var config = getConfigFromLocalization(checkout.localization); | |
| ensureGtag(config, null); | |
| var items = checkout.lineItems.map(function (item) { | |
| return { | |
| item_id: item.variant.product.id, | |
| item_name: item.title, | |
| item_variant: item.variant.title, | |
| price: item.variant.price.amount, | |
| item_brand: item.variant.product.vendor, | |
| item_category: item.variant.product.type, | |
| quantity: item.quantity, | |
| }; | |
| }); | |
| var txId = checkout.order ? checkout.order.id : checkout.token; | |
| gtag("event", "purchase", { | |
| send_to: config.ga4, | |
| transaction_id: txId, | |
| currency: checkout.currencyCode, | |
| value: checkout.totalPrice.amount, | |
| tax: checkout.totalTax.amount, | |
| shipping: checkout.shippingLine ? checkout.shippingLine.price.amount : 0, | |
| items: items, | |
| }); | |
| gtag("event", "conversion", { | |
| send_to: config.adsConversionId + "/" + config.adsConversionLabel, | |
| value: checkout.totalPrice.amount, | |
| currency: checkout.currencyCode, | |
| transaction_id: txId, | |
| }); | |
| }); | |
| analytics.subscribe("payment_info_submitted", async function (event) { | |
| if (!consentGranted) return; | |
| var checkout = event.data.checkout; | |
| var config = getConfigFromLocalization(checkout.localization); | |
| ensureGtag(config, null); | |
| gtag("event", "add_payment_info", { | |
| send_to: config.ga4, | |
| currency: checkout.currencyCode, | |
| value: checkout.totalPrice.amount, | |
| }); | |
| }); | |
| analytics.subscribe("checkout_shipping_info_submitted", async function (event) { | |
| if (!consentGranted) return; | |
| var checkout = event.data.checkout; | |
| var config = getConfigFromLocalization(checkout.localization); | |
| ensureGtag(config, null); | |
| gtag("event", "add_shipping_info", { | |
| send_to: config.ga4, | |
| currency: checkout.currencyCode, | |
| value: checkout.totalPrice.amount, | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment