[{"data":1,"prerenderedAt":1534},["ShallowReactive",2],{"content-query-GLReVOiDDi":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"layout":10,"head":11,"author":13,"tags":14,"categories":20,"date":22,"image":23,"faq":24,"excerpt":34,"body":50,"_type":1527,"_id":1528,"_source":1529,"_file":1530,"_stem":1531,"_extension":1532,"sitemap":1533},"/blog/server-side-google-tag-manager-webhooks","blog",false,"","Send Webhooks to Server-Side Google Tag Manager (sGTM)","Forward webhooks to a server-side Google Tag Manager container, reshape events for an sGTM client, and debug them safely in Preview mode.","post",{"title":12},"Server-Side Google Tag Manager Webhooks (sGTM)","Karolis Rusenas",[15,16,17,18,19],"google tag manager","sgtm","webhooks","analytics","transformations",[21],"integrations","2026-09-06 09:30:00","/images/blog/heroes/route.jpg",[25,28,31],{"q":26,"a":27},"Can server-side Google Tag Manager receive webhooks?","Yes, if the server container has a client that recognizes the incoming path and request format. Webhook Relay can receive the provider event, map it into that format, and forward it to the tagging server.",{"q":29,"a":30},"Why does an sGTM request appear in production but not Preview mode?","Preview traffic must be associated with the active Tag Assistant session. Capture the preview header value for that session, store it as a Webhook Relay function configuration value, and add it only to development traffic.",{"q":32,"a":33},"Should I send arbitrary webhook JSON to an sGTM URL?","Not unless a server-side client is configured to claim that request. Use a custom client or transform the event into a protocol already handled by a client in your container.",{"type":35,"children":36},"root",[37,45],{"type":38,"tag":39,"props":40,"children":41},"element","p",{},[42],{"type":43,"value":44},"text","Server-side Google Tag Manager can receive more than browser analytics hits. With the right server-side client, it can also accept backend events such as completed orders, subscription changes or CRM updates. The missing piece is often payload compatibility: the source sends one webhook shape, while the sGTM client expects another path, body and set of headers.",{"type":38,"tag":39,"props":46,"children":47},{},[48],{"type":43,"value":49},"Webhook Relay can receive the original event, transform it into the contract expected by your sGTM client, and forward it to the tagging server. It also gives you delivery logs and a controlled way to route development events into an active Preview session.",{"type":35,"children":51,"toc":1512},[52,56,60,67,174,198,204,209,243,256,408,413,419,433,447,452,458,463,626,631,1123,1128,1134,1155,1160,1257,1270,1281,1295,1301,1306,1368,1373,1379,1427,1433,1440,1445,1451,1456,1462,1467,1473,1486,1506],{"type":38,"tag":39,"props":53,"children":54},{},[55],{"type":43,"value":44},{"type":38,"tag":39,"props":57,"children":58},{},[59],{"type":43,"value":49},{"type":38,"tag":61,"props":62,"children":64},"h2",{"id":63},"architecture",[65],{"type":43,"value":66},"Architecture",{"type":38,"tag":68,"props":69,"children":72},"pre",{"className":70,"code":71,"language":43,"meta":7,"style":7},"language-text shiki shiki-themes github-dark","commerce / billing / CRM webhook\n                 |\n                 v\n       Webhook Relay input\n        validate + reshape\n                 |\n                 v\n       sGTM tagging server\n                 |\n                 v\n       client -> tags -> vendors\n",[73],{"type":38,"tag":74,"props":75,"children":76},"code",{"__ignoreMap":7},[77,88,97,106,115,124,132,140,149,157,165],{"type":38,"tag":78,"props":79,"children":82},"span",{"class":80,"line":81},"line",1,[83],{"type":38,"tag":78,"props":84,"children":85},{},[86],{"type":43,"value":87},"commerce / billing / CRM webhook\n",{"type":38,"tag":78,"props":89,"children":91},{"class":80,"line":90},2,[92],{"type":38,"tag":78,"props":93,"children":94},{},[95],{"type":43,"value":96},"                 |\n",{"type":38,"tag":78,"props":98,"children":100},{"class":80,"line":99},3,[101],{"type":38,"tag":78,"props":102,"children":103},{},[104],{"type":43,"value":105},"                 v\n",{"type":38,"tag":78,"props":107,"children":109},{"class":80,"line":108},4,[110],{"type":38,"tag":78,"props":111,"children":112},{},[113],{"type":43,"value":114},"       Webhook Relay input\n",{"type":38,"tag":78,"props":116,"children":118},{"class":80,"line":117},5,[119],{"type":38,"tag":78,"props":120,"children":121},{},[122],{"type":43,"value":123},"        validate + reshape\n",{"type":38,"tag":78,"props":125,"children":127},{"class":80,"line":126},6,[128],{"type":38,"tag":78,"props":129,"children":130},{},[131],{"type":43,"value":96},{"type":38,"tag":78,"props":133,"children":135},{"class":80,"line":134},7,[136],{"type":38,"tag":78,"props":137,"children":138},{},[139],{"type":43,"value":105},{"type":38,"tag":78,"props":141,"children":143},{"class":80,"line":142},8,[144],{"type":38,"tag":78,"props":145,"children":146},{},[147],{"type":43,"value":148},"       sGTM tagging server\n",{"type":38,"tag":78,"props":150,"children":152},{"class":80,"line":151},9,[153],{"type":38,"tag":78,"props":154,"children":155},{},[156],{"type":43,"value":96},{"type":38,"tag":78,"props":158,"children":160},{"class":80,"line":159},10,[161],{"type":38,"tag":78,"props":162,"children":163},{},[164],{"type":43,"value":105},{"type":38,"tag":78,"props":166,"children":168},{"class":80,"line":167},11,[169],{"type":38,"tag":78,"props":170,"children":171},{},[172],{"type":43,"value":173},"       client -> tags -> vendors\n",{"type":38,"tag":39,"props":175,"children":176},{},[177,179,188,190,196],{"type":43,"value":178},"Google's ",{"type":38,"tag":180,"props":181,"children":185},"a",{"href":182,"rel":183},"https://developers.google.com/tag-platform/tag-manager/server-side/intro",[184],"nofollow",[186],{"type":43,"value":187},"server-side tagging introduction",{"type":43,"value":189}," explains the core model: a ",{"type":38,"tag":191,"props":192,"children":193},"strong",{},[194],{"type":43,"value":195},"client",{"type":43,"value":197}," claims an incoming HTTP request, turns it into event data, and then tags use that event. A generic webhook will not automatically become an sGTM event. Your container must have a client that recognizes it.",{"type":38,"tag":61,"props":199,"children":201},{"id":200},"before-you-start",[202],{"type":43,"value":203},"Before you start",{"type":38,"tag":39,"props":205,"children":206},{},[207],{"type":43,"value":208},"You need:",{"type":38,"tag":210,"props":211,"children":212},"ul",{},[213,219,233,238],{"type":38,"tag":214,"props":215,"children":216},"li",{},[217],{"type":43,"value":218},"A published server-side GTM container.",{"type":38,"tag":214,"props":220,"children":221},{},[222,224,231],{"type":43,"value":223},"A tagging-server URL, ideally on a ",{"type":38,"tag":180,"props":225,"children":228},{"href":226,"rel":227},"https://developers.google.com/tag-platform/tag-manager/server-side/custom-domain",[184],[229],{"type":43,"value":230},"first-party custom domain",{"type":43,"value":232},".",{"type":38,"tag":214,"props":234,"children":235},{},[236],{"type":43,"value":237},"A client that accepts your chosen path and payload, or a documented protocol you can transform into.",{"type":38,"tag":214,"props":239,"children":240},{},[241],{"type":43,"value":242},"A Webhook Relay bucket with a public input and the tagging-server URL as its output.",{"type":38,"tag":39,"props":244,"children":245},{},[246,248,254],{"type":43,"value":247},"This example assumes a custom client claims ",{"type":38,"tag":74,"props":249,"children":251},{"className":250},[],[252],{"type":43,"value":253},"POST /events",{"type":43,"value":255}," with JSON shaped like this:",{"type":38,"tag":68,"props":257,"children":261},{"className":258,"code":259,"language":260,"meta":7,"style":7},"language-json shiki shiki-themes github-dark","{\n  \"event_name\": \"purchase\",\n  \"event_id\": \"evt_123\",\n  \"timestamp\": \"2026-09-06T08:30:00Z\",\n  \"user_id\": \"user_456\",\n  \"value\": 49.95,\n  \"currency\": \"EUR\"\n}\n","json",[262],{"type":38,"tag":74,"props":263,"children":264},{"__ignoreMap":7},[265,274,299,320,341,362,383,400],{"type":38,"tag":78,"props":266,"children":267},{"class":80,"line":81},[268],{"type":38,"tag":78,"props":269,"children":271},{"style":270},"--shiki-default:#E1E4E8",[272],{"type":43,"value":273},"{\n",{"type":38,"tag":78,"props":275,"children":276},{"class":80,"line":90},[277,283,288,294],{"type":38,"tag":78,"props":278,"children":280},{"style":279},"--shiki-default:#79B8FF",[281],{"type":43,"value":282},"  \"event_name\"",{"type":38,"tag":78,"props":284,"children":285},{"style":270},[286],{"type":43,"value":287},": ",{"type":38,"tag":78,"props":289,"children":291},{"style":290},"--shiki-default:#9ECBFF",[292],{"type":43,"value":293},"\"purchase\"",{"type":38,"tag":78,"props":295,"children":296},{"style":270},[297],{"type":43,"value":298},",\n",{"type":38,"tag":78,"props":300,"children":301},{"class":80,"line":99},[302,307,311,316],{"type":38,"tag":78,"props":303,"children":304},{"style":279},[305],{"type":43,"value":306},"  \"event_id\"",{"type":38,"tag":78,"props":308,"children":309},{"style":270},[310],{"type":43,"value":287},{"type":38,"tag":78,"props":312,"children":313},{"style":290},[314],{"type":43,"value":315},"\"evt_123\"",{"type":38,"tag":78,"props":317,"children":318},{"style":270},[319],{"type":43,"value":298},{"type":38,"tag":78,"props":321,"children":322},{"class":80,"line":108},[323,328,332,337],{"type":38,"tag":78,"props":324,"children":325},{"style":279},[326],{"type":43,"value":327},"  \"timestamp\"",{"type":38,"tag":78,"props":329,"children":330},{"style":270},[331],{"type":43,"value":287},{"type":38,"tag":78,"props":333,"children":334},{"style":290},[335],{"type":43,"value":336},"\"2026-09-06T08:30:00Z\"",{"type":38,"tag":78,"props":338,"children":339},{"style":270},[340],{"type":43,"value":298},{"type":38,"tag":78,"props":342,"children":343},{"class":80,"line":117},[344,349,353,358],{"type":38,"tag":78,"props":345,"children":346},{"style":279},[347],{"type":43,"value":348},"  \"user_id\"",{"type":38,"tag":78,"props":350,"children":351},{"style":270},[352],{"type":43,"value":287},{"type":38,"tag":78,"props":354,"children":355},{"style":290},[356],{"type":43,"value":357},"\"user_456\"",{"type":38,"tag":78,"props":359,"children":360},{"style":270},[361],{"type":43,"value":298},{"type":38,"tag":78,"props":363,"children":364},{"class":80,"line":126},[365,370,374,379],{"type":38,"tag":78,"props":366,"children":367},{"style":279},[368],{"type":43,"value":369},"  \"value\"",{"type":38,"tag":78,"props":371,"children":372},{"style":270},[373],{"type":43,"value":287},{"type":38,"tag":78,"props":375,"children":376},{"style":279},[377],{"type":43,"value":378},"49.95",{"type":38,"tag":78,"props":380,"children":381},{"style":270},[382],{"type":43,"value":298},{"type":38,"tag":78,"props":384,"children":385},{"class":80,"line":134},[386,391,395],{"type":38,"tag":78,"props":387,"children":388},{"style":279},[389],{"type":43,"value":390},"  \"currency\"",{"type":38,"tag":78,"props":392,"children":393},{"style":270},[394],{"type":43,"value":287},{"type":38,"tag":78,"props":396,"children":397},{"style":290},[398],{"type":43,"value":399},"\"EUR\"\n",{"type":38,"tag":78,"props":401,"children":402},{"class":80,"line":142},[403],{"type":38,"tag":78,"props":404,"children":405},{"style":270},[406],{"type":43,"value":407},"}\n",{"type":38,"tag":39,"props":409,"children":410},{},[411],{"type":43,"value":412},"Change the path and fields to match your client. Do not copy this contract into production unless your sGTM container is configured to accept it.",{"type":38,"tag":61,"props":414,"children":416},{"id":415},"_1-create-the-public-webhook-input",[417],{"type":43,"value":418},"1. Create the public webhook input",{"type":38,"tag":39,"props":420,"children":421},{},[422,424,431],{"type":43,"value":423},"Create a ",{"type":38,"tag":180,"props":425,"children":428},{"href":426,"rel":427},"https://my.webhookrelay.com/new-public-destination",[184],[429],{"type":43,"value":430},"public destination",{"type":43,"value":432}," and set its destination to your tagging server, for example:",{"type":38,"tag":68,"props":434,"children":436},{"className":70,"code":435,"language":43,"meta":7,"style":7},"https://metrics.example.com\n",[437],{"type":38,"tag":74,"props":438,"children":439},{"__ignoreMap":7},[440],{"type":38,"tag":78,"props":441,"children":442},{"class":80,"line":81},[443],{"type":38,"tag":78,"props":444,"children":445},{},[446],{"type":43,"value":435},{"type":38,"tag":39,"props":448,"children":449},{},[450],{"type":43,"value":451},"Copy the generated Webhook Relay input URL and register it with the service sending the original webhook.",{"type":38,"tag":61,"props":453,"children":455},{"id":454},"_2-transform-the-provider-payload",[456],{"type":43,"value":457},"2. Transform the provider payload",{"type":38,"tag":39,"props":459,"children":460},{},[461],{"type":43,"value":462},"Suppose the source sends an order event:",{"type":38,"tag":68,"props":464,"children":466},{"className":258,"code":465,"language":260,"meta":7,"style":7},"{\n  \"id\": \"ord_123\",\n  \"type\": \"order.completed\",\n  \"created_at\": \"2026-09-06T08:30:00Z\",\n  \"customer\": { \"id\": \"user_456\" },\n  \"total\": { \"amount\": 49.95, \"currency\": \"EUR\" }\n}\n",[467],{"type":38,"tag":74,"props":468,"children":469},{"__ignoreMap":7},[470,477,498,519,539,570,619],{"type":38,"tag":78,"props":471,"children":472},{"class":80,"line":81},[473],{"type":38,"tag":78,"props":474,"children":475},{"style":270},[476],{"type":43,"value":273},{"type":38,"tag":78,"props":478,"children":479},{"class":80,"line":90},[480,485,489,494],{"type":38,"tag":78,"props":481,"children":482},{"style":279},[483],{"type":43,"value":484},"  \"id\"",{"type":38,"tag":78,"props":486,"children":487},{"style":270},[488],{"type":43,"value":287},{"type":38,"tag":78,"props":490,"children":491},{"style":290},[492],{"type":43,"value":493},"\"ord_123\"",{"type":38,"tag":78,"props":495,"children":496},{"style":270},[497],{"type":43,"value":298},{"type":38,"tag":78,"props":499,"children":500},{"class":80,"line":99},[501,506,510,515],{"type":38,"tag":78,"props":502,"children":503},{"style":279},[504],{"type":43,"value":505},"  \"type\"",{"type":38,"tag":78,"props":507,"children":508},{"style":270},[509],{"type":43,"value":287},{"type":38,"tag":78,"props":511,"children":512},{"style":290},[513],{"type":43,"value":514},"\"order.completed\"",{"type":38,"tag":78,"props":516,"children":517},{"style":270},[518],{"type":43,"value":298},{"type":38,"tag":78,"props":520,"children":521},{"class":80,"line":108},[522,527,531,535],{"type":38,"tag":78,"props":523,"children":524},{"style":279},[525],{"type":43,"value":526},"  \"created_at\"",{"type":38,"tag":78,"props":528,"children":529},{"style":270},[530],{"type":43,"value":287},{"type":38,"tag":78,"props":532,"children":533},{"style":290},[534],{"type":43,"value":336},{"type":38,"tag":78,"props":536,"children":537},{"style":270},[538],{"type":43,"value":298},{"type":38,"tag":78,"props":540,"children":541},{"class":80,"line":117},[542,547,552,557,561,565],{"type":38,"tag":78,"props":543,"children":544},{"style":279},[545],{"type":43,"value":546},"  \"customer\"",{"type":38,"tag":78,"props":548,"children":549},{"style":270},[550],{"type":43,"value":551},": { ",{"type":38,"tag":78,"props":553,"children":554},{"style":279},[555],{"type":43,"value":556},"\"id\"",{"type":38,"tag":78,"props":558,"children":559},{"style":270},[560],{"type":43,"value":287},{"type":38,"tag":78,"props":562,"children":563},{"style":290},[564],{"type":43,"value":357},{"type":38,"tag":78,"props":566,"children":567},{"style":270},[568],{"type":43,"value":569}," },\n",{"type":38,"tag":78,"props":571,"children":572},{"class":80,"line":126},[573,578,582,587,591,595,600,605,609,614],{"type":38,"tag":78,"props":574,"children":575},{"style":279},[576],{"type":43,"value":577},"  \"total\"",{"type":38,"tag":78,"props":579,"children":580},{"style":270},[581],{"type":43,"value":551},{"type":38,"tag":78,"props":583,"children":584},{"style":279},[585],{"type":43,"value":586},"\"amount\"",{"type":38,"tag":78,"props":588,"children":589},{"style":270},[590],{"type":43,"value":287},{"type":38,"tag":78,"props":592,"children":593},{"style":279},[594],{"type":43,"value":378},{"type":38,"tag":78,"props":596,"children":597},{"style":270},[598],{"type":43,"value":599},", ",{"type":38,"tag":78,"props":601,"children":602},{"style":279},[603],{"type":43,"value":604},"\"currency\"",{"type":38,"tag":78,"props":606,"children":607},{"style":270},[608],{"type":43,"value":287},{"type":38,"tag":78,"props":610,"children":611},{"style":290},[612],{"type":43,"value":613},"\"EUR\"",{"type":38,"tag":78,"props":615,"children":616},{"style":270},[617],{"type":43,"value":618}," }\n",{"type":38,"tag":78,"props":620,"children":621},{"class":80,"line":134},[622],{"type":38,"tag":78,"props":623,"children":624},{"style":270},[625],{"type":43,"value":407},{"type":38,"tag":39,"props":627,"children":628},{},[629],{"type":43,"value":630},"Attach this JavaScript function to the sGTM output:",{"type":38,"tag":68,"props":632,"children":636},{"className":633,"code":634,"language":635,"meta":7,"style":7},"language-javascript shiki shiki-themes github-dark","const source = JSON.parse(r.body)\n\nif (source.type !== \"order.completed\") {\n  r.stopForwarding()\n  return\n}\n\nconst event = {\n  event_name: \"purchase\",\n  event_id: source.id,\n  timestamp: source.created_at,\n  user_id: source.customer && source.customer.id,\n  value: source.total && source.total.amount,\n  currency: source.total && source.total.currency\n}\n\nif (!event.event_id || !event.user_id || !event.currency) {\n  r.stopForwarding()\n  return\n}\n\nr.setMethod(\"POST\")\nr.setPath(\"/events\")\nr.setRawQuery(\"\")\nr.setHeader(\"Content-Type\", \"application/json\")\nr.setBody(JSON.stringify(event))\n","javascript",[637],{"type":38,"tag":74,"props":638,"children":639},{"__ignoreMap":7},[640,679,688,716,734,742,749,756,777,793,801,809,828,846,864,872,880,931,947,955,963,971,1000,1026,1052,1087],{"type":38,"tag":78,"props":641,"children":642},{"class":80,"line":81},[643,649,654,659,664,668,674],{"type":38,"tag":78,"props":644,"children":646},{"style":645},"--shiki-default:#F97583",[647],{"type":43,"value":648},"const",{"type":38,"tag":78,"props":650,"children":651},{"style":279},[652],{"type":43,"value":653}," source",{"type":38,"tag":78,"props":655,"children":656},{"style":645},[657],{"type":43,"value":658}," =",{"type":38,"tag":78,"props":660,"children":661},{"style":279},[662],{"type":43,"value":663}," JSON",{"type":38,"tag":78,"props":665,"children":666},{"style":270},[667],{"type":43,"value":232},{"type":38,"tag":78,"props":669,"children":671},{"style":670},"--shiki-default:#B392F0",[672],{"type":43,"value":673},"parse",{"type":38,"tag":78,"props":675,"children":676},{"style":270},[677],{"type":43,"value":678},"(r.body)\n",{"type":38,"tag":78,"props":680,"children":681},{"class":80,"line":90},[682],{"type":38,"tag":78,"props":683,"children":685},{"emptyLinePlaceholder":684},true,[686],{"type":43,"value":687},"\n",{"type":38,"tag":78,"props":689,"children":690},{"class":80,"line":99},[691,696,701,706,711],{"type":38,"tag":78,"props":692,"children":693},{"style":645},[694],{"type":43,"value":695},"if",{"type":38,"tag":78,"props":697,"children":698},{"style":270},[699],{"type":43,"value":700}," (source.type ",{"type":38,"tag":78,"props":702,"children":703},{"style":645},[704],{"type":43,"value":705},"!==",{"type":38,"tag":78,"props":707,"children":708},{"style":290},[709],{"type":43,"value":710}," \"order.completed\"",{"type":38,"tag":78,"props":712,"children":713},{"style":270},[714],{"type":43,"value":715},") {\n",{"type":38,"tag":78,"props":717,"children":718},{"class":80,"line":108},[719,724,729],{"type":38,"tag":78,"props":720,"children":721},{"style":270},[722],{"type":43,"value":723},"  r.",{"type":38,"tag":78,"props":725,"children":726},{"style":670},[727],{"type":43,"value":728},"stopForwarding",{"type":38,"tag":78,"props":730,"children":731},{"style":270},[732],{"type":43,"value":733},"()\n",{"type":38,"tag":78,"props":735,"children":736},{"class":80,"line":117},[737],{"type":38,"tag":78,"props":738,"children":739},{"style":645},[740],{"type":43,"value":741},"  return\n",{"type":38,"tag":78,"props":743,"children":744},{"class":80,"line":126},[745],{"type":38,"tag":78,"props":746,"children":747},{"style":270},[748],{"type":43,"value":407},{"type":38,"tag":78,"props":750,"children":751},{"class":80,"line":134},[752],{"type":38,"tag":78,"props":753,"children":754},{"emptyLinePlaceholder":684},[755],{"type":43,"value":687},{"type":38,"tag":78,"props":757,"children":758},{"class":80,"line":142},[759,763,768,772],{"type":38,"tag":78,"props":760,"children":761},{"style":645},[762],{"type":43,"value":648},{"type":38,"tag":78,"props":764,"children":765},{"style":279},[766],{"type":43,"value":767}," event",{"type":38,"tag":78,"props":769,"children":770},{"style":645},[771],{"type":43,"value":658},{"type":38,"tag":78,"props":773,"children":774},{"style":270},[775],{"type":43,"value":776}," {\n",{"type":38,"tag":78,"props":778,"children":779},{"class":80,"line":151},[780,785,789],{"type":38,"tag":78,"props":781,"children":782},{"style":270},[783],{"type":43,"value":784},"  event_name: ",{"type":38,"tag":78,"props":786,"children":787},{"style":290},[788],{"type":43,"value":293},{"type":38,"tag":78,"props":790,"children":791},{"style":270},[792],{"type":43,"value":298},{"type":38,"tag":78,"props":794,"children":795},{"class":80,"line":159},[796],{"type":38,"tag":78,"props":797,"children":798},{"style":270},[799],{"type":43,"value":800},"  event_id: source.id,\n",{"type":38,"tag":78,"props":802,"children":803},{"class":80,"line":167},[804],{"type":38,"tag":78,"props":805,"children":806},{"style":270},[807],{"type":43,"value":808},"  timestamp: source.created_at,\n",{"type":38,"tag":78,"props":810,"children":812},{"class":80,"line":811},12,[813,818,823],{"type":38,"tag":78,"props":814,"children":815},{"style":270},[816],{"type":43,"value":817},"  user_id: source.customer ",{"type":38,"tag":78,"props":819,"children":820},{"style":645},[821],{"type":43,"value":822},"&&",{"type":38,"tag":78,"props":824,"children":825},{"style":270},[826],{"type":43,"value":827}," source.customer.id,\n",{"type":38,"tag":78,"props":829,"children":831},{"class":80,"line":830},13,[832,837,841],{"type":38,"tag":78,"props":833,"children":834},{"style":270},[835],{"type":43,"value":836},"  value: source.total ",{"type":38,"tag":78,"props":838,"children":839},{"style":645},[840],{"type":43,"value":822},{"type":38,"tag":78,"props":842,"children":843},{"style":270},[844],{"type":43,"value":845}," source.total.amount,\n",{"type":38,"tag":78,"props":847,"children":849},{"class":80,"line":848},14,[850,855,859],{"type":38,"tag":78,"props":851,"children":852},{"style":270},[853],{"type":43,"value":854},"  currency: source.total ",{"type":38,"tag":78,"props":856,"children":857},{"style":645},[858],{"type":43,"value":822},{"type":38,"tag":78,"props":860,"children":861},{"style":270},[862],{"type":43,"value":863}," source.total.currency\n",{"type":38,"tag":78,"props":865,"children":867},{"class":80,"line":866},15,[868],{"type":38,"tag":78,"props":869,"children":870},{"style":270},[871],{"type":43,"value":407},{"type":38,"tag":78,"props":873,"children":875},{"class":80,"line":874},16,[876],{"type":38,"tag":78,"props":877,"children":878},{"emptyLinePlaceholder":684},[879],{"type":43,"value":687},{"type":38,"tag":78,"props":881,"children":883},{"class":80,"line":882},17,[884,888,893,898,903,908,913,918,922,926],{"type":38,"tag":78,"props":885,"children":886},{"style":645},[887],{"type":43,"value":695},{"type":38,"tag":78,"props":889,"children":890},{"style":270},[891],{"type":43,"value":892}," (",{"type":38,"tag":78,"props":894,"children":895},{"style":645},[896],{"type":43,"value":897},"!",{"type":38,"tag":78,"props":899,"children":900},{"style":270},[901],{"type":43,"value":902},"event.event_id ",{"type":38,"tag":78,"props":904,"children":905},{"style":645},[906],{"type":43,"value":907},"||",{"type":38,"tag":78,"props":909,"children":910},{"style":645},[911],{"type":43,"value":912}," !",{"type":38,"tag":78,"props":914,"children":915},{"style":270},[916],{"type":43,"value":917},"event.user_id ",{"type":38,"tag":78,"props":919,"children":920},{"style":645},[921],{"type":43,"value":907},{"type":38,"tag":78,"props":923,"children":924},{"style":645},[925],{"type":43,"value":912},{"type":38,"tag":78,"props":927,"children":928},{"style":270},[929],{"type":43,"value":930},"event.currency) {\n",{"type":38,"tag":78,"props":932,"children":934},{"class":80,"line":933},18,[935,939,943],{"type":38,"tag":78,"props":936,"children":937},{"style":270},[938],{"type":43,"value":723},{"type":38,"tag":78,"props":940,"children":941},{"style":670},[942],{"type":43,"value":728},{"type":38,"tag":78,"props":944,"children":945},{"style":270},[946],{"type":43,"value":733},{"type":38,"tag":78,"props":948,"children":950},{"class":80,"line":949},19,[951],{"type":38,"tag":78,"props":952,"children":953},{"style":645},[954],{"type":43,"value":741},{"type":38,"tag":78,"props":956,"children":958},{"class":80,"line":957},20,[959],{"type":38,"tag":78,"props":960,"children":961},{"style":270},[962],{"type":43,"value":407},{"type":38,"tag":78,"props":964,"children":966},{"class":80,"line":965},21,[967],{"type":38,"tag":78,"props":968,"children":969},{"emptyLinePlaceholder":684},[970],{"type":43,"value":687},{"type":38,"tag":78,"props":972,"children":974},{"class":80,"line":973},22,[975,980,985,990,995],{"type":38,"tag":78,"props":976,"children":977},{"style":270},[978],{"type":43,"value":979},"r.",{"type":38,"tag":78,"props":981,"children":982},{"style":670},[983],{"type":43,"value":984},"setMethod",{"type":38,"tag":78,"props":986,"children":987},{"style":270},[988],{"type":43,"value":989},"(",{"type":38,"tag":78,"props":991,"children":992},{"style":290},[993],{"type":43,"value":994},"\"POST\"",{"type":38,"tag":78,"props":996,"children":997},{"style":270},[998],{"type":43,"value":999},")\n",{"type":38,"tag":78,"props":1001,"children":1003},{"class":80,"line":1002},23,[1004,1008,1013,1017,1022],{"type":38,"tag":78,"props":1005,"children":1006},{"style":270},[1007],{"type":43,"value":979},{"type":38,"tag":78,"props":1009,"children":1010},{"style":670},[1011],{"type":43,"value":1012},"setPath",{"type":38,"tag":78,"props":1014,"children":1015},{"style":270},[1016],{"type":43,"value":989},{"type":38,"tag":78,"props":1018,"children":1019},{"style":290},[1020],{"type":43,"value":1021},"\"/events\"",{"type":38,"tag":78,"props":1023,"children":1024},{"style":270},[1025],{"type":43,"value":999},{"type":38,"tag":78,"props":1027,"children":1029},{"class":80,"line":1028},24,[1030,1034,1039,1043,1048],{"type":38,"tag":78,"props":1031,"children":1032},{"style":270},[1033],{"type":43,"value":979},{"type":38,"tag":78,"props":1035,"children":1036},{"style":670},[1037],{"type":43,"value":1038},"setRawQuery",{"type":38,"tag":78,"props":1040,"children":1041},{"style":270},[1042],{"type":43,"value":989},{"type":38,"tag":78,"props":1044,"children":1045},{"style":290},[1046],{"type":43,"value":1047},"\"\"",{"type":38,"tag":78,"props":1049,"children":1050},{"style":270},[1051],{"type":43,"value":999},{"type":38,"tag":78,"props":1053,"children":1055},{"class":80,"line":1054},25,[1056,1060,1065,1069,1074,1078,1083],{"type":38,"tag":78,"props":1057,"children":1058},{"style":270},[1059],{"type":43,"value":979},{"type":38,"tag":78,"props":1061,"children":1062},{"style":670},[1063],{"type":43,"value":1064},"setHeader",{"type":38,"tag":78,"props":1066,"children":1067},{"style":270},[1068],{"type":43,"value":989},{"type":38,"tag":78,"props":1070,"children":1071},{"style":290},[1072],{"type":43,"value":1073},"\"Content-Type\"",{"type":38,"tag":78,"props":1075,"children":1076},{"style":270},[1077],{"type":43,"value":599},{"type":38,"tag":78,"props":1079,"children":1080},{"style":290},[1081],{"type":43,"value":1082},"\"application/json\"",{"type":38,"tag":78,"props":1084,"children":1085},{"style":270},[1086],{"type":43,"value":999},{"type":38,"tag":78,"props":1088,"children":1090},{"class":80,"line":1089},26,[1091,1095,1100,1104,1109,1113,1118],{"type":38,"tag":78,"props":1092,"children":1093},{"style":270},[1094],{"type":43,"value":979},{"type":38,"tag":78,"props":1096,"children":1097},{"style":670},[1098],{"type":43,"value":1099},"setBody",{"type":38,"tag":78,"props":1101,"children":1102},{"style":270},[1103],{"type":43,"value":989},{"type":38,"tag":78,"props":1105,"children":1106},{"style":279},[1107],{"type":43,"value":1108},"JSON",{"type":38,"tag":78,"props":1110,"children":1111},{"style":270},[1112],{"type":43,"value":232},{"type":38,"tag":78,"props":1114,"children":1115},{"style":670},[1116],{"type":43,"value":1117},"stringify",{"type":38,"tag":78,"props":1119,"children":1120},{"style":270},[1121],{"type":43,"value":1122},"(event))\n",{"type":38,"tag":39,"props":1124,"children":1125},{},[1126],{"type":43,"value":1127},"This filters unrelated events, maps names explicitly, and rejects incomplete purchases before they reach the tagging container. The event ID gives downstream tags a stable value for deduplication.",{"type":38,"tag":61,"props":1129,"children":1131},{"id":1130},"_3-route-a-webhook-into-sgtm-preview-mode",[1132],{"type":43,"value":1133},"3. Route a webhook into sGTM Preview mode",{"type":38,"tag":39,"props":1135,"children":1136},{},[1137,1139,1144,1146,1153],{"type":43,"value":1138},"Open your server container and click ",{"type":38,"tag":191,"props":1140,"children":1141},{},[1142],{"type":43,"value":1143},"Preview",{"type":43,"value":1145},". Google's ",{"type":38,"tag":180,"props":1147,"children":1150},{"href":1148,"rel":1149},"https://developers.google.com/tag-platform/tag-manager/server-side/debug",[184],[1151],{"type":43,"value":1152},"server-side debugging guide",{"type":43,"value":1154}," shows how Tag Assistant displays incoming requests, the client that claimed them, event data and tag execution.",{"type":38,"tag":39,"props":1156,"children":1157},{},[1158],{"type":43,"value":1159},"For a non-browser request to join that preview session, attach the preview-session header value captured for the active Tag Assistant session. Keep it out of the function source:",{"type":38,"tag":68,"props":1161,"children":1163},{"className":633,"code":1162,"language":635,"meta":7,"style":7},"const previewHeader = cfg.get(\"GTM_PREVIEW_HEADER\")\n\nif (previewHeader) {\n  r.setHeader(\"X-Gtm-Server-Preview\", previewHeader)\n}\n",[1164],{"type":38,"tag":74,"props":1165,"children":1166},{"__ignoreMap":7},[1167,1206,1213,1225,1250],{"type":38,"tag":78,"props":1168,"children":1169},{"class":80,"line":81},[1170,1174,1179,1183,1188,1193,1197,1202],{"type":38,"tag":78,"props":1171,"children":1172},{"style":645},[1173],{"type":43,"value":648},{"type":38,"tag":78,"props":1175,"children":1176},{"style":279},[1177],{"type":43,"value":1178}," previewHeader",{"type":38,"tag":78,"props":1180,"children":1181},{"style":645},[1182],{"type":43,"value":658},{"type":38,"tag":78,"props":1184,"children":1185},{"style":270},[1186],{"type":43,"value":1187}," cfg.",{"type":38,"tag":78,"props":1189,"children":1190},{"style":670},[1191],{"type":43,"value":1192},"get",{"type":38,"tag":78,"props":1194,"children":1195},{"style":270},[1196],{"type":43,"value":989},{"type":38,"tag":78,"props":1198,"children":1199},{"style":290},[1200],{"type":43,"value":1201},"\"GTM_PREVIEW_HEADER\"",{"type":38,"tag":78,"props":1203,"children":1204},{"style":270},[1205],{"type":43,"value":999},{"type":38,"tag":78,"props":1207,"children":1208},{"class":80,"line":90},[1209],{"type":38,"tag":78,"props":1210,"children":1211},{"emptyLinePlaceholder":684},[1212],{"type":43,"value":687},{"type":38,"tag":78,"props":1214,"children":1215},{"class":80,"line":99},[1216,1220],{"type":38,"tag":78,"props":1217,"children":1218},{"style":645},[1219],{"type":43,"value":695},{"type":38,"tag":78,"props":1221,"children":1222},{"style":270},[1223],{"type":43,"value":1224}," (previewHeader) {\n",{"type":38,"tag":78,"props":1226,"children":1227},{"class":80,"line":108},[1228,1232,1236,1240,1245],{"type":38,"tag":78,"props":1229,"children":1230},{"style":270},[1231],{"type":43,"value":723},{"type":38,"tag":78,"props":1233,"children":1234},{"style":670},[1235],{"type":43,"value":1064},{"type":38,"tag":78,"props":1237,"children":1238},{"style":270},[1239],{"type":43,"value":989},{"type":38,"tag":78,"props":1241,"children":1242},{"style":290},[1243],{"type":43,"value":1244},"\"X-Gtm-Server-Preview\"",{"type":38,"tag":78,"props":1246,"children":1247},{"style":270},[1248],{"type":43,"value":1249},", previewHeader)\n",{"type":38,"tag":78,"props":1251,"children":1252},{"class":80,"line":117},[1253],{"type":38,"tag":78,"props":1254,"children":1255},{"style":270},[1256],{"type":43,"value":407},{"type":38,"tag":39,"props":1258,"children":1259},{},[1260,1262,1268],{"type":43,"value":1261},"Add ",{"type":38,"tag":74,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":43,"value":1267},"GTM_PREVIEW_HEADER",{"type":43,"value":1269}," under the function's configuration variables. Treat it as short-lived development configuration, remove it from the production output after testing, and never hard-code a captured session value in a shared function.",{"type":38,"tag":39,"props":1271,"children":1272},{},[1273,1279],{"type":38,"tag":74,"props":1274,"children":1276},{"className":1275},[],[1277],{"type":43,"value":1278},"X-Gtm-Server-Preview",{"type":43,"value":1280}," is preview-session transport data, not an authentication mechanism or a permanent container setting. Recapture it when the Tag Assistant session changes and keep the destination protected independently.",{"type":38,"tag":39,"props":1282,"children":1283},{},[1284,1286,1293],{"type":43,"value":1285},"If you operate your own tagging infrastructure, Google separates the tagging server from a preview server and documents the required environment variables in its ",{"type":38,"tag":180,"props":1287,"children":1290},{"href":1288,"rel":1289},"https://developers.google.com/tag-platform/tag-manager/server-side/manual-setup-guide",[184],[1291],{"type":43,"value":1292},"manual setup guide",{"type":43,"value":1294},". Keep the preview service private where possible and expose the public tagging endpoint through your normal load balancer.",{"type":38,"tag":61,"props":1296,"children":1298},{"id":1297},"_4-debug-the-event-in-tag-assistant",[1299],{"type":43,"value":1300},"4. Debug the event in Tag Assistant",{"type":38,"tag":39,"props":1302,"children":1303},{},[1304],{"type":43,"value":1305},"Send one test event, then inspect:",{"type":38,"tag":1307,"props":1308,"children":1309},"ol",{},[1310,1328,1338,1348,1358],{"type":38,"tag":214,"props":1311,"children":1312},{},[1313,1318,1320,1326],{"type":38,"tag":191,"props":1314,"children":1315},{},[1316],{"type":43,"value":1317},"Requests:",{"type":43,"value":1319}," confirm the ",{"type":38,"tag":74,"props":1321,"children":1323},{"className":1322},[],[1324],{"type":43,"value":1325},"/events",{"type":43,"value":1327}," request appeared.",{"type":38,"tag":214,"props":1329,"children":1330},{},[1331,1336],{"type":38,"tag":191,"props":1332,"children":1333},{},[1334],{"type":43,"value":1335},"Client:",{"type":43,"value":1337}," confirm the intended client claimed it.",{"type":38,"tag":214,"props":1339,"children":1340},{},[1341,1346],{"type":38,"tag":191,"props":1342,"children":1343},{},[1344],{"type":43,"value":1345},"Event data:",{"type":43,"value":1347}," compare names, types and required identifiers.",{"type":38,"tag":214,"props":1349,"children":1350},{},[1351,1356],{"type":38,"tag":191,"props":1352,"children":1353},{},[1354],{"type":43,"value":1355},"Tags:",{"type":43,"value":1357}," verify which tags fired and why others did not.",{"type":38,"tag":214,"props":1359,"children":1360},{},[1361,1366],{"type":38,"tag":191,"props":1362,"children":1363},{},[1364],{"type":43,"value":1365},"Webhook Relay delivery:",{"type":43,"value":1367}," compare the transformed request with the sGTM response.",{"type":38,"tag":39,"props":1369,"children":1370},{},[1371],{"type":43,"value":1372},"If the request reaches sGTM but no client claims it, fix the path, content type or custom-client logic. If it never appears in Tag Assistant but the production server responds, refresh the Preview session and its header value.",{"type":38,"tag":61,"props":1374,"children":1376},{"id":1375},"privacy-and-reliability-checklist",[1377],{"type":43,"value":1378},"Privacy and reliability checklist",{"type":38,"tag":210,"props":1380,"children":1381},{},[1382,1387,1392,1404,1409,1414],{"type":38,"tag":214,"props":1383,"children":1384},{},[1385],{"type":43,"value":1386},"Send only fields required by the tags. Avoid copying the entire source webhook.",{"type":38,"tag":214,"props":1388,"children":1389},{},[1390],{"type":43,"value":1391},"Remove email addresses, names and other direct identifiers unless your consent and vendor configuration permit them.",{"type":38,"tag":214,"props":1393,"children":1394},{},[1395,1397,1403],{"type":43,"value":1396},"Verify the source webhook before transforming it. See ",{"type":38,"tag":180,"props":1398,"children":1400},{"href":1399},"/blog/verify-webhook-signature",[1401],{"type":43,"value":1402},"webhook signature verification",{"type":43,"value":232},{"type":38,"tag":214,"props":1405,"children":1406},{},[1407],{"type":43,"value":1408},"Preserve a stable event ID so retries do not become duplicate conversions.",{"type":38,"tag":214,"props":1410,"children":1411},{},[1412],{"type":43,"value":1413},"Filter non-production events or route them to a separate sGTM container.",{"type":38,"tag":214,"props":1415,"children":1416},{},[1417,1419,1425],{"type":43,"value":1418},"Inspect failures in the ",{"type":38,"tag":180,"props":1420,"children":1422},{"href":1421},"/features/webhook-logs",[1423],{"type":43,"value":1424},"webhook logs view",{"type":43,"value":1426}," before changing tags.",{"type":38,"tag":61,"props":1428,"children":1430},{"id":1429},"common-problems",[1431],{"type":43,"value":1432},"Common problems",{"type":38,"tag":1434,"props":1435,"children":1437},"h3",{"id":1436},"the-tagging-server-returns-2xx-but-no-tag-fires",[1438],{"type":43,"value":1439},"The tagging server returns 2xx, but no tag fires",{"type":38,"tag":39,"props":1441,"children":1442},{},[1443],{"type":43,"value":1444},"A load balancer can accept a request even when no sGTM client claims it. Use Preview mode to inspect client selection and verify the request path and format.",{"type":38,"tag":1434,"props":1446,"children":1448},{"id":1447},"preview-works-but-production-does-not",[1449],{"type":43,"value":1450},"Preview works, but production does not",{"type":38,"tag":39,"props":1452,"children":1453},{},[1454],{"type":43,"value":1455},"Preview can hide missing published changes. Publish the latest container version and test the normal output without the preview header.",{"type":38,"tag":1434,"props":1457,"children":1459},{"id":1458},"one-source-event-creates-duplicate-conversions",[1460],{"type":43,"value":1461},"One source event creates duplicate conversions",{"type":38,"tag":39,"props":1463,"children":1464},{},[1465],{"type":43,"value":1466},"Webhook delivery is retryable. Pass the source event ID through the transform and configure downstream tags or APIs to deduplicate it.",{"type":38,"tag":1434,"props":1468,"children":1470},{"id":1469},"the-function-contains-an-analytics-secret",[1471],{"type":43,"value":1472},"The function contains an analytics secret",{"type":38,"tag":39,"props":1474,"children":1475},{},[1476,1478,1484],{"type":43,"value":1477},"Move it into a configuration variable and read it with ",{"type":38,"tag":74,"props":1479,"children":1481},{"className":1480},[],[1482],{"type":43,"value":1483},"cfg.get(...)",{"type":43,"value":1485},". This keeps reusable source code separate from account-specific credentials.",{"type":38,"tag":39,"props":1487,"children":1488},{},[1489,1491,1497,1499,1505],{"type":43,"value":1490},"For more mapping and validation patterns, continue with the ",{"type":38,"tag":180,"props":1492,"children":1494},{"href":1493},"/blog/auto-transform-webhook",[1495],{"type":43,"value":1496},"webhook transformation cookbook",{"type":43,"value":1498}," or inspect a raw sample first with ",{"type":38,"tag":180,"props":1500,"children":1502},{"href":1501},"/webhook-bin",[1503],{"type":43,"value":1504},"Webhook Bin",{"type":43,"value":232},{"type":38,"tag":1507,"props":1508,"children":1509},"style",{},[1510],{"type":43,"value":1511},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":99,"depth":99,"links":1513},[1514,1515,1516,1517,1518,1519,1520,1521],{"id":63,"depth":90,"text":66},{"id":200,"depth":90,"text":203},{"id":415,"depth":90,"text":418},{"id":454,"depth":90,"text":457},{"id":1130,"depth":90,"text":1133},{"id":1297,"depth":90,"text":1300},{"id":1375,"depth":90,"text":1378},{"id":1429,"depth":90,"text":1432,"children":1522},[1523,1524,1525,1526],{"id":1436,"depth":99,"text":1439},{"id":1447,"depth":99,"text":1450},{"id":1458,"depth":99,"text":1461},{"id":1469,"depth":99,"text":1472},"markdown","content:blog:server-side-google-tag-manager-webhooks.md","content","blog/server-side-google-tag-manager-webhooks.md","blog/server-side-google-tag-manager-webhooks","md",{"loc":4},1788727851283]