Preskoči na sadržaj

Kako Dodati Data Layer na Shopify Plus

Vodič korak po korak za dodavanje data layera na Shopify Plus: GTM sa podrazumevanom saglasnošću u theme.liquid, view_item i add_to_cart iz teme, custom pixel od begin_checkout do purchase, pa podešavanje GTM-a i testiranje.

Kako Dodati Data Layer na Shopify Plus

Da biste dodali data layer na Shopify Plus, instalirajte Google Tag Manager u theme.liquid i iz teme šaljite GA4 ecommerce događaje na stranicama prodavnice, a zatim u Settings > Customer events dodajte custom pixel koji GTM-u šalje događaje iz checkouta i kupovine. Kod teme se ne izvršava u checkoutu, pa piksel pokriva sve od begin_checkout do purchase.

Vodič prolazi kroz šest koraka sa kodom koji možete da prilagodite, a zatim kroz testiranje i česte greške. Zašto su šema događaja, imenovanje i pravila saglasnosti baš ovakvi, objašnjavamo u tekstu najbolje prakse za Shopify Plus data layer.

Šta vam treba pre početka?

  • Odluka o aplikaciji Google & YouTube. Aplikacija već šalje view_item, add_to_cart, begin_checkout, purchase i druge događaje u GA4 (Google). Ako ostane povezana sa GA4, ne šaljite iste događaje u isti GA4 property iz GTM-a, jer će se kupovine brojati dva puta.
  • Dva GTM web containera, jedan za temu i jedan za custom pixel. Ovo je naša preporuka, a ne Shopify pravilo: tako se okidači iz prodavnice ne aktiviraju u sandboxu piksela.
  • Podešena customer privacy podešavanja i cookie banner u Shopify-u.
  • Kopija aktivne teme. U Online Store > Themes kliknite ... pored teme, izaberite Duplicate i radite na kopiji.

Korak 1: Kako da instalirate GTM sa podrazumevanom saglasnošću?

Otvorite kopiju teme preko ... > Edit code. Napravite snippet data-layer.liquid (popunićete ga u koraku 2). U layout/theme.liquid ga ubacite unutar <head>, posle {{ content_for_header }}, a odmah iza njega nalepite head deo GTM container koda iz Admin > Install Google Tag Manager:

{{ content_for_header }}
{% render 'data-layer' %}
<!-- Google Tag Manager container code from GTM goes here -->

Redosled je bitan. Google podrazumevane vrednosti saglasnosti moraju da se izvrše pre bilo kog taga (Google), a snippet koristi window.Shopify, koji učitava content_for_header.

Korak 2: Kako iz teme da šaljete saglasnost, kontekst stranice i dodavanje u korpu?

Nalepite ovaj kod u snippets/data-layer.liquid. On sve signale saglasnosti postavlja na denied, a zatim ih ažurira iz Shopify Customer Privacy API-ja, koji kombinuje vaša podešavanja privatnosti, lokaciju posetioca i njegov izbor. Osim toga, šalje kontekst stranice i definiše pomoćnu funkciju za add_to_cart.

<script>
  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }

  // 1. Consent defaults, before GTM loads
  gtag('consent', 'default', {
    analytics_storage: 'denied',
    ad_storage: 'denied',
    ad_user_data: 'denied',
    ad_personalization: 'denied'
  });

  // 2. Real status from Shopify's Customer Privacy API
  function sendConsent() {
    var privacy = window.Shopify && window.Shopify.customerPrivacy;
    if (!privacy) return;
    var marketing = privacy.marketingAllowed() ? 'granted' : 'denied';
    gtag('consent', 'update', {
      analytics_storage: privacy.analyticsProcessingAllowed() ? 'granted' : 'denied',
      ad_storage: marketing,
      ad_user_data: marketing,
      ad_personalization: marketing
    });
  }
  if (window.Shopify && window.Shopify.loadFeatures) {
    window.Shopify.loadFeatures(
      [{ name: 'consent-tracking-api', version: '0.2' }],
      function (error) { if (!error) sendConsent(); }
    );
  }
  document.addEventListener('visitorConsentCollected', sendConsent);

  // 3. Page context (no personal data)
  dataLayer.push({
    page_type: {{ request.page_type | json }},
    language: {{ request.locale.iso_code | json }},
    currency: {{ cart.currency.iso_code | json }},
    customer_logged_in: {% if customer %}true{% else %}false{% endif %}
  });

  // 4. Helper for add_to_cart, called from your cart JavaScript
  window.pushAddToCart = function (item, quantity) {
    var price = item.final_price / 100;
    dataLayer.push({ ecommerce: null });
    dataLayer.push({
      event: 'add_to_cart',
      ecommerce: {
        currency: {{ cart.currency.iso_code | json }},
        value: price * quantity,
        items: [{
          item_id: String(item.sku || item.variant_id),
          item_name: item.product_title,
          item_variant: item.variant_title,
          item_brand: item.vendor,
          price: price,
          quantity: quantity
        }]
      }
    });
  };
