Shopify Markets Nedir?
Shopify Markets, tek bir store üzerinden birden fazla coğrafi pazara satış yapmayı sağlayan Shopify’ın çoklu pazar yönetimi altyapısı. Her market, belirli bölgeleri (ülke veya ülke grupları), dilleri, para birimlerini ve fiyatlandırma kurallarını bir arada tanımlar.1
Bir store’un en fazla 50 market’i olabilir. Markets, üst pazar (parent market) ve alt pazar (sub-market) hiyerarşisini destekler. Alt pazarlar, üst pazarın kişiselleştirmelerini (para birimi, katalog, tema) devralır ve gerektiğinde override edebilir.2 Örneğin Kuzey Amerika üst pazarı USD kullanır; Kanada alt pazarı bunu CAD olarak override ederken tema kişiselleştirmesini korur.
Ziyaretçi hiçbir aktif market ile eşleşmezse yedek bölge (fallback region) devreye girer. Cookie bridge implementasyonunda bu edge case’in handle edilmesi gerekir.
Market bazlı tema kişiselleştirmesi yalnızca Advanced ve Plus planlarında mümkündür. Starter ve Basic planlarında tüm pazarlar aynı temayı görür. Ancak theme app extension (app embed) tüm planlarda çalışır.2
Market’ler üç farklı URL yapısıyla sunulabilir:
- Alt alan adı:
de.example.com,fr.example.com - Alt klasör:
example.com/de,example.com/fr - Özel alan adı:
example.de,example.fr
Automatic Redirection ve EU Kısıtı
Shopify, ziyaretçinin coğrafi konumuna göre otomatik yönlendirme sunar. Ancak AB mevzuatı gereği, ccTLD kullanan EU market’lerde (.de, .fr, .nl vb.) otomatik yönlendirme devre dışıdır. Bir Fransız müşteri .de domain’ine girerse .fr’ye yönlendirilmez, girdiği domain’de kalır.3 Shared domain yapılarında (.com/de, .com/fr) bu kısıt geçerli değildir.
Bu, tracking açısından kritik bir implikasyon taşır: ccTLD kullanan EU market’lerde URL bazlı market tespiti güvenilmez olabilir. Ziyaretçi “yanlış” domain’de geziniyor olabilir. Bu nedenle market tespitini yalnızca URL’ye değil, Liquid localization objesine dayandırmak gerekir ki bu da cookie bridge pattern’inin neden önemli olduğunu güçlendiren nedenlerden biridir.
Storefront’ta market verisi iki kaynaktan okunabilir:
Liquid localization Objesi (Server-Side)
Canonical kaynak. Herhangi bir Liquid dosyasında (layout, section, snippet) kullanılabilir:
{{ localization.market.handle }} {# "netherlands" #}
{{ localization.country.iso_code }} {# "NL" #}
{{ localization.language.iso_code }} {# "nl" #}
{{ request.locale }} {# "nl" - URL prefix #}
Bu obje market handle, ülke, dil, mevcut ülke ve dil listeleri dahil tüm market bilgisini taşır.4
window.Shopify Global Objesi (Client-Side)
JavaScript’te erişilebilen global obje:
Shopify.shop; // "d1pnh6-fj.myshopify.com"
Shopify.locale; // "nl"
Shopify.country; // "NL"
Shopify.currency; // { active: "EUR", rate: "1.0" }
Her iki kaynak da storefront’ta güvenilir şekilde çalışır. Ancak pixel sandbox’ından bu kaynaklara doğrudan erişilemez.
Customer Events Mimarisi
Shopify, üçüncü taraf tracking entegrasyonlarını Customer Events (Web Pixels API) üzerinden çalıştırır. İki pixel tipi var:5
App Pixel (Strict Sandbox)
- Shopify uygulamaları tarafından
shopify.extension.tomlile tanımlanır - Consent gereksinimleri deklaratif olarak belirtilir; pixel manager yalnızca izin varsa yükler
settingsproperty’si üzerinden GraphQL Admin API konfigürasyonuna erişir1
Custom Pixel (Lax Sandbox)
- Shopify admin panelinden konfigure edilir
analytics,browser,initobjeleri önceden tanımlı olarak sunulursettingsproperty’sine erişimi yoktur
Her iki pixel tipi de sandbox’lanmış bir iframe’de çalışır. DOM’a erişemez, window.Shopify objesini okuyamaz, GTM trigger’ları çalışmaz. Ancak browser objesi üzerinden top frame’deki storage mekanizmalarına async erişim sağlanır:6
// Custom pixel içinde - async, top frame'de çalışır
var marketCookie = await browser.cookie.get("shopify_market");
await browser.localStorage.setItem("key", "value");
await browser.sessionStorage.getItem("key");
Sandbox kısıtlamalarının detayları için Shopify Analytics vs GA4 yazısının “Checkout Sandbox Kısıtlamaları” bölümüne bakabilirsiniz.
analytics.subscribe() ile Event Dinleme
Pixel’ler event’leri analytics.subscribe() üzerinden dinler. Custom event yayınlamak için analytics.publish() kullanılır (yalnızca custom event’ler, standard event’ler yayınlanamaz).7 Bu, cookie bridge’e alternatif bir veri taşıma yolu sunar: storefront’ta bir script, Liquid localization objesinden okuduğu market verisini analytics.publish() ile custom event olarak yayınlayabilir, pixel tarafında analytics.subscribe() ile bu event dinlenebilir. Ancak bu yaklaşımda timing kritiktir; custom event’in standard event’lerden önce publish edilmesi garanti değildir.
analytics.subscribe("page_viewed", function (event) {
// event.data, event.context, event.clientId
});
Veri Boşluğu: Hangi Event’lerde Localization Var?
Shopify Web Pixels API’sinde 16 standard event bulunur. Localization objesi yalnızca checkout event’lerinde mevcuttur:8
Storefront Event’leri (Localization Yok)
| Event | Açıklama | Localization |
|---|---|---|
page_viewed | Sayfa görüntüleme | Yok |
product_viewed | Ürün detay sayfası | Yok |
collection_viewed | Koleksiyon sayfası | Yok |
product_added_to_cart | Sepete ekleme | Yok |
product_removed_from_cart | Sepetten çıkarma | Yok |
cart_viewed | Sepet sayfası | Yok |
search_submitted | Arama | Yok |
alert_displayed | Uyarı mesajı | Yok |
ui_extension_errored | Extension hatası | Yok |
Checkout Event’leri (Localization Var)
| Event | Açıklama | Localization |
|---|---|---|
checkout_started | Checkout başlangıcı | Var |
checkout_address_info_submitted | Adres bilgisi | Var |
checkout_contact_info_submitted | İletişim bilgisi | Var |
checkout_shipping_info_submitted | Kargo seçimi | Var |
payment_info_submitted | Ödeme bilgisi | Var |
checkout_completed | Satın alma tamamlandı | Var (+ order + transactions) |
Localization Objesi Yapısı
Checkout event’lerinde data.checkout.localization objesi şu yapıdadır:
{
"localization": {
"country": {
"isoCode": "NL"
},
"language": {
"isoCode": "nl-NL"
},
"market": {
"id": "gid://shopify/Market/97736360265",
"handle": "netherlands"
}
}
}
country.isoCode: ISO-3166-1 ülke kodulanguage.isoCode: BCP-47 dil etiketi (bölge dahil)market.handle: Store’a özgü market tanımlayıcımarket.id: Shopify global ID
Storefront Event’lerinde Ne Var?
page_viewed event’inin data payload’ı boştur. product_added_to_cart event’inde sadece cart line verileri (ürün, fiyat, miktar) bulunur. Her iki durumda da yalnızca context objesi içindeki navigator.language bilgisi mevcuttur ki bu, tarayıcı dil tercihi olup ziyaretçinin aktif market’ini göstermez.
Init event’inde data.shop seviyesinde bilgi vardır:
{
"data": {
"shop": {
"name": "Example Store",
"paymentSettings": {
"currencyCode": "EUR"
},
"myshopifyDomain": "example-store.myshopify.com",
"countryCode": "NL",
"storefrontUrl": "https://www.example-store.com"
}
}
}
Ancak buradaki countryCode ve currencyCode store varsayılanlarıdır, ziyaretçinin aktif market’i değil. Hollanda, Almanya ve Fransa market’lerine sahip bir store’da üç farklı pazardaki ziyaretçilerin hepsi aynı NL ve EUR değerlerini görür.
Neden Önemli?
Multi-market Shopify store’larda bu veri boşluğu somut sorunlar yaratır:
Per-Market GA4 Measurement ID
Farklı pazarlar için farklı GA4 property’leri kullanmak yaygın bir gereksinimdir. Yasal nedenler (GDPR kapsamında bölgesel veri işleme), organizasyonel nedenler (farklı ajanslar veya ekipler) veya analitik nedenler (cross-market kontaminasyon önleme) bunu gerektirebilir. Storefront event’lerinde market bilgisi olmadan, hangi GA4 property’sine veri göndereceğinizi belirleyemezsiniz.
Per-Market Google Ads Conversion ID
Her market’in kendi Google Ads hesabı ve conversion tracking’i olabilir. Checkout event’lerinde localization mevcut olduğu için checkout_completed event’ini doğru hesaba yönlendirmek mümkündür. Ancak page_viewed ve product_added_to_cart gibi storefront event’lerini market bazında segmente edemezsiniz, bu da remarketing audience’larını ve funnel optimizasyonunu kırar.
Market Bazlı Funnel Analizi
Hangi pazarda hangi ürünlerin görüntülendiği, sepete eklendiği ve checkout’a geçtiği bilgisi ancak tüm funnel boyunca market verisi taşınırsa anlamlıdır. Yalnızca checkout event’lerinde market bilgisi olması, storefront funnel’ını pazar bazında analiz etmeyi engeller.
Currency-Correct Revenue Attribution
Storefront event’leri (add_to_cart) ürün fiyatını ve currency code’u taşır. Ancak aynı ürün farklı market’lerde farklı para birimlerinde gösterilebilir. Market bilgisi olmadan, bir add_to_cart event’inin hangi pazarın para birimiyle kaydedildiği belirsiz kalır.
Shopify’ın para birimi mimarisinde üç farklı currency kavramı var ve bunları karıştırmak revenue attribution’ı bozar:9
| Kavram | Açıklama | Kaynak |
|---|---|---|
| Presentment currency | Ziyaretçinin checkout’ta gördüğü ve ödediği para birimi. Kaynak of truth. | Checkout event’leri |
| Shop currency | Merchant’ın Shopify admin’deki referans para birimi. Presentment’tan canlı kur ile back-convert edilir. Yuvarlamalar eşleşmeyebilir. | Analytics raporları |
| Settlement currency | Merchant’ın payout para birimi. Muhasebe için en doğru değer. | Payment gateway |
GA4 ve Google Ads, property/account seviyesinde tanımlanan bir para birimi kullanır. Event ile farklı bir currency geldiğinde GA4 bir önceki günün döviz kuruyla, Google Ads ise ortalama günlük döviz kuruyla account currency’sine çevirir.10 Bu nedenle event’lerle gönderilen value ve currency parametrelerinin Shopify presentment currency olması gerekir. Shop currency kullanmak çift dönüşüme (Shopify back-conversion + GA4/Ads conversion) yol açar ve intermediate yuvarlama farkları nedeniyle revenue toplamları eşleşmez.
Market Catalog Görünürlüğü
Shopify Markets, merchant’ların belirli ürünleri belirli market’lerden gizlemesine olanak tanır. Bir market’in kataloğundan çıkarılan ürün, storefront’ta arşivlenmiş gibi davranır: listelerden çıkarılır, arama sonuçlarında görünmez, sepete eklenemez.9 Ancak product_viewed event’i hâlâ tetiklenebilir (doğrudan URL erişimi gibi edge case’lerde) ve bu event’te market bilgisi olmadığı için hangi catalog context’inde görüntülendiği bilinemez.
URL Hardcoding ve Market Context Kaybı
Shopify’ın resmi dev docs’u URL’lerin hardcode edilmemesi konusunda açık bir uyarı içerir:9 /cart gibi hardcoded linkler ziyaretçiyi domain default’una zorlar ve market context’i (dil, para birimi) kaybolur. Bu, tracking açısından da geçerli: hardcoded URL’ler üzerinden yapılan navigasyonlarda page_viewed event’i yanlış market context’inde tetiklenir.
Dil Tespitinde navigator.language Güvenilmezliği
Storefront event’lerinde context.navigator.language tarayıcı dil tercihini gösterir ama bu, ziyaretçinin aktif market’ini yansıtmaz. Shopify’ın translation fallback sırası bunu somutlaştırır: Belçika’daki Hollandaca konuşan bir ziyaretçi için fallback Dutch (Belgium) > Base Dutch > French (Belgium) > Base French > Base English şeklinde ilerler.9 navigator.language değeri nl olabilir ama ziyaretçi Fransızca Belçika market’inde geziniyor olabilir. Market tespitini navigator.language’e dayandırmak güvenilmezdir.
Mevcut Yaklaşımların Sınırları
Native Google & YouTube App
Shopify’ın resmi Google entegrasyonu temel event’leri otomatik olarak gönderir. Ancak market bazlı segmentasyon sunmaz. Tüm event’ler tek bir GA4 property’sine, tek bir Google Ads conversion ID’sine gider.11
GTM via Custom Pixel
GTM’yi custom pixel olarak yüklemek tam kontrol sağlar, ancak aynı veri boşluğundan muzdariptir. GTM sandbox’ta çalışır, DOM’a erişemez, storefront event’lerinde localization yoktur. GTM trigger’ları (element visibility, scroll, click) devre dışıdır. GTM Preview Mode çalışmaz.
Server-Side Tracking
Server-side çözümler checkout session kırılmasını çözer ve purchase event doğruluğunu artırır. Ancak storefront event’lerini (page_viewed, product_viewed, add_to_cart) market bazında segmente etme konusunda aynı sınırlamaya tabidirler. Server-side tracking, Shopify’ın sunucu tarafından gönderdiği event verilerine bağlıdır; bu verilerde de storefront event’leri localization taşımaz.
Çözüm: Cookie Bridge Pattern
Bu veri boşluğunu kapatmanın yolu, storefront’ta mevcut olan market verisini pixel sandbox’ına taşımaktır. Genel yaklaşım:
- Theme app extension (app embed) Liquid
localizationobjesini ve/veyawindow.Shopifyverisini okur - Market bilgisini
document.cookieile yazar - Custom pixel sandbox’ından
browser.cookie.get()ile bu cookie’yi async olarak okur - Storefront event’lerini market verisiyle zenginleştirir
Bu, serinin ikinci yazısında consent-aware implementasyonuyla birlikte ele alınıyor: Shopify Markets Cookie Bridge: Consent-Aware Storefront-Pixel Veri Köprüsü.
Footnotes
- Shopify Dev: Markets. GraphQL Admin API referansı: Market object, markets query, MarketWebPresence ↩ ↩2
- Üst pazar / alt pazar hiyerarşisi, yedek bölge (fallback region) ve plan bazlı özellik kısıtlamaları. Market bazlı tema kişiselleştirmesi Advanced+ gerektirir. Shopify Help: Markets’e genel bakış ↩ ↩2
-
AB ccTLD’lerde otomatik yönlendirme yerel mevzuat gereği devre dışıdır.
.de,.fr,.nlgibi ülkeye özgü TLD’ler arasında yönlendirme yapılmaz..com,.shopgibi genel TLD’lerde kısıt yok. Shopify Help: Set up automatic storefront redirection ↩ - Shopify Dev: Liquid Objects - Localization ↩
- Shopify Dev: Web Pixels API ↩
- Shopify Dev: Web Pixels API - Standard API - Browser ↩
- Shopify Dev: Web Pixels API - Emitting Data ↩
- Shopify Dev: Web Pixels API - Standard Events ↩
-
Presentment/shop/settlement currency kavramları, market catalog kısıtlamaları, URL hardcoding uyarısı ve translation fallback sırası. Shopify Dev: About Shopify Markets. Locale-aware URL’ler ve
window.Shopify.routes.rootkullanımı: Shopify Dev: Support multiple currencies and languages ↩ ↩2 ↩3 ↩4 - GA4 property currency’den farklı currency ile gelen event’leri bir önceki günün döviz kuruyla çevirir. GA4 Currency Reference. Google Ads, managed account currency’sine ortalama günlük döviz kuruyla çevirir. Google Ads Currency Conversion ↩
- Littledata Blog: Why Shopify’s Google Analytics Tracking is Broken ↩
- 01 Shopify'ın 16 standard event'inden 9'u (storefront) localization verisi taşımaz, 6'sı (checkout) taşır
- 02 Localization objesi country (ISO-3166-1), language (BCP-47) ve market (handle + id) içerir
- 03 Storefront'ta market verisi Liquid localization objesi ve window.Shopify üzerinden erişilebilir, ancak pixel sandbox'ında bu kaynaklara doğrudan erişim yok
- 04 Custom pixel lax sandbox, app pixel strict sandbox'ta çalışır; her ikisi de browser.cookie ve browser.localStorage API'si ile top frame'e async erişebilir
- 05 Native Google & YouTube App, GTM via Custom Pixel ve server-side çözümler, storefront event'lerinde market segmentasyonu sağlamaz
+ Shopify Customer Events'te localization verisi hangi event'lerde var?
Yalnızca checkout event'lerinde: checkout_started, checkout_address_info_submitted, checkout_contact_info_submitted, checkout_shipping_info_submitted, payment_info_submitted ve checkout_completed. Storefront event'leri (page_viewed, product_viewed, product_added_to_cart vb.) localization objesi taşımaz.
+ Custom pixel ile app pixel arasındaki fark nedir?
Custom pixel lax sandbox'ta, app pixel strict sandbox'ta çalışır. Her ikisi de browser.cookie, browser.localStorage ve browser.sessionStorage API'si ile top frame'e async erişebilir. Custom pixel Shopify admin'den konfigure edilir, app pixel ise shopify.extension.toml üzerinden consent gereksinimleri declare eder.
+ Storefront event'lerinde market verisi neden yok?
Shopify'ın Web Pixels API tasarımı, localization objesini yalnızca checkout context'inde sağlar. Storefront event'lerinin data payload'ı sadece shop seviyesi bilgi içerir (shop countryCode, currencyCode). Ziyaretçinin aktif market'i storefront event payload'larına dahil edilmez.
+ Multi-market Shopify store'da GA4'te pazar bazlı raporlama nasıl yapılır?
Doğrudan yapılamaz, çünkü storefront event'leri market bilgisi taşımaz. Theme app extension ile Liquid localization verisini cookie'ye yazıp, custom pixel'den browser.cookie API'si ile okuyarak event'leri zenginleştirmek gerekir. Bu yöntem serinin ikinci yazısında ele alınıyor.