Reference

Every install snippet you'd copy-paste, in one place.

These are the only HTML snippets that touch a site directly. Everything else — conversions, custom events, audiences — lives inside GTM or the ad platform. Where a GTM template exists, use that instead; full walkthroughs in the How-To guides and Template Gallery.

Google Tag Manager

Google Tag Manager

Container snippet — <head>

Where to find the real version
How to install

Paste as high as possible inside the <head> of every page on your site.

Common mistakes
  • Only one GTM container per site — multiple containers double-fire every tag.
  • Don't wrap it in <script type="module">. It must be a normal script.
  • If you load it via a CMS, make sure it runs before any cookie banner that blocks scripts.
  • Place AFTER your Consent Mode v2 default block (see the Consent How-To).
<!-- Google Tag Manager — replace GTM-XXXXXXX with your container ID -->
<script>(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');</script>
<!-- End Google Tag Manager -->

Highlighted values are placeholders — swap them for your own IDs before going live.

Google Tag Manager

Container snippet — <body> noscript

Where to find the real version
How to install

Paste immediately after the opening <body> tag. Lets GTM work when JavaScript is disabled.

Common mistakes
  • Often forgotten — without it, ~1% of users won't be measured.
  • Make sure the GTM-XXXXXXX ID matches the <head> snippet exactly.
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Highlighted values are placeholders — swap them for your own IDs before going live.

Google

Google

Consent Mode v2 — default block

Where to find the real version
How to install

Paste in <head> BEFORE the GTM container snippet. Sets denied defaults for EEA/UK regions.

Common mistakes
  • Placed AFTER GTM — defaults arrive too late, first tags fire ungated.
  • Missing ad_user_data / ad_personalization (the 'v2' signals).
  • Region list incomplete — keep it in sync with the EEA + UK + Switzerland.
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('consent', 'default', {
    'ad_storage': 'denied',
    'ad_user_data': 'denied',
    'ad_personalization': 'denied',
    'analytics_storage': 'denied',
    'functionality_storage': 'granted',
    'security_storage': 'granted',
    'wait_for_update': 500,
    'region': ['GB','CH','DK','DE','FR','IE','IT','ES','SE','NO','FI',
               'NL','BE','AT','PL','PT','CZ','HU','RO','GR','BG','HR',
               'CY','EE','LV','LT','LU','MT','SI','SK','IS','LI']
  });
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

Universal

Universal

Initialise dataLayer (always do this first)

Where to find the real version
  • Standard pattern — no source needed.
How to install

Paste in <head> BEFORE the GTM container snippet. Guarantees dataLayer exists.

Common mistakes
  • If you push BEFORE GTM loads without this, the array doesn't exist and the push silently no-ops.
<script>window.dataLayer = window.dataLayer || [];</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

GA4

GA4

Google tag (gtag.js) — direct install (NO-GTM fallback)

Where to find the real version
How to install

Paste inside <head>. ONLY if you're not installing GA4 via GTM. If you have GTM, add GA4 through a Google Tag in the container instead.

Common mistakes
  • Don't run gtag.js AND a GA4 tag inside GTM at the same time — duplicate pageviews.
  • Replace G-XXXXXXXXXX with your own Measurement ID (Web stream).
  • Conversion / event tags belong inside GTM or GA4 — don't hard-code them on the site.
<!-- Google tag (gtag.js) — replace G-XXXXXXXXXX with your Measurement ID -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

Meta

Meta

Meta Pixel — direct install (use the GTM template instead if possible)

Where to find the real version
How to install

Paste inside <head>. Prefer the Meta Pixel GTM template — easier to manage events.

Common mistakes
  • Pair with Conversions API via sGTM in 2026 — Pixel alone misses 30–40% of conversions.
  • Never install twice. If you have GTM, only use the GTM template.
  • PII in custom events (email plaintext) → Meta strips and you lose match quality.
<!-- Meta Pixel — replace YOUR_PIXEL_ID -->
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init','YOUR_PIXEL_ID');
fbq('track','PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1"/></noscript>

Highlighted values are placeholders — swap them for your own IDs before going live.

TikTok

TikTok

TikTok Pixel — direct install

Where to find the real version
How to install

Paste inside <head>. Replace C-XXXXXXXXX with your Pixel Code.

Common mistakes
  • Default currency = USD. Always pass currency explicitly on track calls.
  • Capture ttclid from the URL on landing into a 1P cookie or your dataLayer.
  • Pair with Events API (server-side) via sGTM for proper match strength.
<!-- TikTok Pixel — replace C-XXXXXXXXX -->
<script>
!function (w, d, t) {
  w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track",
  "identify","instances","debug","on","off","once","ready","alias","group",
  "enableCookie","disableCookie"];ttq.setAndDefer=function(t,e){t[e]=function(){
  t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};
  for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);
  ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)
  ttq.setAndDefer(e,ttq.methods[n]);return e};ttq.load=function(e,n){
  var i="https://analytics.tiktok.com/i18n/pixel/events.js";ttq._i=ttq._i||{};
  ttq._i[e]=[];ttq._i[e]._u=i;ttq._t=ttq._t||{};ttq._t[e]=+new Date;
  ttq._o=ttq._o||{};ttq._o[e]=n||{};n=document.createElement("script");
  n.type="text/javascript";n.async=!0;n.src=i+"?sdkid="+e+"&lib="+t;
  e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
  ttq.load('C-XXXXXXXXX');
  ttq.page();
}(window, document, 'ttq');
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

