Systems Lab

Agent skill

gtm-server-side-tagging-guide

This skill should be used when the user asks to \"set up server-side GTM\", \"implement Meta CAPI via sGTM\", \"migrate from client-side to server-side tagging\", \"estimate sGTM hosting costs\", or mentions \"server-side tagging\", \"sGTM\", or \"first-party data strategy\".

activeReaches the webInstructions only3,087 words

Filed under Analytics and reporting.

From Ad-Superpowers/ad-superpowers-plugin · 120 skills · 5 · pushed 2026-09-10

What it does when it runs

This skill should be used when the user asks to \"set up server-side GTM\", \"implement Meta CAPI via sGTM\", \"migrate from client-side to server-side tagging\", \"estimate sGTM hosting costs\", or mentions \"server-side tagging\", \"sGTM\", or \"first-party data strategy\". Do NOT use for: client-side GTM tag setup (use gtm-conversion-setup-guide), strategic tracking planning (use tracking-plan-builder), or consent mode implementation (use gtm-consent-mode-guide).

Read from the skill and the 0 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.

Keys and connectors you must supply
None found.
Hosts it reaches
  • api.yourdomain.com
  • sgtm.yourdomain.com
Tool permissions it declares
No allowed-tools in the frontmatter. It only issues instructions, so there is nothing to bound.
Actions present in the files
None. Instructions only.

Ask about gtm-server-side-tagging-guide

Opens your assistant with this page's verified links already in the prompt.

Is this safe to install?ClaudeChatGPT
Adapt it to my stackClaudeChatGPT
What else do I need for it to workClaudeChatGPT
Rather ask a human? Talk to Cheetah
git clone --depth 1 --filter=blob:none --sparse https://github.com/Ad-Superpowers/ad-superpowers-plugin.git /tmp/ad-superpowers-plugin
git -C /tmp/ad-superpowers-plugin sparse-checkout set "plugin/skills/gtm-server-side-tagging-guide"
mkdir -p ~/.claude/skills/gtm-server-side-tagging-guide
cp -R "/tmp/ad-superpowers-plugin/plugin/skills/gtm-server-side-tagging-guide/." ~/.claude/skills/gtm-server-side-tagging-guide/

Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗

Or take the whole library

This repo ships a .claude-plugin manifest, so Claude Code can install all 120 skills at once. Plugin skills are invoked as /<plugin>:<skill>, so they never collide with your own.

/plugin marketplace add Ad-Superpowers/ad-superpowers-plugin
/plugin

The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.

Reproduced in full from Ad-Superpowers/ad-superpowers-plugin/blob/9b6385d2d2d228e4dac096a1d6bc5715c04fa736/plugin/skills/gtm-server-side-tagging-guide/SKILL.md, which is licensed MIT (repository). 3,087 words, 44 headings.

Server-Side GTM Guide

Server-side Google Tag Manager (sGTM) moves tag execution from the visitor's browser to a server you control. Instead of loading multiple third-party scripts on the client, your browser sends a single request to your server, which then fans out events to GA4, Meta, Google Ads, LinkedIn, TikTok, and any other destination. This improves page speed, data quality, privacy compliance, and resilience against ad blockers.

When to Use sGTM: Decision Framework

sGTM is not free and not simple. Use this decision tree to determine whether it is right for your situation.

sGTM Decision Tree

Is accurate conversion tracking critical to your business?
|
+-- No ---> Stay client-side. sGTM adds cost and complexity you don't need.
|
+-- Yes
    |
    Are ad blockers or ITP (Safari) causing >15% data loss?
    |
    +-- No
    |   |
    |   Do you need Google Enhanced Conversions or LinkedIn CAPI?
    |   (Note: Meta CAPI is now mandatory — implement via sGTM or backend code)
    |   |
    |   +-- No ---> Stay client-side. sGTM won't add enough value.
    |   +-- Yes --> Consider sGTM. Server-side is the cleanest way to implement these.
    |
    +-- Yes
        |
        Is your monthly ad spend >EUR 5,000?
        |
        +-- No ---> The cost of sGTM may exceed the value recovered. Start with
        |           Enhanced Conversions client-side as a cheaper alternative.
        |
        +-- Yes --> sGTM is strongly recommended. The data quality improvement
                    will pay for itself in better optimization.

Benefits vs. Costs