</script>

Filter json ispisuje bezbedne JavaScript stringove. Cene iz Ajax Cart API-ja su u najmanjoj jedinici valute, pa ih funkcija deli sa 100.

Korak 3: Kako da pošaljete view_item sa stranice proizvoda?

Napravite snippet data-layer-product.liquid sa kodom ispod i ubacite ga na kraj glavne sekcije proizvoda pomoću {% render 'data-layer-product', product: product %}. U temi Dawn to je sections/main-product.liquid. Online Store 2.0 teme nemaju fajl šablona product.liquid, pa tražite u folderu sections/.

{%- assign variant = product.selected_or_first_available_variant -%}
<script>
  window.dataLayer = window.dataLayer || [];
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: 'view_item',
    ecommerce: {
      currency: {{ cart.currency.iso_code | json }},
      value: {{ variant.price | divided_by: 100.0 }},
      items: [{
        item_id: {{ variant.sku | default: variant.id | append: '' | json }},
        item_name: {{ product.title | json }},
        item_variant: {{ variant.title | json }},
        item_brand: {{ product.vendor | json }},
        item_category: {{ product.type | json }},
        price: {{ variant.price | divided_by: 100.0 }},
        quantity: 1
      }]
    }
  });
</script>

Liquid cene su u najmanjoj jedinici valute (Shopify), zato divided_by: 100.0. Ovde ne koristite money filtere, jer vraćaju formatiran tekst. Događaj view_item_list na stranicama kolekcija pravi se na isti način, sa po jednim artiklom za svaki proizvod iz collection.products.

Korak 4: Kako da aktivirate add_to_cart iz koda korpe?

Teme dodaju proizvode u korpu na različite načine, pa window.pushAddToCart pozovite na mestu gde tema dobija uspešan odgovor od /cart/add.js. U temi Dawn to je skripta forme proizvoda. Odgovor je JSON dodate stavke korpe (Shopify):

const quantity = Number(formData.get('quantity') || 1);
fetch(window.Shopify.routes.root + 'cart/add.js', { method: 'POST', body: formData })
  .then((response) => response.json())
  .then((item) => {
    if (item.status) return; // error response, nothing was added
    window.pushAddToCart(item, quantity);
    // ...the theme's own cart update code continues here
  });

Prosledite količinu koju je posetilac izabrao, a ne onu iz odgovora: ako je artikal već bio u korpi, odgovor sadrži novu ukupnu količinu. Ako tema ima više načina dodavanja u korpu (quick add, upsell aplikacije), alternativa je da se umesto toga pretplatite na product_added_to_cart u pikselu iz koraka 5. Koristite jedan izvor, ne oba.

Korak 5: Kako da custom pixelom šaljete događaje iz checkouta i kupovine?

Shopify checkout, Thank you i Order status stranice više ne izvršavaju kod teme niti Additional scripts. Additional scripts i checkout.liquid su ugašeni na Thank you i Order status stranicama 28. avgusta 2025. (Shopify). Pikseli se učitavaju na svim ovim stranicama (Shopify Help Center). Piksel dodajete ovako (Shopify Help Center):

  1. Idite na Settings > Customer events i kliknite Add custom pixel.
  2. Unesite naziv, na primer "GTM checkout", i kliknite Add pixel.
  3. U delu Customer privacy postavite Permission na Required i izaberite svrhe koje vašim tagovima trebaju, najčešće Analytics i Marketing. Data sale podesite prema tagovima koje koristite.
  4. Nalepite kod ispod u prozor Code, sa ID-jem container-a za piksel umesto GTM-XXXXXXX.
  5. Kliknite Save, pa Connect pixel.
