{"id":68781,"date":"2025-02-05T01:34:48","date_gmt":"2025-02-05T01:34:48","guid":{"rendered":"https:\/\/peraltafinancing.com\/analytics\/custom-gtm-loader-for-server-side-tagging\/"},"modified":"2025-02-05T01:34:48","modified_gmt":"2025-02-05T01:34:48","slug":"custom-gtm-loader-for-server-side-tagging","status":"publish","type":"post","link":"https:\/\/fivemor.com\/?p=68781","title":{"rendered":"Custom GTM Loader For Server-side Tagging"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<blockquote>\n<p><strong>Last updated: 18 October 2021<\/strong>. Peview works now with the proxied container even if the container ID is overridden..<\/p>\n<\/blockquote>\n<p>While <a href=\"https:\/\/www.simoahava.com\/analytics\/server-side-tagging-google-tag-manager\/\">server-side tagging<\/a> already has a wonderful built-in Client for <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-web-container-client-server-side-tagging\/\">proxying the Google Tag Manager container<\/a> via your own first-party domain, it\u2019s not perfect.<\/p>\n<p>The main issues are that it doesn\u2019t let you delimit access on a per-origin basis, so requests for the allowlisted container IDs can be sent from anywhere, and that it doesn\u2019t let you freely choose the path via which the container ID is loaded.<\/p>\n<p>To address these issues, I\u2019m happy to reveal that I\u2019ve written a <strong>new Client template<\/strong> for Server containers, named <strong>GTM Loader<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1804 \/ 1148;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/gtm-loader.jpg\" title=\"GTM Loader\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1148\" width=\"1804\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/gtm-loader.jpg#ZgotmplZ\" alt=\"GTM Loader\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The main features of this template are:<\/p>\n<ul>\n<li>Freely choose which request path the Client responds to. You can keep the default <code>\/gtm.js<\/code>, or you can go for something more imaginative, such as <code>\/green-dragons<\/code>.<\/li>\n<li>Always load a container of a specific ID, regardless of what (if anything) is in the <code>?id=<\/code> parameter of the request.<\/li>\n<li>Only allow requests from specific origins.<\/li>\n<\/ul>\n<p>Read on for more information!<\/p>\n<p>                <span class=\"simmer\"><br \/>\n  <span class=\"close\">X<\/span><\/p>\n<p>\n    <span class=\"fa fa-md fa-bell\"\/><br \/>\n    <strong>The Simmer Newsletter<\/strong>\n  <\/p>\n<p>\n    Subscribe to the <a href=\"https:\/\/www.simoahava.com\/newsletter\/\">Simmer newsletter<\/a> to get the latest news and content from Simo Ahava into your email inbox!\n  <\/p>\n<p>  <\/span><\/p>\n<h2 id=\"get-the-template\">Get the template<\/h2>\n<p>As the <a href=\"https:\/\/tagmanager.google.com\/gallery\/\">Community Template Gallery<\/a> doesn\u2019t distribute Client templates yet, you\u2019ll need to manually import the template file.<\/p>\n<p>First, fetch the raw <code>template.tpl<\/code> file from the GitHub repo by following <a href=\"https:\/\/raw.githubusercontent.com\/gtm-templates-simo-ahava\/gtm-loader\/main\/template.tpl\">this link<\/a> and saving the page as <code>template.tpl<\/code> in your computer.<\/p>\n<p>Then, in your <strong>Server<\/strong> container, go to <strong>Templates<\/strong> and click <strong>New<\/strong> in the box for Client templates.<\/p>\n<div style=\"aspect-ratio: 2470 \/ 916;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/new-client-template.jpg\" title=\"New Client Template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"916\" width=\"2470\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/new-client-template.jpg#ZgotmplZ\" alt=\"New Client Template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In the <strong>overflow menu<\/strong> in the top-right corner of the screen, choose <strong>Import<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1036 \/ 708;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/import-template.jpg\" title=\"Import template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"708\" width=\"1036\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/import-template.jpg#ZgotmplZ\" alt=\"Import template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Locate the <code>template.tpl<\/code> file from your container, wait for the editor to refresh with the GTM Loader template, and then click <strong>Save<\/strong> to save the template.<\/p>\n<div style=\"aspect-ratio: 1944 \/ 940;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/save-template.jpg\" title=\"Save template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"940\" width=\"1944\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/save-template.jpg#ZgotmplZ\" alt=\"Save template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h2 id=\"create-a-new-client\">Create a new Client<\/h2>\n<p>Head on over to <strong>Clients<\/strong> in your container, and click <strong>New<\/strong> to create a new Client.<\/p>\n<div style=\"aspect-ratio: 2524 \/ 568;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/new-client.jpg\" title=\"New client\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"568\" width=\"2524\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/new-client.jpg#ZgotmplZ\" alt=\"New client\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>From the list of available Clients, choose the <strong>GTM Loader<\/strong> Client.<\/p>\n<p>You should be ready now to customize the new Client!<\/p>\n<h2 id=\"configure-the-client\">Configure the Client<\/h2>\n<p>Here\u2019s what the Client looks like with all the available fields in display:<\/p>\n<div style=\"aspect-ratio: 1802 \/ 1138;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2021\/05\/template-ready-for-editing.jpg\" title=\"Client ready for editing\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1138\" width=\"1802\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2021\/05\/template-ready-for-editing.jpg#ZgotmplZ\" alt=\"Client ready for editing\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h3 id=\"request-path\">Request Path<\/h3>\n<p>Set this to a path (include the leading slash). You can also just keep the default <code>\/gtm.js<\/code> if you wish.<\/p>\n<p>The Client will be listening for requests to this path, and if an <strong>exact match<\/strong> is made, the Client will claim the request and work its wonders.<\/p>\n<p>For example, if you set the path to <code>\/google_tag_manager.js<\/code> as in the screenshot above, then a request to <strong>https:\/\/<your server-side=\"\" domain=\"\">\/google_tag_manager.js?id=GTM-ABCDEFG<\/your><\/strong> will load the Google Tag Manager container with ID <strong>GTM-ABCDEFG<\/strong> unless you also have the <strong>Override Container ID<\/strong> setting checked (more on this below).<\/p>\n<p>Remember that it\u2019s <strong>exact match<\/strong>! The request must be with a path that exactly matches the setting you configure in this Client.<\/p>\n<h3 id=\"override-container-id\">Override Container ID<\/h3>\n<blockquote>\n<p><strong>Important!<\/strong> If you override the Container ID, <strong>Preview<\/strong> containers will be loaded, but the browser has to make an additional request to <code>www.googletagmanager.com<\/code>. So if your site has a Content Security Policy, <code>https:\/\/www.googletagmanager.com<\/code> mus still be added to it for Preview mode to work properly.<\/p>\n<\/blockquote>\n<p>If you check this setting, you can then add a valid Google Tag Manager container ID to the respective field.<\/p>\n<p>This setting means that <em>regardless of what is in the <code>?id=<\/code> parameter<\/em>, a container with the configured ID will be returned.<\/p>\n<p>When you have this setting checked, you can actually drop the <code>?id=<\/code> parameter from the request altogether, as the container with the configured ID will be loaded in all cases.<\/p>\n<h3 id=\"allowed-origins\">Allowed Origins<\/h3>\n<p>In this field, you can add a comma-separated list of <strong>origins<\/strong> from which requests will only be respected.<\/p>\n<p>For example, if you add <code>https:\/\/www.teamsimmer.com,https:\/\/www.simoahava.com<\/code> to the field, then only requests from those two origins will be able to fetch the container.<\/p>\n<p>Remember that the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Origin#syntax\">origin<\/a> is the scheme (<code>http<\/code> or <code>https<\/code>) plus <code>:\/\/<\/code> plus hostname plus port. So basically everything up to the request path.<\/p>\n<p>You can also add <code>*<\/code> to this field, in which case the Client will claim the request regardless of where it originated from.<\/p>\n<p>If you need to manually provide the origin (e.g. when working with an embedded resource or when testing), you can add <code>&amp;origin=<origin\/><\/code> to the request URL. For example, to load the container even when I\u2019m not on <code>https:\/\/www.simoahava.com<\/code> and I\u2019ve set that into the Allowed Origins field, I can browse to this:<\/p>\n<p><strong>https:\/\/<your server-side=\"\" domain=\"\">\/google_tag_manager.js?id=GTM-ABCDEFG&amp;origin=https:\/\/www.simoahava.com<\/your><\/strong><\/p>\n<h2 id=\"how-it-works\">How it works<\/h2>\n<p>A Client created with the template listens for requests that are dispatched to the request path defined in the Client settings.<\/p>\n<h3 id=\"validate-the-request\">Validate the request<\/h3>\n<p>When a request like that is received, the Client does two checks:<\/p>\n<ol>\n<li>Is the <strong>Override Container ID<\/strong> setting checked and a valid GTM container ID has been configured, OR is there a valid GTM container ID as the value of the <code>id<\/code> query parameter in the request?<\/li>\n<li>Is the value of <strong>Allowed Origins<\/strong> the wildcard (<code>*<\/code>) OR does the request come from an allowed origin OR does it have an allowed origin as the value of the <code>origin<\/code> query parameter in the request?<\/li>\n<\/ol>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#aaa;font-style:italic\">\/\/ If the incoming request matches the request configured in the Client\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">if<\/span> (requestPath === data.requestPath) {\n  \n  <span style=\"color:#aaa;font-style:italic\">\/\/ If the request is for a valid GTM container ID\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (!containerId.match(<span style=\"color:#a50\">'^GTM-.+$'<\/span>)) <span style=\"color:#00a\">return<\/span>;\n  \n  <span style=\"color:#aaa;font-style:italic\">\/\/ If the request comes from a valid origin\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (!validateOrigin()) <span style=\"color:#00a\">return<\/span>;\n  \n  ...\n}\n<\/code><\/pre>\n<\/div>\n<p>If both resolve to <code>true<\/code>, the request is claimed.<\/p>\n<h3 id=\"fetch-the-preview-container\">Fetch the preview container<\/h3>\n<p>If the request is for a <strong>preview<\/strong> container, meaning it has the <code>gtm_debug<\/code>, <code>gtm_auth<\/code>, and <code>gtm_preview<\/code> query parameters, the Client acts as a transparent proxy.<\/p>\n<p>It simply forwards the request to GTM servers with all the headers and parameters intact, and returns the result back to the request source.<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#00a\">const<\/span> fetchPreviewContainer = () =&gt; {\n  sendHttpGet(\n    httpEndpoint  + \n              <span style=\"color:#a50\">'&amp;id='<\/span> + containerId + \n              <span style=\"color:#a50\">'&amp;gtm_auth='<\/span> + gtm_auth + \n              <span style=\"color:#a50\">'&amp;gtm_debug='<\/span> + gtm_debug + \n              <span style=\"color:#a50\">'&amp;gtm_preview='<\/span> + gtm_preview, \n    (statusCode, headers, body) =&gt; {\n      sendResponse(body, headers, statusCode);\n    }, {timeout: <span style=\"color:#099\">1500<\/span>}\n  );\n};\n<\/code><\/pre>\n<\/div>\n<p>Importantly, when a preview container is fetched, the result <strong>is not cached<\/strong>. This is vital to make preview useful, as otherwise the user would need to wait for the cache to expire before the refreshed preview container becomes available.<\/p>\n<h3 id=\"fetch-the-live-container\">Fetch the live container<\/h3>\n<p>When a <strong>live<\/strong> container is fetched, on the other hand, the process changes quite a bit.<\/p>\n<p>The template uses <code>templateDataStorage<\/code>, which is <a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/api#templatedatastorage\">an API<\/a> designed to persist information across requests in the Server container.<\/p>\n<p>When a request for the live container comes in, the Client checks if there already is a cached version of the library <strong>and<\/strong> if the resource was cached less than <strong>7.5 minutes ago<\/strong>. In this case, the cached library (and any cached headers) are returned to the request source.<\/p>\n<blockquote>\n<p>This way the Client saves resources by <strong>not having to fetch the resource from Google servers anymore<\/strong>.<\/p>\n<\/blockquote>\n<p>Why 7.5 minutes cache duration? Well, that\u2019s <strong>half<\/strong> of the <strong>browser cache time<\/strong> for the GTM library itself (15 minutes). This way the browser cache still has the final say on how long to cache the resource, but unlike a browser cache, <strong>all users<\/strong> benefit from the server-side cache even if the user has never downloaded the resource before.<\/p>\n<p>If the resource is not cached or if the cache has expired, then the container is fetched from Google servers.<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#00a\">const<\/span> fetchLiveContainer = () =&gt; {\n  <span style=\"color:#00a\">const<\/span> now = getTimestampMillis();\n  \n  <span style=\"color:#aaa;font-style:italic\">\/\/ Set timeout to 7.5 minutes\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">const<\/span> storageTimeout = now - cacheMaxTimeInMs;\n  \n  <span style=\"color:#aaa;font-style:italic\">\/\/ If the cache has expired fetch library from Google servers and write response to cache\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (!templateDataStorage.getItemCopy(storedJs) || \n      templateDataStorage.getItemCopy(storedTimeout) '&amp;id=' + containerId, \n      (statusCode, headers, body) =&gt; {\n        <span style=\"color:#00a\">if<\/span> (statusCode === <span style=\"color:#099\">200<\/span>) {\n          templateDataStorage.setItemCopy(storedJs, body);\n          templateDataStorage.setItemCopy(storedHeaders, headers);\n          templateDataStorage.setItemCopy(storedTimeout, now);\n        }\n        sendResponse(body, headers, statusCode);\n      }, {timeout: <span style=\"color:#099\">1500<\/span>}\n    );\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Otherwise, pull the item from cache and do not make a request to Google servers\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  } <span style=\"color:#00a\">else<\/span> {\n    sendResponse(\n      templateDataStorage.getItemCopy(storedJs),\n      templateDataStorage.getItemCopy(storedHeaders),\n      <span style=\"color:#099\">200<\/span>\n    );\n  }\n};\n<\/code><\/pre>\n<\/div>\n<p>So <code>templateDataStorage<\/code> functions as an additional layer of caching here, reducing server response latency and network egress costs.<\/p>\n<h2 id=\"summary\">Summary<\/h2>\n<p>Why create a template like this when the <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-web-container-client-server-side-tagging\/\">built-in web container client<\/a> works just fine?<\/p>\n<p>Cynics could say that this is an improved way to circumvent ad blockers. And they\u2019d be right! This <strong>does<\/strong> make it easier to circumvent ad blockers, as their heuristics target not just the <code>googletagmanager.com<\/code> domain but also the <code>gtm.js<\/code> file and the <code>GTM-...<\/code> container ID.<\/p>\n<p>However, I designed the template to introduce additional flexibility to moving Google Tag Manager to a first-party context. Being able to optimize for request paths and query parameters seems like an obvious enhancement. The <code>templateDataStorage<\/code> setup adds an additional layer of cost optimization.<\/p>\n<p>But there\u2019s also the twist that maybe ad blockers targeting Google Tag Manager are throwing the baby out with the bathwater. GTM itself is not a tracking tool, and many use it for purposes completely unrelated to tracking or data collection.<\/p>\n<p>Having said that, if I were to design an ad blocker today, I would probably block GTM as well, as it\u2019s more than likely that the bathwater is so dirty it must be chucked regardless of the collateral damage it causes.<\/p>\n<p>So it\u2019s a tough balance to make. The only things I can recommend are these:<\/p>\n<ul>\n<li>You should approach server-side tagging with <strong>best intentions at heart<\/strong>.<\/li>\n<li>Do your best to <strong>improve<\/strong> rather than erode <strong>transparency<\/strong>.<\/li>\n<li>Be <strong>honest and respectful<\/strong> to your site visitors.<\/li>\n<li>Make sure these mechanisms are <strong>documented<\/strong> somewhere so that if someone were to audit the data flows on the site and the server, your tags would not obstruct this important work.<\/li>\n<\/ul>\n<p>This way we\u2019ll all have a good time with server-side tagging.<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Last updated: 18 October 2021. Peview works now with the proxied container even if the container ID is overridden.. While server-side tagging already has a wonderful built-in Client for proxying the Google Tag Manager container via your own first-party domain, it\u2019s not perfect. The main issues are that it doesn\u2019t let you delimit access on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":68782,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[834,32680,36475,18475,29117],"dealstore":[],"offerexpiration":[],"class_list":["post-68781","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-custom","tag-gtm","tag-loader","tag-serverside","tag-tagging"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Custom GTM Loader For Server-side Tagging - Som2ny Network<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fivemor.com\/?p=68781\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom GTM Loader For Server-side Tagging - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"Last updated: 18 October 2021. Peview works now with the proxied container even if the container ID is overridden.. While server-side tagging already has a wonderful built-in Client for proxying the Google Tag Manager container via your own first-party domain, it\u2019s not perfect. The main issues are that it doesn\u2019t let you delimit access on [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fivemor.com\/?p=68781\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-02-05T01:34:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1441\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fivemor.com\/?p=68781#article\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\"},\"headline\":\"Custom GTM Loader For Server-side Tagging\",\"datePublished\":\"2025-02-05T01:34:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781\"},\"wordCount\":1418,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg\",\"keywords\":[\"Custom\",\"GTM\",\"Loader\",\"Serverside\",\"Tagging\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fivemor.com\/?p=68781#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fivemor.com\/?p=68781\",\"url\":\"https:\/\/fivemor.com\/?p=68781\",\"name\":\"Custom GTM Loader For Server-side Tagging - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781#primaryimage\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg\",\"datePublished\":\"2025-02-05T01:34:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fivemor.com\/?p=68781#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fivemor.com\/?p=68781\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/?p=68781#primaryimage\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg\",\"width\":2560,\"height\":1441},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fivemor.com\/?p=68781#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/fivemor.com\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Custom GTM Loader For Server-side Tagging\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fivemor.com\/#website\",\"url\":\"https:\/\/fivemor.com\/\",\"name\":\"Som2ny Network\",\"description\":\"Daily Deals\",\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fivemor.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/fivemor.com\/#organization\",\"name\":\"Som2ny Network\",\"url\":\"https:\/\/fivemor.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"width\":300,\"height\":86,\"caption\":\"Som2ny Network\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png\",\"caption\":\"admin\"},\"sameAs\":[\"https:\/\/fivemor.com\"],\"url\":\"https:\/\/fivemor.com\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Custom GTM Loader For Server-side Tagging - Som2ny Network","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fivemor.com\/?p=68781","og_locale":"en_US","og_type":"article","og_title":"Custom GTM Loader For Server-side Tagging - Som2ny Network","og_description":"Last updated: 18 October 2021. Peview works now with the proxied container even if the container ID is overridden.. While server-side tagging already has a wonderful built-in Client for proxying the Google Tag Manager container via your own first-party domain, it\u2019s not perfect. The main issues are that it doesn\u2019t let you delimit access on [&hellip;]","og_url":"https:\/\/fivemor.com\/?p=68781","og_site_name":"Som2ny Network","article_published_time":"2025-02-05T01:34:48+00:00","og_image":[{"width":2560,"height":1441,"url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg","type":"image\/jpeg"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fivemor.com\/?p=68781#article","isPartOf":{"@id":"https:\/\/fivemor.com\/?p=68781"},"author":{"name":"admin","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371"},"headline":"Custom GTM Loader For Server-side Tagging","datePublished":"2025-02-05T01:34:48+00:00","mainEntityOfPage":{"@id":"https:\/\/fivemor.com\/?p=68781"},"wordCount":1418,"commentCount":0,"publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"image":{"@id":"https:\/\/fivemor.com\/?p=68781#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg","keywords":["Custom","GTM","Loader","Serverside","Tagging"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fivemor.com\/?p=68781#respond"]}]},{"@type":"WebPage","@id":"https:\/\/fivemor.com\/?p=68781","url":"https:\/\/fivemor.com\/?p=68781","name":"Custom GTM Loader For Server-side Tagging - Som2ny Network","isPartOf":{"@id":"https:\/\/fivemor.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/fivemor.com\/?p=68781#primaryimage"},"image":{"@id":"https:\/\/fivemor.com\/?p=68781#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg","datePublished":"2025-02-05T01:34:48+00:00","breadcrumb":{"@id":"https:\/\/fivemor.com\/?p=68781#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fivemor.com\/?p=68781"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/?p=68781#primaryimage","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/02\/custom-gtm-loader-server-side-tagging-scaled.jpg","width":2560,"height":1441},{"@type":"BreadcrumbList","@id":"https:\/\/fivemor.com\/?p=68781#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fivemor.com\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Custom GTM Loader For Server-side Tagging"}]},{"@type":"WebSite","@id":"https:\/\/fivemor.com\/#website","url":"https:\/\/fivemor.com\/","name":"Som2ny Network","description":"Daily Deals","publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fivemor.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/fivemor.com\/#organization","name":"Som2ny Network","url":"https:\/\/fivemor.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/#\/schema\/logo\/image\/","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","width":300,"height":86,"caption":"Som2ny Network"},"image":{"@id":"https:\/\/fivemor.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png","caption":"admin"},"sameAs":["https:\/\/fivemor.com"],"url":"https:\/\/fivemor.com\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/68781","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=68781"}],"version-history":[{"count":0,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/68781\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/media\/68782"}],"wp:attachment":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=68781"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=68781"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=68781"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=68781"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=68781"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}