BenefitImpactWho Benefits Most
First-party cookie controlExtends cookie lifetime from 7 days (ITP) to up to 400 daysSafari-heavy audiences (EU, mobile)
Ad blocker bypassRecovers 15-30% of lost eventsSites with tech-savvy audiences
Faster page loadsRemoves 3-8 third-party scripts from browserAll sites, especially mobile
Data enrichmentAdd server-side data (CRM, margin, LTV) to eventsE-commerce, SaaS
Single point of controlAll vendor tags managed server-sideMulti-platform advertisers
Privacy compliancePII never leaves your serverEU businesses under GDPR
Meta CAPI quality scoreScore 7+ with redundant setupAll Meta advertisers (CAPI is now mandatory for signal quality)
CostEstimate
HostingEUR 30-500/month depending on traffic
Setup time20-80 hours (depends on complexity)
Maintenance2-5 hours/month
Debugging complexityHigher than client-side
Team knowledgeRequires someone who understands HTTP, cookies, server infra

Architecture Overview

Client-Side Only (Before)

Browser                  Third-party servers
  |
  +---> gtm.js ---------> GA4 (analytics.google.com)
  +---> fbevents.js -----> Meta (connect.facebook.net)
  +---> ads.js ----------> Google Ads (googleads.g.doubleclick.net)
  +---> insight.js ------> LinkedIn (snap.licdn.com)
  +---> pixel.js --------> TikTok (analytics.tiktok.com)

5 third-party scripts, 5 network connections, 5 points of failure

Hybrid (Client + Server, Recommended)

Browser                   Your Server (sGTM)          Platforms
  |                           |
  +---> gtm.js               |
  |     (client container)    |
  |     |                     |
  |     +-- GA4 Config -------> First-party endpoint
  |     |   (transport_url)    |
  |     |                      +--> GA4 (Measurement Protocol)
  |     +-- dataLayer events   +--> Meta (Conversions API)
  |         via HTTP POST ---->+--> Google Ads (Enhanced Conv.)
  |                            +--> LinkedIn (CAPI)
  |                            +--> TikTok (Events API)
  |
  +---> fbevents.js (optional, for dedup + fallback)

1 first-party request + optional client pixels for redundancy

Full Server-Side (Advanced)

Browser                   Your Server (sGTM)          Platforms
  |                           |
  +-- Single HTTP request --> |
      (custom fetch/beacon)   +--> GA4
                              +--> Meta CAPI
                              +--> Google Ads
                              +--> LinkedIn CAPI
                              +--> TikTok Events API

No third-party scripts at all. Maximum speed and control.
Requires custom client-side code (no GTM client container).

Hosting Options

Option 1: Google Cloud Run (Official)

Google's recommended hosting. The sGTM container runs as a Cloud Run service.

AspectDetail
SetupGTM UI > Admin > Install Tag Manager > Server-side > Auto-provision
ScalingAuto-scales 0 to N instances based on traffic
RegionChoose EU (europe-west1) for GDPR compliance
Min instancesSet to 1-3 for production (avoids cold starts)
CPU allocation"CPU is always allocated" for consistent performance

Cost Estimation (Google Cloud Run):

Monthly EventsEstimated Cost (EUR)Notes
100,00015-301 min instance, low CPU
500,00040-802 min instances
1,000,00070-1503 min instances
5,000,000200-4005-8 min instances
10,000,000350-7008-15 min instances
50,000,000+700-2,000Auto-scaling, consider reserved instances

Setup Steps:

  1. Create a Google Cloud project (or use existing)
  2. Enable billing on the project
  3. In GTM, create a Server container
  4. Choose "Automatically provision tagging server"
  5. Select Cloud Run region (pick EU for EU businesses)
  6. GTM creates the Cloud Run service automatically
  7. Set min instances to at least 1 in Cloud Run console
  8. Configure custom domain (see Custom Domain section below)

Option 2: Stape.io (Managed)

Easiest option. Stape manages the infrastructure.

AspectDetail
Setup10 minutes, no cloud console needed
PricingFrom EUR 20/month (500k events) to EUR 200+/month
FeaturesCustom domain, auto-SSL, EU hosting, preview mode support
Best forTeams without DevOps/cloud infrastructure expertise

Stape Pricing (as of 2026):

PlanMonthly EventsPrice (EUR)
Starter500,000~20
Business2,000,000~50
Pro10,000,000~150
EnterpriseCustomCustom

Option 3: AWS / Other Cloud

For teams already on AWS or Azure. Run the sGTM Docker image on ECS, Fargate, or App Service.