// Paste as JavaScript only: no <script> tags in a custom pixel
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }

// Consent mode from Shopify's privacy status
let privacy = init.customerPrivacy;
function sendConsent(mode) {
  const marketing = privacy.marketingAllowed ? 'granted' : 'denied';
  gtag('consent', mode, {
    analytics_storage: privacy.analyticsProcessingAllowed ? 'granted' : 'denied',
    ad_storage: marketing,
    ad_user_data: marketing,
    ad_personalization: marketing
  });
}
sendConsent('default');
api.customerPrivacy.subscribe('visitorConsentCollected', (event) => {
  privacy = event.customerPrivacy;
  sendConsent('update');
});

// GTM loader (the head snippet from GTM, without the script tags)
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');

// Same item ID rule as the theme: SKU, else variant ID
function toItems(checkout) {
  return checkout.lineItems.map((line, index) => ({
    item_id: String(line.variant?.sku || line.variant?.id),
    item_name: line.variant?.product?.title || line.title,
    item_variant: line.variant?.title,
    item_brand: line.variant?.product?.vendor,
    price: Number(line.variant?.price?.amount),
    quantity: line.quantity,
    index: index
  }));
}

// value = subtotal before shipping and tax; change it to match your definition
function pushCheckout(name, event, extra) {
  const checkout = event.data.checkout;
  dataLayer.push({ ecommerce: null });
  dataLayer.push({
    event: name,
    page_location: event.context.window.location.href,
    ecommerce: Object.assign({
      currency: checkout.currencyCode,
      value: Number(checkout.subtotalPrice?.amount),
      items: toItems(checkout)
    }, extra || {})
  });
}

analytics.subscribe('checkout_started', (e) => pushCheckout('begin_checkout', e));
analytics.subscribe('checkout_shipping_info_submitted', (e) => pushCheckout('add_shipping_info', e));
analytics.subscribe('payment_info_submitted', (e) => pushCheckout('add_payment_info', e));
analytics.subscribe('checkout_completed', (e) => {
  const checkout = e.data.checkout;
  const codes = (checkout.discountApplications || [])
    .filter((d) => d.type === 'DISCOUNT_CODE')
    .map((d) => d.title);
  pushCheckout('purchase', e, {
    transaction_id: checkout.order?.id,
    tax: Number(checkout.totalTax?.amount || 0),
    shipping: Number(checkout.shippingLine?.price?.amount || 0),
    coupon: codes.join(',')
  });
});

Kako ovo radi: piksel se izvršava u sandboxed iframe-u, pa ima sopstveni window.dataLayer i ne može da čita niti menja vašu stranicu (Shopify). init.customerPrivacy i visitorConsentCollected drže consent mode usklađenim (Shopify). Putanje polja su iz dokumentacije za checkout_completed, a checkout_completed se aktivira jednom po checkoutu, na prvoj upsell stranici ako koristite post-purchase ponude. Pošto window.location u sandboxu nije URL vaše prodavnice, kod šalje page_location iz event.context, kako predlaže Shopify GTM vodič.

Imajte u vidu da Shopify ne pruža podršku za kod custom piksela, a isti vodič navodi da klikovi na spoljne linkove i drugi okidači zasnovani na DOM-u ne rade u sandboxu.

Korak 6: Kako da podesite GTM?

  1. Okidači: napravite Custom Event okidač za svaki naziv događaja: view_item i add_to_cart u container-u teme; begin_checkout, add_shipping_info, add_payment_info i purchase u container-u piksela.
  2. Google tag: u oba container-a dodajte GA4 measurement ID. U container-u piksela postavite konfiguracioni parametar send_page_view na false, jer tema već šalje preglede stranica, a URL iz sandboxa bi zagadio izveštaje.
  3. Event tag: napravite tag Google Analytics: GA4 Event sa Event Name {{Event}}. U More Settings > Ecommerce izaberite Send Ecommerce data i Data Source Data Layer, kako opisuje Google vodič. U container-u piksela dodajte parametar događaja page_location iz Data Layer Variable.
  4. Ostale promenljive: dodajte Data Layer Variable za page_type i customer_logged_in ako ih želite kao parametre.
  5. Publish: svaki container objavite kao imenovanu verziju.