Reddit

Reddit

Reddit Pixel — direct install

Where to find the real version
How to install

Paste inside <head>. Replace YOUR_REDDIT_PIXEL_ID.

Common mistakes
  • 7-day click attribution by default — shorter than Meta. Don't compare like-for-like.
  • Pair with Reddit CAPI if budgets are significant.
<!-- Reddit Pixel -->
<script>
!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};
p.callQueue=[];var t=d.createElement("script");t.src="https://www.redditstatic.com/ads/pixel.js",t.async=!0;
var s=d.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}}(window,document);
rdt('init','YOUR_REDDIT_PIXEL_ID', { optOut: false, useDecimalCurrencyValues: true });
rdt('track', 'PageVisit');
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

LinkedIn

LinkedIn

LinkedIn Insight Tag — direct install

Where to find the real version
How to install

Paste inside <body>. Replace YOUR_PARTNER_ID.

Common mistakes
  • Don't fire on staging — it pollutes audiences fast.
  • B2B: add LinkedIn CAPI for longer attribution windows.
<!-- LinkedIn Insight Tag -->
<script type="text/javascript">
_linkedin_partner_id = "YOUR_PARTNER_ID";
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(_linkedin_partner_id);
(function(l) { if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])};
window.lintrk.q=[]}var s=document.getElementsByTagName("script")[0];
var b=document.createElement("script");b.type="text/javascript";b.async=true;
b.src="https://snap.licdn.com/li.lms-analytics/insight.min.js";
s.parentNode.insertBefore(b,s);})(window.lintrk);
</script>
<noscript><img height="1" width="1" style="display:none;" alt=""
src="https://px.ads.linkedin.com/collect/?pid=YOUR_PARTNER_ID&fmt=gif" /></noscript>

Highlighted values are placeholders — swap them for your own IDs before going live.

Microsoft

Microsoft

Microsoft UET Tag — direct install

Where to find the real version
How to install

Paste inside <head>. Replace YOUR_UET_TAG_ID.

Common mistakes
  • Often forgotten as part of Google Ads import — UET is separate.
  • Enable Enhanced Conversions for Microsoft Ads (similar to Google's).
<!-- Microsoft UET Tag -->
<script>
(function(w,d,t,r,u){var f,n,i;w[u]=w[u]||[],f=function(){var o={ti:"YOUR_UET_TAG_ID",enableAutoSpaTracking:true};o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")},
n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function(){var s=this.readyState;s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)},
i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)})(window,document,"script","//bat.bing.com/bat.js","uetq");
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

Pinterest

Pinterest

Pinterest Tag — direct install

Where to find the real version
How to install

Paste inside <head>. Replace YOUR_TAG_ID.

Common mistakes
  • Event names omit underscores: 'addtocart' not 'add_to_cart'.
  • Pair with Pinterest Conversions API for proper coverage.
<!-- Pinterest Tag -->
<script>
!function(e){if(!window.pintrk){window.pintrk = function () {
window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var
n=window.pintrk;n.queue=[],n.version="3.0";var
t=document.createElement("script");t.async=!0,t.src=e;var r=document.getElementsByTagName("script")[0];
r.parentNode.insertBefore(t,r)}}("https://s.pinimg.com/ct/core.js");
pintrk('load', 'YOUR_TAG_ID');
pintrk('page');
</script>
<noscript><img height="1" width="1" style="display:none;" alt=""
src="https://ct.pinterest.com/v3/?event=init&tid=YOUR_TAG_ID&noscript=1" /></noscript>

Highlighted values are placeholders — swap them for your own IDs before going live.

Snap

Snap

Snap Pixel — direct install

Where to find the real version
How to install

Paste inside <head>. Replace YOUR_PIXEL_ID.

Common mistakes
  • Always pass hashed email + phone — match rate is volatile without it.
<!-- Snap Pixel -->
<script type='text/javascript'>
(function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function(){
a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)};
a.queue=[];var s='script';r=t.createElement(s);r.async=!0;
r.src=n;var u=t.getElementsByTagName(s)[0];
u.parentNode.insertBefore(r,u);})(window,document,
'https://sc-static.net/scevent.min.js');
snaptr('init', 'YOUR_PIXEL_ID', { user_email: '__INSERT_USER_EMAIL__' });
snaptr('track', 'PAGE_VIEW');
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

X (Twitter)

X (Twitter)

X Universal Website Tag

Where to find the real version
How to install

Paste inside <head>. Replace YOUR_PIXEL_ID.

Common mistakes
  • X has rebranded the tag multiple times — check for the latest version.