AspectDetail
Docker imagegcr.io/cloud-tagging-10302018/gtm-cloud-image:stable
Required env varsCONTAINER_CONFIG (from GTM UI), PORT (default 8080)
Load balancerRequired (ALB on AWS, App Gateway on Azure)
Auto-scalingConfigure based on CPU/request count
Estimated costSimilar to GCR, depends on instance type

Hosting Comparison

FactorGoogle Cloud RunStape.ioAWS/Azure
Setup time30-60 min10 min2-4 hours
Technical skillMediumLowHigh
Cost controlFullLimitedFull
EU hostingYesYesYes
Custom domainManualBuilt-inManual
Preview serverSeparate instanceBuilt-inSeparate instance
Vendor lock-inLow (Docker image)MediumLow

Custom Domain Setup (Critical)

Without a custom domain, your sGTM server uses a Google Cloud URL. This means requests are still "third-party" and gain no cookie benefit. A custom domain makes your server first-party.

Steps

  1. Choose a subdomain: sgtm.yourdomain.com or data.yourdomain.com
  2. Create DNS record: CNAME pointing to your Cloud Run service URL
  3. Configure SSL: Automatic via Cloud Run, or via Stape
  4. Update GTM client container: Set transport_url in Google Tag to https://sgtm.yourdomain.com
  5. Set cookie domain: Configure the GA4 client in sGTM to set cookies on .yourdomain.com

DNS Record Example

Type: CNAME
Name: sgtm
Value: your-service-abc123-ew.a.run.app
TTL: 300

First-Party Cookie Configuration

In the sGTM container, the GA4 client automatically sets a _ga-equivalent cookie. Because the request goes to your subdomain, the cookie is first-party and not subject to ITP 7-day expiry.

CookieDomainLifetimePurpose
_ga (server-set).yourdomain.comUp to 400 daysGA client ID
_ga_XXXXX.yourdomain.comUp to 400 daysGA session data
FPID.yourdomain.comUp to 400 daysFirst-party ID for sGTM

Migration: Client-Side to Server-Side

Do not rip out client-side tags and go full server-side in one step. Use a phased approach.

Phase 1: Parallel (Week 1-2)

Run both client-side and server-side simultaneously. Compare event counts.

Client GTM Container:
  - GA4 Config tag: add transport_url = https://sgtm.yourdomain.com
  - All other tags: keep as-is (still fire client-side)

Server GTM Container:
  - GA4 Client: receives forwarded GA4 hits
  - GA4 Tag: sends to GA4 property (same as client-side)

Result: GA4 receives events from BOTH client and server.
Use GA4 DebugView to confirm both paths work.
Deduplicate via measurement_protocol_secret or disable client direct sends.

Phase 2: Add Server-Side Destinations (Week 2-4)

Add Meta CAPI, Google Ads Enhanced Conversions, etc. as server-side tags.

Server GTM Container:
  - GA4 Client (receiving from client)
  - GA4 Tag (forwarding to GA4)
  - Meta CAPI Tag (NEW - sending to Meta server-side)
  - Google Ads Enhanced Conversions Tag (NEW)
  - LinkedIn CAPI Tag (NEW, if supported)

Client GTM Container:
  - Keep Meta Pixel (redundant, for dedup)
  - Keep LinkedIn Insight Tag (redundant, for dedup)

Phase 3: Reduce Client-Side (Week 4-8)

Once server-side events are confirmed working and deduplicated, remove redundant client-side tags.

Client GTM Container:
  - GA4 Config (with transport_url pointing to sGTM)
  - Meta Pixel base code (for dedup event_id matching only)
  - Remove: standalone Meta event tags
  - Remove: LinkedIn Insight Tag (if CAPI covers it)
  - Remove: TikTok Pixel (if Events API covers it)

Server GTM Container:
  - Handles all conversion forwarding

Phase 4: Optimize (Month 2+)

  • Add data enrichment (CRM data, margin, LTV)
  • Implement consent-aware server-side processing
  • Remove remaining unnecessary client-side scripts
  • Monitor and tune server costs

Server-Side Clients (Receiving Data)

Clients in sGTM receive incoming HTTP requests and parse them into an event data object that tags can use.

GA4 Client (Built-In)

SettingRecommended Value
PriorityDefault
GA4 Measurement ID AllowlistAdd your G-XXXXXXXXXX IDs
Default GA4 paths/g/collect, /j/collect
Set cookie on.yourdomain.com
FPID cookie lifetime400 days
JavaScript managedNot required (auto)