Kako da testirate podešavanje?

  • Prodavnica: otvorite GTM Preview za container teme. Proverite da se view_item pojavljuje na stranici proizvoda sa tačnom cenom i valutom, a add_to_cart posle dodavanja proizvoda.
  • Checkout: opcija Troubleshoot tag u Tag Assistant-u ne prepoznaje Google tagove unutar custom piksela. Koristite Shopify Pixel Helper da vidite da događaji stižu do piksela (Shopify Help Center), a GA4 DebugView da vidite šta stiže u GA4.
  • Test porudžbina: napravite porudžbinu u test režimu vašeg provajdera plaćanja. Potvrdite jedan purchase sa transaction_id, value, currency i items, i proverite da li se događaji iz checkouta nastavljaju u istoj GA4 sesiji kao događaji iz prodavnice.
  • Posle lansiranja: prve nedelje svakog dana uporedite kupovine u GA4 sa Shopify porudžbinama, a zatim jednom nedeljno.

Koje su najčešće greške?

GreškaRešenje
Kod za kupovinu ostao u Additional scriptsViše se ne izvršava na Thank you stranici. Prebacite ga u custom pixel.
Universal Analytics objekti (ecommerce.detail, actionField, transactionTotal)Napravite ih ponovo sa GA4 nazivima događaja i nizom items.
Automatski pregledi stranica ostali uključeni u container-u pikselaTamo postavite send_page_view na false. Preglede stranica šalje container teme.
Cene ispisane money filterimaZa brojčane vrednosti koristite divided_by: 100.0.
Različiti ID-jevi artikala u temi i pikseluNa oba mesta koristite isto pravilo: SKU ili ID varijante.
Isti container ID u temi i pikselu, sa All Pages okidačimaKoristite poseban container za piksel ili ograničite njegove okidače na nazive događaja iz checkouta.

Većina prodavnica može da prati ove korake bez izmena. Ako vaša ima prilagođenu korpu, više aplikacija u checkoutu ili praćenje koje se već ne slaže sa brojem porudžbina u Shopify-u, možemo da ga postavimo i testiramo umesto vas u okviru usluge prilagođavanja Shopify Plus checkouta.

FAQ

Gde se u Shopify-u stavlja kod za data layer?

Kod za prodavnicu ide u temu: snippet koji se ubacuje u layout/theme.liquid za podatke na celom sajtu i snippet u glavnoj sekciji proizvoda za podatke o proizvodu. Kod za checkout i kupovine ide u custom pixel u Settings > Customer events.

Mogu li da pratim kupovine iz teme?

Ne. Thank you i Order status stranice su deo Shopify checkouta i ne učitavaju fajlove teme. Umesto toga se pretplatite na checkout_completed u pikselu.

Da li GTM Preview mode radi za custom pixel?

Shopify vodič ne opisuje GTM Preview za piksele, a opcija Troubleshoot tag u Tag Assistant-u ne može da prepozna Google tagove unutar piksela. Shopify preporučuje Pixel Helper. Kombinujte ga sa GA4 DebugView.

Da li mi za ovo treba Shopify Plus?

Ne. Data layer u temi i custom pikseli rade i na drugim planovima. Plus dodaje checkout UI ekstenzije na koracima information, shipping i payment, koje mogu da šalju dodatne sopstvene događaje vašem pikselu (Shopify).

Zašto GA4 pokazuje manje kupovina od Shopify-a?

Posetioci koji odbiju saglasnost, blokatori oglasa i zaštita od praćenja u pregledačima uklanjaju događaje koje Shopify i dalje beleži kao porudžbine. Stabilna razlika je normalna. Nagla promena obično znači pokvaren snippet, isključen piksel ili duplog pošiljaoca.

Skalirate se na Shopify Plus-u?

Migracija, B2B, arhitektura, performanse — vodimo angažmane koje druge agencije vraćaju.

Checklista koju prolazimo pre nego što dotaknemo kod klijenta

Stiže vam na email, uz nekoliko kratkih poruka u naredne dve nedelje: šta najčešće vidimo na Shopify prodavnicama i šta zaista pomaže.

Bez spama. Odjava u bilo kom trenutku. Politika privatnosti

Želite više naših tekstova u Google pretrazi? Dodajte Codersy kao željeni izvor.

Dodaj Codersy na Google(otvara se u novom prozoru)