Skip to content
TrackPilot

বাংলায় পড়ুন

Server-side GTM (sGTM) setup

Host your Google Tag Manager server container with us: create it, connect your domain, configure GTM, install the loader, send GA4 and Meta Conversions API events without double counting.

TrackPilot runs Google's official tagging-server image for you. You keep building tags in Google Tag Manager as usual; we host the server container, give it a first-party URL and count its requests. Setup takes about 20 minutes.

Starting from an empty GTM? See GTM setup from scratch for the data layer, every variable, trigger and tag, and the server container.

Before you start

  • A Google Tag Manager account with a web container (ID like GTM-ABC1234) already installed on your site.
  • A TrackPilot account. The number of sGTM containers you can run depends on your plan (see Billing).
  • Access to your domain's DNS, to add one CNAME record.

Step 1 — Create a server container in Google Tag Manager

  1. Open tagmanager.google.com → Admin → + next to Container.
  2. Give it a name (for example server-yourshop.com) and pick Server as the target platform.
  3. Choose Manually provision tagging server and copy the Container Config — a long string that starts like aWQ9R1RN….

Already have a server container (for example on another host)? Open it → Admin → Container Settings and copy the same Container Config. Your tags, triggers and clients come with it.

Step 2 — Create the container in TrackPilot

  1. Dashboard → sGTM → New container.
  2. Enter a name, paste the Container Config and click Create container.
  3. The status moves requested → deploying → running within 1–2 minutes. Reload the page to see it.

The container page shows the sGTM container ID, the built-in URL and the requests used this month. You can stop, start or delete the container there at any time.

Step 3 — Connect your own domain

A subdomain of your site makes gtm.js and every hit first-party: longer-lived cookies and far fewer ad-blocker losses.

  1. Container page → Domains → add a hostname such as data.yourshop.com. Pick a neutral word: avoid gtm, analytics, tracking, pixel or tag, which ad blockers look for.
  2. At your DNS provider create the CNAME record shown in the dashboard. If your DNS is on Cloudflare, set it to DNS only (grey cloud).
  3. Wait until both hostname and SSL show active (usually minutes; the page refreshes by itself).

Below we write https://data.yourshop.com — use your own hostname everywhere it appears.

Step 4 — Configure the server container in GTM

  1. Server container URL: server container → Admin → Container Settings → add https://data.yourshop.com → Save.
  2. Web Container client (required): Clients → New → Google Tag Manager: Web Container → Allowed Container IDs = your web container ID (GTM-ABC1234) → Save. Without this client the tagging server answers gtm.js and ns.html with 400 Bad Request.
  3. GA4 client: new server containers already have one. Keep it — it receives the events your website sends.
  4. Submit → Publish. The tagging server picks up a new version within about a minute.

Check: https://data.yourshop.com/gtm.js?id=GTM-ABC1234 should return JavaScript, and https://data.yourshop.com/healthz should return status 200.

Step 5 — Install the first-party loader on your website

  1. Container page → Install code (Custom Loader) → pick your tagging-server URL, enter your web container ID → Generate.
  2. Paste the first snippet as high as possible inside <head> and the <noscript> snippet right after the opening <body> tag.
  3. Remove the old Google Tag Manager snippet — the page must load GTM only once.

The snippet looks like this (generate yours in the dashboard):

<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://data.yourshop.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-ABC1234');</script>

Step 6 — Send GA4 events to the server

  1. Web container → your Google tag (GA4 configuration) → Configuration settings → add server_container_url = https://data.yourshop.com. Optionally add first_party_collection = true.
  2. On each GA4 event tag that carries shop data (view_item, add_to_cart, add_payment_info, purchase): More settings → Ecommerce → tick Send Ecommerce data, data source Data Layer. This sends the items list to the server.
  3. Also add these event parameters, so the server can build complete Meta events:
ParameterValue
event_id{{Event ID}} — the same variable the Meta Pixel tags use (Step 8)
valueorder or item value (number)
currencyfor example BDT
content_ids, content_type, content_name, num_itemsfrom your data layer
contents{{JS - FB Contents (String)}} — must be a JSON string, see below

GA4 sends every parameter as text, so an array arrives as [object Object]. Create two Custom JavaScript variables (they read the Data Layer Variable ecommerce.items):

JS - FB Contents (String)