The GA4 client intercepts requests from the client-side Google Tag (when transport_url points to your sGTM server) and creates an event data object.

Custom Client (Webhook)

For receiving events from your backend (not browser-initiated):

// Custom client template
const claimRequest = require('claimRequest');
const getRequestBody = require('getRequestBody');
const getRequestHeader = require('getRequestHeader');
const JSON = require('JSON');
const runContainer = require('runContainer');

// Only claim POST requests to /webhook
if (getRequestHeader('method') === 'POST' && 
    getRequestPath().indexOf('/webhook') === 0) {
  
  claimRequest();
  
  const body = JSON.parse(getRequestBody());
  
  const eventData = {
    event_name: body.event,
    // Map your webhook fields to event data
  };
  
  runContainer(eventData, () => {
    // Response after all tags fire
  });
}

Server-Side Tags (Sending Data)

Meta Conversions API Tag

The official Meta CAPI tag template is available in the sGTM Community Template Gallery.

SettingValue
Tag TemplateFacebook Conversions API (Community)
API Access TokenYour Meta CAPI token (from Events Manager)
Pixel IDYour Meta Pixel ID
Action Sourcewebsite
Event NameMap from event_data (e.g., Purchase)
Event IDMust match client-side eventID for dedup

Required User Data (for matching):

FieldSourceHashing
Emailevent_data.user_data.email_addressAuto-hashed (SHA256)
Phoneevent_data.user_data.phone_numberAuto-hashed
First Nameevent_data.user_data.address.first_nameAuto-hashed
Last Nameevent_data.user_data.address.last_nameAuto-hashed
Cityevent_data.user_data.address.cityAuto-hashed
Countryevent_data.user_data.address.countryPlain
IP Addressevent_data.ip_overridePlain (auto-populated)
User Agentevent_data.user_agentPlain (auto-populated)
FBCevent_data.fbcPlain (from _fbc cookie)
FBPevent_data.fbpPlain (from _fbp cookie)

Deduplication:

Meta deduplicates events by matching event_name + event_id. The event_id sent from the client-side Pixel must match the event_id sent from the server-side CAPI tag.

In your client-side GTM:

// Generate event_id and push to dataLayer
var eventId = 'evt_' + Date.now() + '_' + Math.random().toString(36).substr(2,9);
dataLayer.push({ event: 'purchase', event_id: eventId, ecommerce: { ... } });

In the Meta Pixel tag (client-side):

fbq('track', 'Purchase', { value: 50, currency: 'EUR' }, { eventID: eventId });

In the sGTM Meta CAPI tag: map event_data.event_id to the Event ID field.

Google Ads Enhanced Conversions Tag

SettingValue
Tag TypeGoogle Ads Conversion Tracking (built-in)
Conversion IDAW-XXXXXXXXX
Conversion LabelXXXXXXXXXXXXXXX
Include user-provided dataEnable
Emailevent_data.user_data.email_address
Phoneevent_data.user_data.phone_number
AddressFrom event_data.user_data.address.*

LinkedIn Conversions API

LinkedIn supports server-side conversion tracking via their Conversions API. As of 2026, there is a community sGTM tag template.

SettingValue
API TokenLinkedIn CAPI access token
Conversion Rule IDFrom LinkedIn Campaign Manager
User identifiersEmail (SHA256 hashed), LinkedIn first-party ID

TikTok Events API

TikTok also supports server-side event sending. Community sGTM tag template available.

SettingValue
Access TokenTikTok Events API token
Pixel IDTikTok Pixel ID
EventCompletePayment, SubmitForm, etc.
User dataEmail, phone (hashed), IP, user agent

Event Data Enrichment

One of the most powerful sGTM features: enrich events with server-side data before sending to platforms.

Common Enrichment Patterns

EnrichmentSourceBenefit
Customer LTVCRM / database lookupBetter Smart Bidding (tROAS)
Profit marginProduct databaseValue-based bidding on margin, not revenue
Customer segmentCRMAudience targeting signals
Lead scoreCRM / marketing automationSend qualified leads only
Offline conversionCRM (delayed)Feed back sales data to ad platforms
Cart contentsBackend sessionMore accurate than client-side scraping

Enrichment via Firestore Lookup (Example)

Trigger: purchase event arrives at sGTM