<!-- X (Twitter) Universal Website Tag -->
<script>
!function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments);
},s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='https://static.ads-twitter.com/uwt.js',
a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');
twq('config','YOUR_PIXEL_ID');
</script>

Highlighted values are placeholders — swap them for your own IDs before going live.

Shopify

Shopify

Customer Events — GA4 purchase (Shopify-native)

Where to find the real version
How to install

Paste into a Custom Pixel in Shopify (NOT into theme.liquid). Shopify runs custom pixels in a sandboxed iframe — you cannot use window, document, dataLayer, gtag() or fbq() directly. Use the analytics.subscribe API plus fetch / Measurement Protocol / CAPI.

Common mistakes
  • Custom Pixels are sandboxed — no access to window/document/dataLayer. Send data via Measurement Protocol or CAPI using fetch.
  • checkout_completed is the only reliable purchase event on Shopify — Shopify hides the thank-you page from your theme, so theme-level GA4 / Pixel purchase tags will NOT fire.
  • Use checkout.order.id (or checkout.token) as transaction_id / event_id so server-side dedupe works.
  • Shopify's Google / Meta channel apps ALSO fire purchase events — disable one side or you'll double-count.
  • Test with a real (or Bogus Gateway) order in incognito — Shopify's preview tool doesn't fire checkout_completed.
// Shopify Customer Events — Custom Pixel
// GA4 purchase via Measurement Protocol (sandbox-safe)
// Replace G-XXXXXXXXXX and YOUR_API_SECRET (GA4 → Admin → Data Streams → Measurement Protocol API secrets)

analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;
  const clientId = event.clientId || (Date.now() + '.' + Math.random().toString(36).slice(2));

  const payload = {
    client_id: clientId,
    events: [{
      name: 'purchase',
      params: {
        transaction_id: checkout.order?.id ?? checkout.token,
        value: checkout.totalPrice.amount,
        currency: checkout.currencyCode,
        tax: checkout.totalTax?.amount ?? 0,
        shipping: checkout.shippingLine?.price?.amount ?? 0,
        items: checkout.lineItems.map((li, i) => ({
          item_id: li.variant?.sku ?? li.variant?.id ?? li.id,
          item_name: li.title,
          item_variant: li.variant?.title,
          price: li.variant?.price?.amount,
          quantity: li.quantity,
          index: i,
        })),
      },
    }],
  };

  fetch('https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET', {
    method: 'POST',
    body: JSON.stringify(payload),
    keepalive: true,
  });
});

Highlighted values are placeholders — swap them for your own IDs before going live.

Shopify

Customer Events — Meta CAPI purchase (Shopify-native)

Where to find the real version
How to install

Paste into a Custom Pixel. For production, proxy this through your own server route so the access token isn't exposed in the browser — the snippet below is for testing or for stores where the pixel is locked down to your own staff.

Common mistakes
  • Never ship the CAPI access token in the browser long-term — proxy via a server route (e.g. /api/public/meta-capi).
  • event_id must match the Pixel-side purchase event_id for Meta to dedupe.
  • Hash email & phone with SHA-256 before sending (the snippet does it).
  • Use action_source: 'website' — 'system_generated' gets filtered.
// Shopify Customer Events — Meta CAPI (testing — proxy in production)
// Replace YOUR_PIXEL_ID and YOUR_CAPI_TOKEN

async function sha256(str) {
  const buf = new TextEncoder().encode(str.trim().toLowerCase());
  const hash = await crypto.subtle.digest('SHA-256', buf);
  return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2,'0')).join('');
}

analytics.subscribe('checkout_completed', async (event) => {
  const c = event.data.checkout;
  const eventId = c.order?.id ?? c.token;

  const userData = {};
  if (c.email) userData.em = [await sha256(c.email)];
  if (c.phone) userData.ph = [await sha256(c.phone.replace(/\D/g,''))];

  await fetch('https://graph.facebook.com/v19.0/YOUR_PIXEL_ID/events?access_token=YOUR_CAPI_TOKEN', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    keepalive: true,
    body: JSON.stringify({
      data: [{
        event_name: 'Purchase',
        event_time: Math.floor(Date.now()/1000),
        event_id: eventId,
        action_source: 'website',
        event_source_url: event.context.window.location.href,
        user_data: userData,
        custom_data: {
          currency: c.currencyCode,
          value: Number(c.totalPrice.amount),
          contents: c.lineItems.map(li => ({
            id: li.variant?.sku ?? li.variant?.id,
            quantity: li.quantity,
            item_price: Number(li.variant?.price?.amount ?? 0),
          })),
          content_type: 'product',
        },
      }],
    }),
  });
});

Highlighted values are placeholders — swap them for your own IDs before going live.

A note on direct-install vs GTM templates

Every snippet here can also be installed via a GTM template (see the Template Gallery). Direct install is for cases where you don't have GTM, you're testing, or you're handing off to a developer. Production setups should use templates so you can version, preview and roll back tracking changes without touching code.