function () {
  var items = {{DLV - ecommerce.items}} || [];
  return JSON.stringify(items.map(function (i) {
    return { id: String(i.item_id), quantity: Number(i.quantity) || 1, item_price: Number(i.price) || 0 };
  }));
}

JS - FB Value (use it for value when your data layer has no order total)

function () {
  var items = {{DLV - ecommerce.items}} || [];
  var total = 0;
  for (var k = 0; k < items.length; k++) {
    total += (Number(items[k].price) || 0) * (Number(items[k].quantity) || 1);
  }
  return total;
}

For purchase, prefer the real order total (with shipping and discounts) when your data layer has it.

Step 7 — Meta Conversions API in the server container

  1. Server container → Templates → Search Gallery → add Conversions API Tag (by facebookincubator).
  2. Tags → New → Conversions API Tag:
    • Pixel ID — your Meta Pixel / dataset ID.
    • API Access Token — Events Manager → your dataset → Settings → Generate access token.
    • Action Source = Website, tick Extend Meta Pixel cookies (fbp/fbc) and Enable Event Enhancement.
    • Test Event Code — only while testing (copy it from Events Manager → Test events). Remove it before going live, or Meta treats every server event as a test.
  3. Trigger: a Custom trigger that fires on all events coming from the GA4 client (for example Client Name equals GA4).
  4. Submit → Publish.

Step 8 — Deduplication: one Event ID for browser and server

The browser Pixel and the server send the same event. Meta keeps one only when both carry the same event ID.

  1. Create one Event ID variable in the web container (for example the Event Id variable template from the Community Gallery).
  2. Use the official Meta Pixel tag template. If GTM shows an update for an older "Facebook Pixel" template, accept it — the old one has no Event ID field.
  3. Every Meta Pixel tag (PageView, ViewContent, AddToCart, AddPaymentInfo, Purchase) → More Settings → Event ID = {{Event ID}}.
  4. Every matching GA4 event tag → parameter event_id = {{Event ID}} (Step 6).

Already sending server events yourself? The Meta Pixel tag's Meta-enabled Conversions API integration option is not needed; you can leave it off.

More on how matching works: Event deduplication.

Step 9 — Test

  1. GTM Preview on the server container: open your site, then check each event's Event Data — contents must be a JSON list and value a number — and that the Conversions API tag shows an outgoing request to graph.facebook.com with status 200.
  2. Events Manager → Test events: each action shows a Browser row and a Server row. The server row says Deduplicated and both share one Event ID.
  3. Meta Pixel Helper (Chrome extension): open an event — it shows the Event ID the browser sent.

After publishing, reload the test page with Ctrl+Shift+R: browsers keep the previous gtm.js for a few minutes.

Troubleshooting

What you seeCauseFix
gtm.js returns 400No Web Container client, or not published yetStep 4, publish, wait one minute
Domain stays pendingCNAME missing or proxiedAdd the CNAME from the dashboard; on Cloudflare use DNS only
Container shows errorContainer Config pasted incompletely, or your plan's container limit reachedCopy the config again; check Billing; contact support
No server rows in Test eventsThe CAPI tag's Test Event Code is not today's codeCopy the current code from Test events into the tag (remove it before going live)
contents shows [object Object]An array sent as a GA4 parameterUse the JSON string variable from Step 6
Server event has only value and currencyitems not sent to the serverTick Send Ecommerce data on the GA4 event tags (Step 6)
Browser row has no Event ID in Test eventsThat column is often empty for browser rows; or the page still loads the old gtm.jsCheck with Meta Pixel Helper after a hard reload
Events counted twiceBrowser and server event IDs differUse the same {{Event ID}} variable on both sides (Step 8)

Moving from another sGTM host

  1. Create the container in TrackPilot with the same Container Config (Step 2) — all your tags, triggers and clients stay in Google Tag Manager.
  2. Point your tagging domain's DNS to us (Step 3). Once it shows active, traffic reaches the new container.
  3. Add the Web Container client if your old host served gtm.js its own way (Step 4), and use our loader snippet (Step 5).
  4. Test (Step 9), then cancel the old hosting.

Usage and limits

Every request to your tagging server counts toward the monthly allowance of your plan. The sGTM page shows requests this month / limit and how many containers your plan allows; upgrade on the Billing page.


Stuck? Ask for setup help — we answer in বাংলা or English.