1. Extract customer_id from event_data
2. Firestore lookup: customers/{customer_id}
3. Get: ltv_score, customer_segment, first_purchase_date
4. Add to event_data:
   - event_data['x-ltv-score'] = ltv_score
   - event_data['x-customer-segment'] = customer_segment
   - event_data['x-new-customer'] = (first_purchase_date == today)
5. GA4 tag sends enriched data
6. Google Ads tag uses x-new-customer for New Customer Acquisition

Enrichment via HTTP Request (API Lookup)

Use the sGTM sendHttpRequest API to call your own backend:

const sendHttpRequest = require('sendHttpRequest');
const JSON = require('JSON');

sendHttpRequest('https://api.yourdomain.com/enrich', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ...' },
  body: JSON.stringify({ transaction_id: event_data.transaction_id })
}, (statusCode, headers, body) => {
  const data = JSON.parse(body);
  // Add enriched data to event
});

Debugging Server-Side Tags

sGTM Preview Mode

  1. In GTM Server container, click "Preview"
  2. Send a test event from your website (with client GTM in Preview mode)
  3. The sGTM Preview panel shows:
    • Incoming request details
    • Which client claimed the request
    • Event data object created
    • Which tags fired and their responses
    • Outgoing HTTP requests (to GA4, Meta, etc.)

Debugging Checklist

CheckHow
Events reaching sGTM?Check sGTM Preview > Requests tab
Client claiming request?Check sGTM Preview > Client tab (should show "Claimed")
Event data populated?Check sGTM Preview > Event Data tab
Tags firing?Check sGTM Preview > Tags tab
Tags succeeding?Check HTTP response codes (200 = success)
Meta CAPI received?Meta Events Manager > Test Events > Server
GA4 received?GA4 DebugView or Real-time reports
Google Ads received?Google Ads > Tools > Conversions > Diagnostics

Common Server-Side Issues

IssueCauseFix
0 events in sGTMtransport_url not set in client GA4Add transport_url to Google Tag
Client not claimingRequest path doesn't match client configCheck client path settings
Meta CAPI 400 errorMissing required fields (access token, pixel ID)Verify CAPI configuration
Meta Event Match Quality lowMissing user data (email, phone, fbp, fbc)Pass user data in dataLayer
Duplicate events in GA4Both client and server sendingDisable direct GA4 sends from client
Cookie not first-partyCustom domain not configuredSet up CNAME for sGTM subdomain
High latencyCold starts (0 min instances)Set min instances to 1+

When NOT to Use sGTM

sGTM is not always the right answer. Skip it when:

SituationWhy
Monthly ad spend < EUR 2,000Cost of sGTM exceeds attribution value recovered
Simple website (brochure site)No conversions to track server-side
No technical resourcesOngoing maintenance requires server/cloud knowledge
Single platform (GA4 only)Client-side GA4 with transport_url gives most benefits
Low traffic (< 10k monthly visits)Client-side tracking is sufficient
No privacy requirementsAd blocker bypass alone may not justify the cost

Cheaper Alternatives to Full sGTM:

AlternativeCostBenefit
GA4 Google Tag with transport_urlFree (uses Google's proxy)First-party cookies for GA4
Meta CAPI via backend codeFree (dev time only)Server-side Meta without sGTM
Google Ads Enhanced Conversions (client)FreeBetter attribution without server
LinkedIn offline conversions uploadFreeFeed CRM data to LinkedIn

MCP Tools for sGTM

Auditing Your Setup

Use gtm_audit to inspect both your client-side and server-side GTM containers:

# Audit client container
gtm_audit(container_path="accounts/123456/containers/CLIENT_ID")
-> Check: transport_url configured, event_id generation, user_data passing

# Audit server container  
gtm_audit(container_path="accounts/123456/containers/SERVER_ID")
-> Check: clients configured, tags for each platform, enrichment tags

Verifying Data Flow

Use ga4_run_report to compare event volumes before and after sGTM migration:

ga4_run_report(
  property_id="...",
  dimensions=["eventName", "platform"],
  metrics=["eventCount"],
  start_date="7daysAgo",
  end_date="today"
)

Compare:
- Event counts before sGTM vs. after
- Expect 10-30% increase in tracked events (recovered from ad blockers)
- Expect improved session duration and engagement metrics

Other skills for the same job

Different authors, same problem. Matched on the words in the skill name, across every library in the catalogue except this one.

Need help setting it up?

This page tells you what gtm-server-side-tagging-guide does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.

Book a call →

The directory stays free. There is nothing gated behind this.