{"id":99258,"date":"2025-02-20T10:43:35","date_gmt":"2025-02-20T10:43:35","guid":{"rendered":"https:\/\/accountants4yourbusiness.co.uk\/analytics\/custom-templates-guide-for-google-tag-manager\/"},"modified":"2025-02-20T10:43:35","modified_gmt":"2025-02-20T10:43:35","slug":"custom-templates-guide-for-google-tag-manager","status":"publish","type":"post","link":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258","title":{"rendered":"Custom Templates Guide For Google Tag Manager"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<blockquote>\n<p><strong>Last updated 12 August 2020<\/strong>: Added details about <a href=\"https:\/\/www.simoahava.com\/analytics\/server-side-tagging-google-tag-manager\/\">server-side tagging<\/a>.<\/p>\n<\/blockquote>\n<p>As I have finally managed to pick up my jaw from the floor, it\u2019s now time to tell you what\u2019s got me so excited. <a href=\"https:\/\/tagmanager.google.com\/\">Google Tag Manager<\/a> recently released a new feature called <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/\"><strong>Custom Templates<\/strong><\/a>. Actually, it\u2019s not fair to call it a <em>feature<\/em>. It\u2019s a full-blown paradigm shift in how we use Google Tag Manager. It\u2019s a <em>suite<\/em> of features designed to help brands, companies, and users create and share their own custom JavaScript and HTML setups with ease, while taking care that the code is optimized for delivery in the web browser.<\/p>\n<div style=\"aspect-ratio: 2626 \/ 942;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/custom-templates-google-tag-manager.jpg\" title=\"custom templates in google tag manager\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"942\" width=\"2626\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/custom-templates-google-tag-manager.jpg#ZgotmplZ\" alt=\"custom templates in google tag manager\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Custom Templates<\/strong>, in short, are tag, variable, and Client templates that <strong>you<\/strong> can create and configure. In other words, if you have a cool idea for a tag (e.g. an analytics tracking tag for a vendor not natively supported by GTM), a variable (e.g. a Custom JavaScript variable that does something with a string), or a Client (e.g. a server-side endpoint for some new analytics tool), you can now turn them into reusable templates which can, in turn, be shared with other users and containers via template export and import. You can also use the <a href=\"https:\/\/tagmanager.google.com\/gallery\/\">Community gallery<\/a> to distribute your templates.<\/p>\n<div style=\"aspect-ratio: 1574 \/ 382;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/template-in-the-list.jpg\" title=\"Example template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"382\" width=\"1574\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/template-in-the-list.jpg#ZgotmplZ\" alt=\"Example template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Templates use a customized, sandboxed version of JavaScript, which has its own idiosyncratic vernacular that you must learn (with the help of this guide, of course). The reason for this added complexity is that with templates you can ensure that the code being executed is safe, unintrusive, and optimized.<\/p>\n<p>Furthermore, templates you create will define certain <strong>permissions<\/strong> that are required for the template code to be able to run. An additional level of governance is provided by way of <strong>policies<\/strong> defined on the web page itself where the template code might be run. The interplay between these permissions and policies is a core feature of template security.<\/p>\n<p>There are lots and lots of things to cover in this guide, so let\u2019s just get started.<\/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=\"how-to-read-this-guide\">How to read this guide<\/h2>\n<p>This is a long guide. It has to be &#8211; there\u2019s so much about custom templates that needs to be addressed in any document whose purpose is to provide a comprehensive treatment of the subject matter.<\/p>\n<p>However, <strong>don\u2019t interpret my inability to write concise prose as indicative of how complex custom templates are<\/strong>. I can assure you &#8211; they\u2019re absolutely manageable by anyone who\u2019s been using Google Tag Manager for a while.<\/p>\n<p>This guide is a <strong>reference<\/strong>. Its purpose is to offer you documentation to support your work with custom templates.<\/p>\n<p>Because of this, I want to suggest some different ways to approach this guide.<\/p>\n<p>Be sure to check out my other guide on how to <a href=\"https:\/\/www.simoahava.com\/analytics\/create-facebook-pixel-custom-tag-template\/\">create a Facebook pixel template<\/a> &#8211; it should shed more light on how templates work. You can also check the corresponding <a href=\"https:\/\/youtu.be\/5ESEtwq7fxc\">video<\/a> if you prefer watching rather than reading.<\/p>\n<p>You can also view all the custom templates I have created and\/or collected in <a href=\"https:\/\/github.com\/sahava\/GoogleTagManagerTemplates\">this GitHub repository<\/a> and in the <a href=\"https:\/\/www.simoahava.com\/custom-templates\/\">Templates<\/a> section of this site.<\/p>\n<h2 id=\"custom-templates-in-a-nutshell\">Custom Templates in a nutshell<\/h2>\n<p>Google Tag Manager\u2019s Custom Templates offer a way to build a user interface around the custom code you might want to run on the site using Google Tag Manager. The user interface is what you\u2019ve come accustomed to when using GTM\u2019s tags and variables. It comprises <strong>text input fields<\/strong>, <strong>settings<\/strong>, <strong>tables<\/strong>, <strong>labels<\/strong>, <strong>drop-down menus<\/strong>, and so forth.<\/p>\n<div style=\"aspect-ratio: 2972 \/ 1078;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-template-before-after.jpg\" title=\"Tag template before and after\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1078\" width=\"2972\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-template-before-after.jpg#ZgotmplZ\" alt=\"Tag template before and after\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Obviously, the UI itself is already a huge asset. Being able to offer a user interface in lieu of a complicated code block will minimize problems arising from input errors, and will help keep the code stable.<\/p>\n<p>However, the templates have another, less apparent (but no less impactful) function. They add layers of <strong>protection<\/strong> and <strong>security<\/strong> to the code they abstract. Templates use a <a href=\"#sandboxed-javascript\">custom <strong>JavaScript framework<\/strong><\/a> which introduces a handful of <a href=\"#template-apis\">APIs<\/a> (application programming interfaces) that you must use if you want the code to actually do anything.<\/p>\n<p>This introduces a steep learning curve, because you can\u2019t just copy-paste code from <a href=\"https:\/\/www.stackoverflow.com\/\">Stack Overflow<\/a> any more. If you want to set a global <code>window<\/code> property, you need to use <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#setinwindow\">an API for that<\/a>. If you want to log to console, you need to use <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#logtoconsole\">an API for that<\/a>. If you want to check the value of a cookie, guess what, you need to use <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#getcookievalues\">an API for that<\/a>.<\/p>\n<div style=\"aspect-ratio: 1872 \/ 410;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/api-in-use.jpg\" title=\"API in use\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"410\" width=\"1872\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/api-in-use.jpg#ZgotmplZ\" alt=\"API in use\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Basically any code that tries to access the global state of the page or run any native JavaScript functions defined on the global level requires an API call.<\/p>\n<p>So why this added complexity? Well, for one, these APIs make sure that potentially dangerous and\/or intrusive modifications to the global state are done in a controlled manner.<\/p>\n<p>Whenever you want to use an API, you must <code>require()<\/code> it in the template code. And when you introduce an API like that, the template automatically generates a set of configurable <a href=\"#permissions\">permissions<\/a> for that API call.<\/p>\n<div style=\"aspect-ratio: 1932 \/ 496;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/api-permissions.jpg\" title=\"API permissions\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"496\" width=\"1932\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/api-permissions.jpg#ZgotmplZ\" alt=\"API permissions\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In a nutshell, templates encapsulate the logic you would otherwise introduce with custom code. By introducing APIs with <strong>permissions<\/strong>, the templates can be configured to work in a secure and easily managed context.<\/p>\n<p>An added level of security is the introduction of <a href=\"#policies-reference\"><strong>policies<\/strong><\/a>, where you as the site owner can add some code to the web page itself, which can have additional levels of control over how template permissions are resolved.<\/p>\n<p>For example, if I have a tag configured to send hits to some endpoint, I can write a policy on the page that only allows pixel requests to one of the many endpoints configured in the tag.<\/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:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n<span style=\"color:#00a\">function<\/span> gtag(){dataLayer.push(arguments);}\n\ngtag(<span style=\"color:#a50\">'policy'<\/span>, <span style=\"color:#a50\">'send_pixel'<\/span>, <span style=\"color:#00a\">function<\/span>(container, policy, data) {\n  <span style=\"color:#00a\">if<\/span> (data.url !== <span style=\"color:#a50\">'https:\/\/snowplow.simoahava.com\/i'<\/span>) {\n    <span style=\"color:#00a\">throw<\/span>(<span style=\"color:#a50\">'Invalid pixel endpoint!'<\/span>);\n  } <span style=\"color:#00a\">else<\/span> {\n    <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n  }\n});\n<\/code><\/pre>\n<\/div>\n<p>With that policy in place, the image request will only be executed if the endpoint URL is <code>https:\/\/snowplow.simoahava.com\/i<\/code>. Otherwise, the tag will fail in an error, and you can see the error message in the <a href=\"https:\/\/www.simoahava.com\/analytics\/new-errors-tab-preview-mode\/\"><strong>Errors<\/strong> tab<\/a> of Preview mode.<\/p>\n<div style=\"aspect-ratio: 1066 \/ 227;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-errors.jpg\" title=\"Tag errors\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"227\" width=\"1066\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-errors.jpg#ZgotmplZ\" alt=\"Tag errors\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>An additional perk of using templates is that you don\u2019t have to add the nasty <code>unsafe-eval<\/code> keyword to your <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-content-security-policy\/\">Content Security Policy<\/a>. Any code run through a template is compiled into JavaScript when the container is written, and thus doesn\u2019t require the use of <code>eval()<\/code>.<\/p>\n<p>Conversely, with Custom HTML tags and Custom JavaScript variables, the code is written into a string which is then compiled with <code>eval()<\/code> at runtime. This is a bad practice and requires a huge compromise in security if using a Content Security Policy.<\/p>\n<p>I hope you can see the usefulness of Custom Templates. Imagine a library of Custom Templates, where anyone can share their own work for others to download and use in their containers. Smaller brands and companies could finally get their tools and platforms out there for the masses using Google Tag Manager.<\/p>\n<blockquote>\n<p><strong>Update 2 October 2019<\/strong>: You no longer have to imagine such a library as it now exists. Check out the <a href=\"https:\/\/tagmanager.google.com\/gallery\/\">Community Template Gallery<\/a> as well as my <a href=\"https:\/\/www.simoahava.com\/analytics\/introducing-tag-manager-template-gallery\/\">introduction<\/a> to it.<\/p>\n<\/blockquote>\n<h2 id=\"getting-started\">Getting started<\/h2>\n<p>Before exhausting you with all the details about custom templates (and trust me, there\u2019s a <strong>lot<\/strong> to digest in the feature), I want to start by walking you through creating a <strong>tag template<\/strong> and a <strong>variable template<\/strong>. We won\u2019t use all the most complex features for this, but it should serve as a nice intro to how custom templates work in Google Tag Manager.<\/p>\n<p>Be sure to check out <a href=\"https:\/\/www.simoahava.com\/gtm-tips\/build-custom-universal-analytics-client-server-side-tagging\/\">this guide<\/a> for a walkthrough of building a Client template for <strong>server-side tagging<\/strong>.<\/p>\n<p>Don\u2019t forget to check out my other article, which covers the creation of a <a href=\"https:\/\/www.simoahava.com\/analytics\/create-facebook-pixel-custom-tag-template\/\">Facebook pixel template<\/a>. It should provide a more comprehensive (and more overwhelming) look at how templates are created.<\/p>\n<h3 id=\"tag-template-walkthrough\">Tag template walkthrough<\/h3>\n<p>In this walkthrough, we\u2019ll go through how to create a simple <strong>script injection tag<\/strong>. This is how many of the third-party vendors out there want their scripts to be loaded.<\/p>\n<p>We\u2019ll use a wonderful company called <a href=\"https:\/\/conductrics.com\/\">Conductrics<\/a> as an example. They have developed a tool with which you can do A\/B-testing and personalization, using ML-driven targeting logic, dynamic goals, server-side and client-side deployment options, and a whole host of other features to help you answer those difficult business questions you have with <strong>data<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1860 \/ 832;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics.jpg\" title=\"Conductrics tag template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"832\" width=\"1860\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics.jpg#ZgotmplZ\" alt=\"Conductrics tag template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Note!<\/strong> You can of course replace the Conductrics-specific stuff with some other vendor source URL, if you want. The steps you take in this guide would still be identical.<\/p>\n<p>The tag template is simple, by design. Conductrics offers the option to host the required JavaScript for you, so all you need to do is add the <code><script\/><\/code> tag to the page that loads the JavaScript library from Conductrics\u2019 server.<\/p>\n<p>However, I\u2019ve added some UI sugar to make the setup slightly more interesting.<\/p>\n<p>Basically, all templates comprise four components:<\/p>\n<ol>\n<li>\n<p>The details, which determine the template name, logo, and description.<\/p>\n<\/li>\n<li>\n<p>The user interface, which governs the fields and field configurations the template has.<\/p>\n<\/li>\n<li>\n<p>The code editor, which makes use of whatever the user input into the fields to run the actual template code.<\/p>\n<\/li>\n<li>\n<p>Permissions, which determine what type of code can be run by the tag.<\/p>\n<\/li>\n<\/ol>\n<p>We\u2019ll walk through each of these steps here.<\/p>\n<h4 id=\"step-1---create-and-set-the-details-of-the-tag-template\">Step 1 &#8211; Create and set the details of the tag template<\/h4>\n<p>The first thing you need to do is create a new tag template:<\/p>\n<div style=\"aspect-ratio: 2484 \/ 916;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/create-new-tag-template.jpg\" title=\"Create new tag template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"916\" width=\"2484\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/create-new-tag-template.jpg#ZgotmplZ\" alt=\"Create new tag template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, fill in some details. For the image, I used <a href=\"https:\/\/dribbble.com\/shots\/584991--Process\">the logo<\/a> created by Conductrics\u2019 brand designer <a href=\"https:\/\/dribbble.com\/shablazm\/projects\/58695-Conductrics\">Joshua McCowen<\/a>.<\/p>\n<div style=\"aspect-ratio: 1558 \/ 1112;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics-settings.jpg\" title=\"Conductrics settings\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1112\" width=\"1558\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics-settings.jpg#ZgotmplZ\" alt=\"Conductrics settings\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can <strong>Save<\/strong> the template by clicking the respective icon in the top-right corner now. You should see the logo and the template title in the preview window.<\/p>\n<div style=\"aspect-ratio: 1888 \/ 570;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/tag-preview.jpg\" title=\"Tag preview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"570\" width=\"1888\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/tag-preview.jpg#ZgotmplZ\" alt=\"Tag preview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>There! Almost done. Well, not quite.<\/p>\n<h4 id=\"step-2---create-the-ui\">Step 2 &#8211; Create the UI<\/h4>\n<p>Now we need to create the bells and whistles of the tag\u2019s actual user interface.<\/p>\n<p>First, click the <strong>Fields<\/strong> tab to open the <a href=\"#fields-editor\">Fields editor<\/a>. Then, click the blue <strong>Add Field<\/strong> button.<\/p>\n<div style=\"aspect-ratio: 924 \/ 400;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/add-field-button.jpg\" title=\"Add field button\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"400\" width=\"924\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/add-field-button.jpg#ZgotmplZ\" alt=\"Add field button\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In the overlay that opens, select <strong>Text input<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1436 \/ 464;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/choose-text-input.jpg\" title=\"Choose text input\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"464\" width=\"1436\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/choose-text-input.jpg#ZgotmplZ\" alt=\"Choose text input\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You should see a <a href=\"#text-input\">text input<\/a> field appear in the Fields editor. Rename the field to <strong>sourceUrl<\/strong>, and edit the <a href=\"#display-name\">Display name<\/a> setting. The field name is used in the code editor, and the <strong>Display name<\/strong> setting is what the user sees above the field when editing the tag settings.<\/p>\n<div style=\"aspect-ratio: 1900 \/ 568;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/rename-text-field.jpg\" title=\"Rename the text field\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"568\" width=\"1900\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/rename-text-field.jpg#ZgotmplZ\" alt=\"Rename the text field\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The UI could be ready now &#8211; it\u2019s really the only field and the only configuration you\u2019d need.<\/p>\n<p>But let\u2019s make it a bit more robust by adding some <strong>validation<\/strong>.<\/p>\n<p>Click the <strong>cogwheel<\/strong> icon associated with the field to open the <a href=\"#field-configuration\">Field configuration<\/a> overlay. In the overlay, make sure <strong>Display name<\/strong>, <strong>Help text<\/strong>, and <strong>Validation rules<\/strong> are all toggled <strong>ON<\/strong>.<\/p>\n<p>Each field type has its own set of configurations you can edit to make the field more versatile.<\/p>\n<div style=\"aspect-ratio: 2382 \/ 1390;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/field-configurations.jpg\" title=\"Field configurations\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1390\" width=\"2382\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/field-configurations.jpg#ZgotmplZ\" alt=\"Field configurations\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Close the overlay by clicking the <strong>X<\/strong> in the corner, or anywhere outside the overlay.<\/p>\n<p>Next, add some <a href=\"#help-text\">Help text<\/a>. Help text can be seen by hovering over the little question mark next to the Display name when editing the tag.<\/p>\n<div style=\"aspect-ratio: 3624 \/ 1058;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/add-help-text.jpg\" title=\"Add help text\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1058\" width=\"3624\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/add-help-text.jpg#ZgotmplZ\" alt=\"Add help text\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can <strong>Save<\/strong> the template periodically to refresh the template preview and see the changes there.<\/p>\n<p>Next, let\u2019s add some <a href=\"#validation-rules\">Validation rules<\/a>. These can be used to ensure the user adds valid values to the fields.<\/p>\n<p>Click <strong>Add rule<\/strong> and edit the rule to <strong>match a regular expression<\/strong> where the expression is <code>^https:\/\/.*<\/code>. Validation regular expressions look for <strong>full matches only<\/strong>, so you need to add leading and\/or trailing <code>.*<\/code> to use an open-ended pattern.<\/p>\n<div style=\"aspect-ratio: 1820 \/ 516;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/first-validation-rule.jpg\" title=\"First validation rule\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"516\" width=\"1820\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/first-validation-rule.jpg#ZgotmplZ\" alt=\"First validation rule\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, click the little action menu in the top corner of the validation rule box, and select <strong>Show advanced settings<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1326 \/ 374;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-advanced-settings.jpg\" title=\"Show advanced settings\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"374\" width=\"1326\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-advanced-settings.jpg#ZgotmplZ\" alt=\"Show advanced settings\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Validation rules have two advanced settings. The first is where you can provide a <strong>custom error message<\/strong> (which we\u2019ll use). The second is one where you can establish conditions for <strong>when<\/strong> this validation rule is active (or inactive).<\/p>\n<p>In this case, let\u2019s add a descriptive error message. Set the <strong>Error message<\/strong> field to <code>The URL must start with \"https:\/\/\".<\/code>.<\/p>\n<div style=\"aspect-ratio: 986 \/ 362;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-message.jpg\" title=\"Error message\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"362\" width=\"986\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-message.jpg#ZgotmplZ\" alt=\"Error message\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can now quickly <strong>test<\/strong> how this works. Click <strong>Save<\/strong> in the top right corner, then click the tag template in the preview mode to enter edit mode. Add some string to the text input field that <strong>doesn\u2019t<\/strong> start with \u201chttps:\/\/\u201d, and click the <strong>Test<\/strong> button in the top-right corner. You should see your error message.<\/p>\n<div style=\"aspect-ratio: 1868 \/ 986;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-message-shown.jpg\" title=\"Error message shown\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"986\" width=\"1868\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-message-shown.jpg#ZgotmplZ\" alt=\"Error message shown\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Cool, right?<\/p>\n<p>Let\u2019s add <strong>two<\/strong> more validation rules. Make them look like this:<\/p>\n<div style=\"aspect-ratio: 1750 \/ 1306;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/last-validation-rules.jpg\" title=\"Last validation rules\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1306\" width=\"1750\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/last-validation-rules.jpg#ZgotmplZ\" alt=\"Last validation rules\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The first rule ensures that the script is loaded from a <code>*.conductrics.com<\/code> domain, and the second rule requires that the script URL has the <code>apikey<\/code> parameter.<\/p>\n<p>One final thing we\u2019ll add to the user interface is a simple <strong>debug<\/strong> toggle.<\/p>\n<p>Click the <strong>Add field<\/strong> button, and select <strong>Checkbox<\/strong> from the overlay.<\/p>\n<div style=\"aspect-ratio: 1362 \/ 550;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/checkbox.jpg\" title=\"Checkbox\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"550\" width=\"1362\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/checkbox.jpg#ZgotmplZ\" alt=\"Checkbox\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Set the field name to <strong>debug<\/strong>, and set the <strong>Checkbox text<\/strong> field to <strong>Log debug messages to console<\/strong>. Feel free to save the template to see how the checkbox looks like in the wild.<\/p>\n<div style=\"aspect-ratio: 2852 \/ 796;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/checkbox-in-preview.jpg\" title=\"Checkbox in template preview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"796\" width=\"2852\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/checkbox-in-preview.jpg#ZgotmplZ\" alt=\"Checkbox in template preview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>We\u2019re all done with the UI, finally!<\/p>\n<h4 id=\"step-3---add-some-code\">Step 3 &#8211; Add some code<\/h4>\n<p>Now, select the <strong>Code<\/strong> tab from the template editor. You should see some boilerplate code that will help you get started (we\u2019ll replace this with some other stuff soon enough).<\/p>\n<div style=\"aspect-ratio: 1904 \/ 758;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/code-editor-template.jpg\" title=\"Code editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"758\" width=\"1904\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/code-editor-template.jpg#ZgotmplZ\" alt=\"Code editor\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>For <strong>tag<\/strong> templates, the code you write has three components you need to be aware of.<\/p>\n<ul>\n<li>\n<p>The <strong>code format<\/strong> itself, which utilizes a special, <a href=\"#sandboxed-javascript\">sandboxed JavaScript<\/a>. This sandboxed JS offers a bunch of <a href=\"#template-apis\">template APIs<\/a> you can use to work with JavaScript outside the scope of the code itself (access <code>dataLayer<\/code>, write cookies, and so forth).<\/p>\n<\/li>\n<li>\n<p>The <code>data<\/code> object, which comprises the contents of the tag fields the user might have interacted with.<\/p>\n<\/li>\n<li>\n<p>The <code>data.gtmOnSuccess()<\/code> and <code>data.gtmOnFailure()<\/code> methods, which indicate success or failure, respectively, of the tag execution.<\/p>\n<\/li>\n<\/ul>\n<p>With these three in mind, we need to do the following.<\/p>\n<ol>\n<li>\n<p>We need the tag to load Conductrics\u2019 JavaScript from their network, which means we\u2019ll utilize the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#injectscript\"><code>injectScript<\/code> API<\/a> to do so.<\/p>\n<\/li>\n<li>\n<p>We\u2019ll take the URL for the <code>injectScript<\/code> API from the text field in the tag, and if the user has chosen to write debug messages to the console, we\u2019ll respect that choice.<\/p>\n<\/li>\n<li>\n<p>If the script loads fine, we\u2019ll signal this with <code>data.gtmOnSuccess()<\/code>, but if there\u2019s a failure (such as a <code>404<\/code> error), we\u2019ll call the <code>data.gtmOnFailure()<\/code> method.<\/p>\n<\/li>\n<\/ol>\n<p><strong>Success<\/strong> and <strong>failure<\/strong> are relevant for <a href=\"#tag-templates-in-the-code-editor\">Preview mode output<\/a> and also for <a href=\"https:\/\/www.simoahava.com\/analytics\/understanding-tag-sequencing-in-google-tag-manager\/\">tag sequencing<\/a>.<\/p>\n<p>Without further ado, here\u2019s the complete code you should replace the contents of the code editor with:<\/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:#aaa;font-style:italic\">\/\/ Require the necessary APIs\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> logToConsole = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n<span style=\"color:#00a\">const<\/span> injectScript = require(<span style=\"color:#a50\">'injectScript'<\/span>);\n<span style=\"color:#00a\">const<\/span> queryPermission = require(<span style=\"color:#a50\">'queryPermission'<\/span>);\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ Get the URL the user input into the text field\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> url = data.sourceUrl;\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ If the user chose to log debug output, initialize the logging method\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> log = data.debug ? logToConsole : (() =&gt; {});\n\nlog(<span style=\"color:#a50\">'Conductrics: Loading script from '<\/span> + url);\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ If the script loaded successfully, log a message and signal success\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> onSuccess = () =&gt; {\n  log(<span style=\"color:#a50\">'Conductrics: Script loaded successfully.'<\/span>);\n  data.gtmOnSuccess();\n};\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ If the script fails to load, log a message and signal failure\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> onFailure = () =&gt; {\n  log(<span style=\"color:#a50\">'Conductrics: Script load failed.'<\/span>);\n  data.gtmOnFailure();\n};\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ If the URL input by the user matches the permissions set for the template,\n<\/span><span style=\"color:#aaa;font-style:italic\">\/\/ inject the script with the onSuccess and onFailure methods as callbacks.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">if<\/span> (queryPermission(<span style=\"color:#a50\">'inject_script'<\/span>, url)) {\n  injectScript(url, onSuccess, onFailure);\n} <span style=\"color:#00a\">else<\/span> {\n  log(<span style=\"color:#a50\">'Conductrics: Script load failed due to permissions mismatch.'<\/span>);\n  data.gtmOnFailure();\n}\n<\/code><\/pre>\n<\/div>\n<p>The code comments should help you understand how the code works. Here are some key things about the code:<\/p>\n<ul>\n<li>\n<p>The <strong>APIs<\/strong> are loaded with the <code>require()<\/code> method. You must use these APIs &#8211; their counterparts in browser JavaScript have been suppressed. For example, <code>console.log()<\/code> would not work, nor would <code>document.createElement()<\/code>.<\/p>\n<\/li>\n<li>\n<p>The <code>data<\/code> object has keys matching the <strong>field names<\/strong> you edited in the field editor. Any value those fields have will be the values stored in the <code>data<\/code> object. Thus, if the user typed <code>hello<\/code> into the <code>sourceUrl<\/code> field, that value would be available via <code>data.sourceUrl<\/code>.<\/p>\n<\/li>\n<li>\n<p>Using <code>queryPermission()<\/code> is a good way to ensure the user input matches the permissions set in the template. The permissions are updated <strong>automatically<\/strong> when you <code>require()<\/code> a specific API in the code editor (we\u2019ll get to the permissions in the next chapter).<\/p>\n<\/li>\n<\/ul>\n<p>Key thing to note is that this editor is a <strong>JavaScript editor<\/strong>. Thus, unlike with Custom HTML tags, you <strong>should not<\/strong> wrap the code with <code><script\/><\/code> and <code\/>.<\/p>\n<p>Once you\u2019re done, click <strong>Save<\/strong> and move on to the next chapter.<\/p>\n<h4 id=\"step-4---modify-permissions\">Step 4 &#8211; Modify permissions<\/h4>\n<p>The final thing to edit are the <strong>permissions<\/strong>. When you <code>require()<\/code> APIs, you\u2019ll also automatically enable their permission configurations in the <strong>Permissions<\/strong> tab. See the <a href=\"#permissions\">chapter on permissions<\/a> for more details on how these work.<\/p>\n<p>Anyway, since you are using the <code>logToConsole<\/code> and <code>injectScript<\/code> APIs, their permissions are now available for editing. The <code>queryPermission<\/code> and <code>require<\/code> APIs don\u2019t have any permissions associated with them.<\/p>\n<p>Click to the <strong>Permissions<\/strong> tab and expand the two permissions you find.<\/p>\n<div style=\"aspect-ratio: 900 \/ 431;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permissions-expanded.jpg\" title=\"Permissions expanded\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"431\" width=\"900\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permissions-expanded.jpg#ZgotmplZ\" alt=\"Permissions expanded\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The <a href=\"#injects-scripts\">Injects Scripts<\/a> permission is, surprise surprise, for the <code>injectScript<\/code> API. It expects URL match patterns that the value input by the user into the text field must match.<\/p>\n<p>Add the value <code>https:\/\/*.conductrics.com\/<\/code> into the text field.<\/p>\n<p>This value basically means that the script URL injected in the page must be a subdomain of <code>conductrics.com<\/code>, and it can have any path structure (the <code>\/<\/code> after the hostname acts as a wildcard). Thus it will match, for example:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/conductrics.com\/tracker<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/de.cdn-v3.conductrics.com\/ac-aBcDeFgH\/v3\/agent-api\/js\/f-aBcDeFggg\/dt-b1234567?apikey=api-w123456<\/code><\/p>\n<\/li>\n<\/ul>\n<p>The <a href=\"#logs-to-console\">Logs to Console<\/a> permission should be self-explanatory. It governs how the <code>logToConsole<\/code> API works. You can check the <strong>Always log<\/strong> option, because we manage logging to console in the template code itself.<\/p>\n<p>Right now, the permissions should look like this:<\/p>\n<div style=\"aspect-ratio: 646 \/ 368;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permission-settings-done.jpg\" title=\"Permission settings done\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"368\" width=\"646\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permission-settings-done.jpg#ZgotmplZ\" alt=\"Permission settings done\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Click <strong>Save<\/strong> to save the current template.<\/p>\n<h4 id=\"step-5---preview-and-test\">Step 5 &#8211; Preview and test<\/h4>\n<p>You can now click to edit the tag in the <strong>Template Preview<\/strong> window. When you\u2019ve added some text, you can click the <strong>Test<\/strong> button to see what happens.<\/p>\n<p>You can also choose to show a <strong>test page<\/strong> from the template menu:<\/p>\n<div style=\"aspect-ratio: 1095 \/ 684;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-preview.jpg\" title=\"Template preview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"684\" width=\"1095\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-preview.jpg#ZgotmplZ\" alt=\"Template preview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Test different things:<\/p>\n<ul>\n<li>\n<p>Try with a random, non-URL string to see the warning about the missing <code>https:\/\/<\/code>.<\/p>\n<\/li>\n<li>\n<p>Try with <code>https:\/\/<\/code> but with a hostname that doesn\u2019t contain <code>conductrics.com<\/code> to see the error for incorrect URL.<\/p>\n<\/li>\n<li>\n<p>Try with <code>https:\/\/domain.conductrics.com\/loader<\/code> to see the error for missing <code>apikey<\/code>.<\/p>\n<\/li>\n<li>\n<p>Try with <code>https:\/\/domain.conductrics.com\/loader?apikey=12345<\/code> to see the code pass with flying colors.<\/p>\n<\/li>\n<li>\n<p>Try with and without the <strong>Debug<\/strong> checkbox checked, and see how this impacts what you see in the <strong>Console<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<div style=\"aspect-ratio: 956 \/ 255;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/console-logging.jpg\" title=\"Console output\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"255\" width=\"956\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/console-logging.jpg#ZgotmplZ\" alt=\"Console output\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>If you already have a <a href=\"https:\/\/conductrics.com\/contact\/\">Conductrics account<\/a>, you can test with a real deployment URL to see the success message in the console.<\/p>\n<p>Finally, you can dig deep into the <code>iframe<\/code> of the <strong>Test page<\/strong> to find your script tag there.<\/p>\n<div style=\"aspect-ratio: 1113 \/ 268;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/script-in-test-page.jpg\" title=\"Script in the test page\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"268\" width=\"1113\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/script-in-test-page.jpg#ZgotmplZ\" alt=\"Script in the test page\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Once done testing to your satisfaction, you can do one final <strong>Save<\/strong> and then close the template editor &#8211; you are ready to create your first tag off of this template!<\/p>\n<h4 id=\"step-6---create-tag-and-preview\">Step 6 &#8211; Create tag and preview<\/h4>\n<p>In the GTM UI, go to Tags and click <strong>New<\/strong>. In the overlay that opens, find your new template and click it.<\/p>\n<div style=\"aspect-ratio: 1017 \/ 289;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/create-new-tag.jpg\" title=\"Create new tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"289\" width=\"1017\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/create-new-tag.jpg#ZgotmplZ\" alt=\"Create new tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>This screen should be familiar to you. The only difference to native templates in GTM is the <strong>Tag permissions<\/strong> bar. Click it to preview what permissions have been set for the template.<\/p>\n<div style=\"aspect-ratio: 862 \/ 324;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permissions-in-the-template.jpg\" title=\"Permissions in the template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"324\" width=\"862\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/permissions-in-the-template.jpg#ZgotmplZ\" alt=\"Permissions in the template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Then, fill in the tag fields as you would with a regular template. For testing purposes, just set it to fire on the <strong>All Pages<\/strong> trigger.<\/p>\n<p>You can try with invalid URLs to see the error messages. However, to test how the tag actually works, use a correct (but ultimately invalid) URL like <code>https:\/\/domain.conductrics.com\/loader?apikey=12345<\/code>, and the tag should look like this:<\/p>\n<div style=\"aspect-ratio: 1179 \/ 583;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/first-conductrics-tag.jpg\" title=\"First Conductrics tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"583\" width=\"1179\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/first-conductrics-tag.jpg#ZgotmplZ\" alt=\"First Conductrics tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Then, go the <strong>Preview mode<\/strong> and enter your site.<\/p>\n<p>You should see the tag having fired, but in <strong>Failed<\/strong> state because the endpoint returned a <code>404<\/code> error.<\/p>\n<div style=\"aspect-ratio: 612 \/ 250;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics-failed.jpg\" title=\"Conductrics failed\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"250\" width=\"612\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/conductrics-failed.jpg#ZgotmplZ\" alt=\"Conductrics failed\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Check out the <a href=\"https:\/\/kb.mailster.co\/how-can-i-open-the-browsers-console\/\">JavaScript console<\/a>, too. You should see some relevant output there.<\/p>\n<div style=\"aspect-ratio: 627 \/ 151;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/javascript-console-output.jpg\" title=\"JavaScript console output\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"151\" width=\"627\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/javascript-console-output.jpg#ZgotmplZ\" alt=\"JavaScript console output\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Finally, since we\u2019re <strong>injecting a script<\/strong>, you can drill into the page elements to find it in the <code\/> of the page.<\/p>\n<div style=\"aspect-ratio: 771 \/ 227;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/elements-panel.jpg\" title=\"Elements panel\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"227\" width=\"771\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/elements-panel.jpg#ZgotmplZ\" alt=\"Elements panel\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h4 id=\"step-7---youre-done\">Step 7 &#8211; You\u2019re done!<\/h4>\n<p><strong>And that\u2019s it!<\/strong>. This was an extremely simple use case, and it might seem like a really complicated way to go about it. However, remember that you\u2019re providing controls for <strong>governance<\/strong> and <strong>responsible<\/strong> code injection here.<\/p>\n<p>The use of <a href=\"#permissions\">permissions<\/a>, <a href=\"#sandboxed-javascript\">sandboxed JavaScript<\/a>, and, if you choose to use them, <a href=\"#policies-reference\">policies<\/a> help you run a tight ship on what the custom tags can and can\u2019t do on the site.<\/p>\n<p>The template itself does a simple script injection, but I hope I convinced you how powerful the UI editor can be, and we barely scratched the surface!<\/p>\n<h3 id=\"variable-template-walkthrough\">Variable template walkthrough<\/h3>\n<p>Variable templates differ from tag templates in that they only have a singular purpose: to <strong>return<\/strong> a value. Optimally, they should <strong>not<\/strong> have any <em>side effects<\/em>, which include e.g. setting variables in the global scope, writing cookies, pushing to <code>dataLayer<\/code>, injecting scripts, or firing pixels.<\/p>\n<p>In this example, we\u2019ll create a simple variable which is intended to work with the <a href=\"https:\/\/www.simoahava.com\/gtm-tips\/hitcallback-eventcallback\/\"><code>hitCallback<\/code><\/a> field of your Google Analytics tags.<\/p>\n<p>The idea is that the variable will return a function (<code>hitCallback<\/code> always requires a function as its value), which when executed will write a cookie into the browser. This cookie can then be used to check if less than 30 minutes (the default expiration) have passed since the last Google Analytics hit to GA, thus giving you a <em>very rough<\/em> estimate of whether a GA session is currently active.<\/p>\n<p>So yes, we\u2019re breaking the \u201cno side effects\u201d rule I literally <em>just<\/em> mentioned, but this is a bit different. It\u2019s not an uncontrollable side effect, which it would be if it fired every single time the variable is called. Instead, the functionality is restricted to the <code>hitCallback<\/code> function, which is only executed <strong>once<\/strong>, when the Google Analytics request has been dispatched.<\/p>\n<div style=\"aspect-ratio: 1590 \/ 916;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-variable.jpg\" title=\"Session cookie variable\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"916\" width=\"1590\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-variable.jpg#ZgotmplZ\" alt=\"Session cookie variable\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Note, there are <a href=\"https:\/\/www.simoahava.com\/analytics\/create-and-update-google-analytics-session-timeout-cookie\/\">more elegant ways<\/a> to handle this, but for the purposes of this guide I wanted to start off with something simple.<\/p>\n<h4 id=\"step-1---create-and-set-the-details-of-the-variable-template\">Step 1 &#8211; Create and set the details of the variable template<\/h4>\n<p>Browse to <strong>Templates<\/strong>, and click <strong>New<\/strong> in the corner of the <strong>Variable Templates<\/strong> area.<\/p>\n<div style=\"aspect-ratio: 2548 \/ 530;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-new-template.jpg\" title=\"New variable template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"530\" width=\"2548\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-new-template.jpg#ZgotmplZ\" alt=\"New variable template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In the view that opens, make sure the <strong>Info<\/strong> tab is selected, and add a <strong>Name<\/strong> and <strong>Description<\/strong> to the variable.<\/p>\n<div style=\"aspect-ratio: 1140 \/ 624;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-description.jpg\" title=\"Variable template details\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"624\" width=\"1140\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-description.jpg#ZgotmplZ\" alt=\"Variable template details\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>As you can see, you can add HTML styling to the description field. The text I wrote was this:<\/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-html\" data-lang=\"html\">Use this variable to write (and update) a session cookie after each Google Analytics hit by using the code&gt;hitCallback<span style=\"color:#1e90ff;font-weight:bold\">code<\/span>&gt; field in the GA tags.<\/code><\/pre>\n<\/div>\n<p>Once done, click <strong>Save<\/strong> in the top right corner and you should see the <strong>Template Preview<\/strong> area show the new template name.<\/p>\n<div style=\"aspect-ratio: 1806 \/ 414;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-preview.jpg\" title=\"Variable template preview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"414\" width=\"1806\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-preview.jpg#ZgotmplZ\" alt=\"Variable template preview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, let\u2019s create the user interface for this template!<\/p>\n<h4 id=\"step-2---create-the-ui-1\">Step 2 &#8211; Create the UI<\/h4>\n<p>Click over to the <strong>Fields<\/strong> tab in the template editor.<\/p>\n<p>This template will comprise three <a href=\"#text-input\">text input<\/a> fields. One for the cookie\u2019s <strong>maximum age<\/strong>, one for the <strong>cookie path<\/strong>, and one for the <strong>cookie domain<\/strong>.<\/p>\n<p>Click the <strong>Add Field<\/strong> button, and choose the Text Input field from the overlay.<\/p>\n<div style=\"aspect-ratio: 3188 \/ 424;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-text-input.jpg\" title=\"Text input fields\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"424\" width=\"3188\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-text-input.jpg#ZgotmplZ\" alt=\"Text input fields\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Do this two more times, so that you end up with three text input fields.<\/p>\n<p>Name the first field <code>maxAge<\/code>, the second <code>cookiePath<\/code>, and the third <code>cookieDomain<\/code>.<\/p>\n<div style=\"aspect-ratio: 1310 \/ 512;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-three-fields.jpg\" title=\"Three text fields\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"512\" width=\"1310\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-three-fields.jpg#ZgotmplZ\" alt=\"Three text fields\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Expand the first field, <code>maxAge<\/code>, and click the <strong>cogwheel<\/strong> icon to open its field configurations. Toggle on <a href=\"#always-in-summary\"><strong>Always in summary<\/strong><\/a>, <a href=\"#default-value\"><strong>Default value<\/strong><\/a>, and <a href=\"#display-name\"><strong>Display name<\/strong><\/a>.<\/p>\n<div style=\"aspect-ratio: 3834 \/ 894;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-max-age-configurations.jpg\" title=\"Max Age configurations\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"894\" width=\"3834\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-max-age-configurations.jpg#ZgotmplZ\" alt=\"Max Age configurations\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Edit the <code>maxAge<\/code> settings to be like this:n<\/p>\n<p><strong>Display name<\/strong>: Maximum age in seconds<br \/><strong>Default value<\/strong>: 1800<br \/><strong>Always in summary<\/strong>: Checked<\/p>\n<p>The <strong>Display name<\/strong> is what appears above the field in the editor.<\/p>\n<p>We\u2019ll use a <strong>Default value<\/strong> of <code>1800<\/code> seconds (that\u2019s 30 minutes), so if the user doesn\u2019t touch the field, that\u2019s the value that will be used.<\/p>\n<p><strong>Always in summary<\/strong> means that the field contents will show up when the variable is opened in the UI but not in edit mode. It\u2019s a convenience thing, not vital in any way.<\/p>\n<div style=\"aspect-ratio: 1344 \/ 570;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-max-age-ready.jpg\" title=\"Max age ready\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"570\" width=\"1344\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-max-age-ready.jpg#ZgotmplZ\" alt=\"Max age ready\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, click the <strong>cogwheel<\/strong> for the <code>cookiePath<\/code> field, and toggle the same configurations on (<strong>Display name<\/strong>, <strong>Default value<\/strong>, and <strong>Always in summary<\/strong>).<\/p>\n<p>Set them to these values:<\/p>\n<p><strong>Display name<\/strong>: Cookie path<br \/><strong>Default value<\/strong>: \/<br \/><strong>Always in summary<\/strong>: Checked<\/p>\n<p>Finally, click the <strong>cogwheel<\/strong> for the <code>cookieDomain<\/code> field, and toggle the same conditions on, together with the <strong>Help text<\/strong> configuration.<\/p>\n<p>Set them to these values:<\/p>\n<p><strong>Display name<\/strong>: Cookie domain<br \/><strong>Help text<\/strong>: Set to \u2018auto\u2019 to write the cookie on the highest possible domain name.<br \/><strong>Default value<\/strong>: auto<br \/><strong>Always in summary<\/strong>: Checked<\/p>\n<p>The fields should look like this:<\/p>\n<div style=\"aspect-ratio: 1906 \/ 1710;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-finished-fields.jpg\" title=\"Session cookie finished fields\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1710\" width=\"1906\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-finished-fields.jpg#ZgotmplZ\" alt=\"Session cookie finished fields\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The <a href=\"#help-text\"><strong>Help text<\/strong><\/a> configuration is pretty cool. If you refresh the <strong>Template Preview<\/strong>, you\u2019ll see how there\u2019s a little question mark next to the <strong>Cookie domain<\/strong> field. By hovering over it, you\u2019ll see the help text.<\/p>\n<div style=\"aspect-ratio: 1352 \/ 872;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-template-preview.jpg\" title=\"Session cookie template preview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"872\" width=\"1352\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/session-cookie-template-preview.jpg#ZgotmplZ\" alt=\"Session cookie template preview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Now you\u2019re ready to add the code!<\/p>\n<h4 id=\"step-3---add-some-code-1\">Step 3 &#8211; Add some code<\/h4>\n<p>Click the <strong>Code<\/strong> tab, and replace the contents with the following:<\/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:#aaa;font-style:italic\">\/\/ Require the necessary APIs\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> setCookie = require(<span style=\"color:#a50\">'setCookie'<\/span>);\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ Build the options object from user input\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> options = {\n  domain: data.cookieDomain,\n  <span style=\"color:#a50\">'max-age'<\/span>: data.maxAge,\n  path: data.path\n};\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ Return the hitCallback function\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">return<\/span> () =&gt; {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Set the cookie when the hit has been dispatched\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  setCookie(<span style=\"color:#a50\">'_ga_session'<\/span>, <span style=\"color:#a50\">'true'<\/span>, options);\n};\n<\/code><\/pre>\n<\/div>\n<p>As you can see, it\u2019s a <strong>very<\/strong> simple variable. It uses a single API, <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#setcookie\"><code>setCookie<\/code><\/a> (for obvious reasons), and it has a <code>return<\/code> statement at the end, which returns a function wherever the variable is called.<\/p>\n<p>If you read the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#setcookie\"><code>setCookie<\/code> specification<\/a>, you can see that it takes three arguments.<\/p>\n<p><code>setCookie(name, value, options)<\/code><\/p>\n<p>To make things a bit easier, we\u2019re building the <code>options<\/code> object before calling the method. The object has three properties, <code>domain<\/code> for the domain name, <code>max-age<\/code> for the maximum age, and <code>path<\/code> for the cookie path.<\/p>\n<p>The <code>setCookie<\/code> API has a nice feature where if you set the value of <code>domain<\/code> to <code>'auto'<\/code>, it automatically finds the highest possible (i.e. shortest) domain name it can use. Thus, if the variable is called on <code>sub.domain.simoahava.com<\/code>, the API writes it on <code>simoahava.com<\/code>.<\/p>\n<p>As you can see, there are no validations or permission checks going on here. After reading this guide, you\u2019ll be able to extend the UI to do the validations directly on the fields, or you can also check the field values in code, falling back to some valid values in case the user input is not perfect.<\/p>\n<p>Once you\u2019ve added the code, make sure to <strong>save<\/strong> the template, and then click on over to the <strong>Permissions<\/strong> tab of the editor. You\u2019ll need to make sure the template has permissions to write the cookie.<\/p>\n<h4 id=\"step-4---modify-permissions-1\">Step 4 &#8211; Modify permissions<\/h4>\n<p>In the <strong>Permissions<\/strong> tab, you should now see a permission for <a href=\"#sets-a-cookie-value\">Sets A Cookie Value<\/a>. It\u2019s added automatically when you run <code>require('setCookie')<\/code> in the template code. Pretty sweet!<\/p>\n<div style=\"aspect-ratio: 1522 \/ 466;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/sets-a-cookie-value.jpg\" title=\"Sets a cookie value\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"466\" width=\"1522\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/sets-a-cookie-value.jpg#ZgotmplZ\" alt=\"Sets a cookie value\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Expand the permission, and click the <strong>+ Add allowed cookie<\/strong> button. In the overlay that opens, configure the cookie as follows:<\/p>\n<p><strong>Cookie name<\/strong>: _ga_session<br \/><strong>Domain<\/strong>: *<br \/><strong>Path<\/strong>: *<br \/><strong>Secure<\/strong>: Any<br \/><strong>Session<\/strong>: Any<\/p>\n<p>Click <strong>Save<\/strong> in the overlay when done. This is what you should see in the permissions area:<\/p>\n<div style=\"aspect-ratio: 1898 \/ 400;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/cookie-permissions.jpg\" title=\"Cookie permissions\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"400\" width=\"1898\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/cookie-permissions.jpg#ZgotmplZ\" alt=\"Cookie permissions\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You\u2019re done with the template! Remember to <strong>Save<\/strong> it one last time.<\/p>\n<p>There\u2019s not much sense in previewing or testing it in the template editor itself. The variable returns a <strong>function<\/strong>, so the only logical place to test it is in an environment where the function is actually executed in context.<\/p>\n<p>Thus, it\u2019s time to create a variable from the template and add it to a tag!<\/p>\n<h4 id=\"step-5---create-variable-add-to-tag-and-preview\">Step 5 &#8211; Create variable, add to tag, and preview<\/h4>\n<p>Click to <strong>Variables<\/strong> in the GTM UI, and click <strong>New<\/strong> in the <strong>User-Defined Variables<\/strong> section.<\/p>\n<p>In the variable type picker, choose your newly created template from the list.<\/p>\n<div style=\"aspect-ratio: 1346 \/ 592;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/variable-picker.jpg\" title=\"Variable picker\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"592\" width=\"1346\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/variable-picker.jpg#ZgotmplZ\" alt=\"Variable picker\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can now configure the variable to your liking. The default settings are more than fine for most cases, though.<\/p>\n<div style=\"aspect-ratio: 2094 \/ 1280;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/hitcallback-session-cookie.jpg\" title=\"Hitcallback session cookie\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1280\" width=\"2094\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/hitcallback-session-cookie.jpg#ZgotmplZ\" alt=\"Hitcallback session cookie\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, find your Google Analytics Page View tag (or create one if you don\u2019t have it), check its <strong>Enable overriding settings in this tag<\/strong>, and browse to <strong>More Settings<\/strong> &gt; <strong>Fields to Set<\/strong>. Click <strong>+Add Field<\/strong>.<\/p>\n<p>Set the <strong>Field Name<\/strong> to <code>hitCallback<\/code>, and <strong>Value<\/strong> to the variable you just created.<\/p>\n<div style=\"aspect-ratio: 1850 \/ 990;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/hitcallback-in-tag.jpg\" title=\"Hitcallback in tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"990\" width=\"1850\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/hitcallback-in-tag.jpg#ZgotmplZ\" alt=\"Hitcallback in tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Save the tag, and go to <strong>Preview mode<\/strong>. Then, load the page where the Page View tag will fire.<\/p>\n<p>If all goes as planned, you should now find a new browser cookie named <code>_ga_session<\/code>, with an expiration set to the number of seconds you set in the <strong>Maximum age in seconds<\/strong> field. Easiest way to find your browser cookies is to use the developer tools of your browser.<\/p>\n<p>In Chrome, press <strong>CMD + OPT + I<\/strong> (Mac) or <strong>CTRL + SHIFT + I<\/strong> (Win\/Linux) to open the developer tools. Then, activate the <strong>Application<\/strong> tab, and select the <strong>Cookies<\/strong> option for your domain. You should see the <code>_ga_session<\/code> cookie with value <code>true<\/code>, and an expiration in the future (or in the past if you set its maximum age to <code>0<\/code>).<\/p>\n<div style=\"aspect-ratio: 2564 \/ 616;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/ga-session-cookie-dev-tools.jpg\" title=\"GA Session cookie\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"616\" width=\"2564\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/ga-session-cookie-dev-tools.jpg#ZgotmplZ\" alt=\"GA Session cookie\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>If you see the cookie then congratulations, your variable template works as intended!<\/p>\n<h4 id=\"step-7---youre-done-1\">Step 7 &#8211; You\u2019re done!<\/h4>\n<p>The purpose of this guide was to walk you through the steps how to create a variable template.<\/p>\n<p>Yes, we used an extremely simple example, but the idea was to get familiarized with the <em>routine<\/em> of template creation, rather than jump in the deep end with all the APIs, field configurations, and permissions available.<\/p>\n<p>The main difference to tag templates is that the variable needs to <strong>return<\/strong> something. Whatever happens before that final <code>return<\/code> statement is up to you, but you might want to avoid too many side effects unless you are absolutely certain they are only invoked in a specific, predictable context (such as <code>hitCallback<\/code>).<\/p>\n<p>That\u2019s it for the tutorial part! Now it\u2019s time to explore with more detail what custom templates are, how they work, and how they are such a game-changer for tag management with GTM.<\/p>\n<p>But first, take a break. You\u2019ve earned it.<\/p>\n<h2 id=\"core-concepts\">Core concepts<\/h2>\n<p>Welcome back!<\/p>\n<p>Before we get to the good stuff, let me go over some of the <strong>core concepts<\/strong> of Custom Templates. These concepts will emerge and re-emerge in much of the discussion below, and they are fundamental to understanding what Custom Templates are and what they can do.<\/p>\n<h3 id=\"sandboxed-javascript\">Sandboxed JavaScript<\/h3>\n<p>Custom Templates are written with <strong>JavaScript<\/strong>. If you are unfamiliar with the language but still aching to start working with templates, I recommend taking a look at some <a href=\"https:\/\/www.simoahava.com\/analytics\/10-javascript-concepts-for-web-analytics-implementation\/#get-the-basics-right\">learning materials<\/a> before trying your hand with the template code. Check out these (free) learning portals, too:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.freecodecamp.org\">freeCodeCamp<\/a> &#8211; Excellent and comprehensive JavaScript and web technology tracks that span everything from the very basics to creating stateful web services.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.codecademy.com\">Codecademy<\/a> &#8211; Great tracks for all sorts of programming languages and disciplines offered in a nice, interactive way.<\/p>\n<\/li>\n<\/ul>\n<p>A further complication is that Custom Templates don\u2019t actually use just any old browser JavaScript. They use a special, <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/sandboxed-javascript\"><strong>sandboxed<\/strong> version<\/a> of the JavaScript language.<\/p>\n<p>Basically, any code you write in the code editor will be automatically wrapped in a function that provides a single argument named <code>data<\/code>.<\/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-js\" data-lang=\"js\"><span style=\"color:#00a\">function<\/span>(data) {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Start of code editor code\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>\n  <span style=\"color:#00a\">const<\/span> log = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n  <span style=\"color:#00a\">const<\/span> copyFromWindow = require(<span style=\"color:#a50\">'copyFromWindow'<\/span>);\n\n  <span style=\"color:#00a\">const<\/span> ga = copyFromWindow(<span style=\"color:#a50\">'GoogleAnalyticsObject'<\/span>);\n\n  <span style=\"color:#00a\">if<\/span> (<span style=\"color:#00a\">typeof<\/span> ga === <span style=\"color:#a50\">'undefined'<\/span>) {\n    log(<span style=\"color:#a50\">'Google Analytics not loaded!'<\/span>);\n  }\n\n  log(data.userInputText);\n\n  data.gtmOnSuccess();\n\n  <span style=\"color:#aaa;font-style:italic\">\/\/ End of code editor code\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<p>The <code>data<\/code> object is really important. Each field in the template will be accessible as a property of the <code>data<\/code> object, and the value of that property will be the result of the user\u2019s interaction with the field. The <code>data<\/code> object also has the <code>gtmOnSuccess()<\/code> and <code>gtmOnFailure()<\/code> methods you must use to signal the tag\u2019s successful completion or its failure. Variable completion is signalled by a <code>return<\/code> statement.<\/p>\n<p>In addition to being automatically wrapped as a function body, the set of JavaScript methods and accessors available to you is limited. Basically, you will have no access to the global <code>window<\/code> object. This includes things like <code>location<\/code>, <code>document<\/code> (and <code>document.cookie<\/code>), <code>console<\/code>, and any constructors (such as <code>new Date()<\/code>.<\/p>\n<p>To access these global methods and properties, you\u2019ll need to use the <strong>template APIs<\/strong> exposed by the template editor.<\/p>\n<h3 id=\"es6-syntax\">ES6+ syntax<\/h3>\n<p>ES6 (ECMAScript 6) is one of the most significant updates the JavaScript standard, originally released in 2015, with prominent support in all the major browsers. The code editor in GTM\u2019s templates supports <strong>some<\/strong> ES6 features. These features include:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/medium.com\/front-end-weekly\/es6-cool-stuffs-var-let-and-const-in-depth-24512e593268\"><strong><code>const<\/code> and <code>let<\/code> keywords<\/strong><\/a>. These two keywords are offered as alternatives to JavaScript\u2019s <code>var<\/code> keyword. The main difference is that <code>const<\/code> and <code>let<\/code> have <strong>block-level scope<\/strong>, meaning they are scoped to the context of the wrapping <code>{<\/code> and <code>}<\/code>, rather than the whole surrounding function context as with <code>var<\/code>. Furthermore, there\u2019s no <a href=\"https:\/\/www.w3schools.com\/js\/js_hoisting.asp\">variable hoisting<\/a> &#8211; <code>const<\/code> and <code>let<\/code> variables cannot be referenced before their declaration. Finally, <code>const<\/code> variables cannot be reassigned.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Functions\/Arrow_functions\"><strong>Arrow functions<\/strong><\/a>. Arrow functions are a new way to write JavaScript function expressions. It\u2019s syntactically more compact, so pursuers of \u201celegant code\u201d rejoice. For example, <code>var multiplyByTwo = function(a) { return a*2; };<\/code> becomes <code>const multiplyByTwo = a =&gt; a*2;<\/code>. Unlike \u201cregular\u201d JavaScript functions, there\u2019s no <code>this<\/code> binding and no access to the <code>arguments<\/code> object.<\/p>\n<\/li>\n<\/ul>\n<p>You are of course free to use the \u201cold\u201d style of JavaScript. In the templates\u2019 code editor, I will try to adhere to ES6 syntax purely out of habit, but also because using <code>const<\/code> and <code>let<\/code> actually has some functional weight in the code, too.<\/p>\n<h3 id=\"restrictions-to-what-type-of-data-you-can-handle\">Restrictions to what type of data you can handle<\/h3>\n<p>To prevent users from circumventing template permissions and from running code that breaks through the templates\u2019 sandbox, Google Tag Manager has a number of suppression mechanisms built in.<\/p>\n<ol>\n<li>\n<p><strong>You can\u2019t access <code>window<\/code> or <code>document<\/code> directly<\/strong>. Access to the global namespace is restricted to <a href=\"#template-apis\">template APIs<\/a>. Even if you tried something clever such as returning <code>window.setTimeout<\/code> in a JavaScript variable, so that it\u2019s <em>technically<\/em> not in the code editor itself, the template editor automatically parses all variables and user-based input brought into the template before it is made accessible to the code editor.<\/p>\n<\/li>\n<li>\n<p><strong>You can\u2019t pass non-plain objects<\/strong>, such as instances created with construtors, to the template code. It\u2019s difficult to contain security of these, because the prototype chain can be manipulated by code outside the template, making the template itself vulnerable and less secure. This basically means that things like <a href=\"https:\/\/www.simoahava.com\/analytics\/customtask-the-guide\/\"><code>customTask<\/code><\/a> will not be possible to do with variable templates for now, because it requires access to a constructed, non-plain <code>model<\/code> object to function.<\/p>\n<\/li>\n<li>\n<p><strong>You can\u2019t access DOM elements<\/strong>. This is kind of the same as (2), because a DOM element represents a complex, non-plain object type. Nevertheless, it means that you can\u2019t access things like <code>{{Click Element}}<\/code> in template code.<\/p>\n<\/li>\n<\/ol>\n<div style=\"aspect-ratio: 957 \/ 351;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/05\/template-restrictions.jpg\" title=\"Template restrictions\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"351\" width=\"957\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/05\/template-restrictions.jpg#ZgotmplZ\" alt=\"Template restrictions\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In time, I\u2019m certain the proliferation of APIs in the template will solve many of the restrictions above, but first and foremost the point of templates is to add a layer of security to prevent scripts outside the template from messing with the code within.<\/p>\n<p>Another one of the idiosyncracies of the templates\u2019 sandboxed JavaScript is how function expressions exposed outside the template code are encapsulated in a <strong>wrapper<\/strong> by GTM.<\/p>\n<p>The purpose of this wrapper is to make sure functions set in the window or returned by the variable template can\u2019t be used to circumvent permissions set in the template.<\/p>\n<p>The wrapper itself is <strong>almost always<\/strong> inconsequential, because it passes the parameters collected by the wrapper to the function created in or handled by the template. However, if any one of the parameters violates the restrictions listed above, the parameter is suppressed and replaced with <code>undefined<\/code>.<\/p>\n<h3 id=\"template-apis\">Template APIs<\/h3>\n<p>The most common global properties and methods you\u2019ll need to use are abstracted behind custom <strong>APIs<\/strong>. We\u2019ve covered a number of API examples in the preceding chapters. For example, there\u2019s <code>logToConsole<\/code> for logging items to the JavaScript console of the browser, and there\u2019s <code>copyFromWindow<\/code> for accessing global variables defined in the <code>window<\/code> object.<\/p>\n<p>Each API comes with its own configurable set of permissions. The <code>copyFromWindow<\/code> API, for example, requires that you define the global keys the code has access to. As soon as you type the <code>require('copyFromWindow')<\/code> statement and refresh the template, the <strong>Accesses Global Variables<\/strong> permissions will become available in the respective tab.<\/p>\n<div style=\"aspect-ratio: 962 \/ 304;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/copyfromwindow-permissions.jpg\" title=\"Accesses global variables\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"304\" width=\"962\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/copyfromwindow-permissions.jpg#ZgotmplZ\" alt=\"Accesses global variables\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>As you can see, for these particular permissions you can define the keys and whether the code has read and\/or write and\/or execution permissions for them. You might have guessed now that <strong>Access Global Variables<\/strong> is not limited to just <code>copyFromWindow<\/code> (which is read-only), but also determines the usefulness of e.g. <code>setInWindow<\/code> (for writing\/setting global variables) and <code>callInWindow<\/code> (for calling global methods).<\/p>\n<p>The purpose of this sandboxed JavaScript is to give you a <strong>safe and secure<\/strong> JavaScript environment to write and run your code in. The interplay between your code and the permissions model is designed to produce code that is as conservative as possible without compromising the runtime logic of what you want to do with the code.<\/p>\n<p>This doesn\u2019t mean that you can\u2019t cause havoc with your custom template &#8211; quite the contrary. However, the user interface guides you to make the correct choices when choosing the APIs and the permissions thereof. Hopefully the guide you are currently reading will further help you understand how to make your code run in the most efficient and responsible way possible.<\/p>\n<h3 id=\"server-side-tagging\">Server-side tagging<\/h3>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/server-side-tagging-google-tag-manager\/\">Server-side tagging<\/a> has its <a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/api\">own set of APIs<\/a>, which mainly revolve around parsing HTTP requests and compiling HTTP responses. The purpose of a Client is to read the incoming requests, launch virtual container processes for tags and triggers, and then build a response back to the source of the original request.<\/p>\n<p>This guide is mostly focused on Custom Templates in web containers, but all the main features apply to Server-side tagging as well.<\/p>\n<h3 id=\"policies\">Policies<\/h3>\n<p>The counterpart of permissions are <strong>policies<\/strong>. Policies give the site owner the ability to block potentially hazardous code from running. It\u2019s somewhat similar to Google Tag Manager\u2019s <a href=\"https:\/\/developers.google.com\/tag-manager\/devguide#restrict\">whitelist\/blacklist<\/a> feature, except with policies you have extremely granular access to how individual permissions are handled.<\/p>\n<p>Policies are basically <code>dataLayer<\/code> commands which specify what happens when a Custom Template for which some permissions have been set tries to execute on the page.<\/p>\n<p>If you don\u2019t define any policies then the tag or variable will run its course unimpeded.<\/p>\n<p>However, you can create a policy which is invoked whenever some specific permission is accessed by the template. Let me show you an example:<\/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> getCookie = require(<span style=\"color:#a50\">'getCookieValues'<\/span>);\n<span style=\"color:#00a\">const<\/span> log = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n\nlog(getCookie(<span style=\"color:#a50\">'_user_id'<\/span>));\ndata.gtmOnSuccess();\n<\/code><\/pre>\n<\/div>\n<p>The template code above uses the <code>getCookieValues<\/code> API to log the value of a cookie named <code>_user_id<\/code>. When you save that code, a new permission appears in the editor, and you need to whitelist the cookie names the code is allowed to access:<\/p>\n<div style=\"aspect-ratio: 610 \/ 178;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/whitelist-cookie-values.jpg\" title=\"Whitelisted cookie values\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"178\" width=\"610\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/whitelist-cookie-values.jpg#ZgotmplZ\" alt=\"Whitelisted cookie values\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Now, if you didn\u2019t specify a policy, the code would always log the cookie value into the console when the tag runs, because the <code>_user_id<\/code> cookie has been whitelisted in the tag permissions.<\/p>\n<p>However, let\u2019s say the page has the following code in the HTML:<\/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:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n<span style=\"color:#00a\">function<\/span> gtag(){dataLayer.push(arguments);}\n\ngtag(<span style=\"color:#a50\">'policy'<\/span>, <span style=\"color:#a50\">'get_cookies'<\/span>, <span style=\"color:#00a\">function<\/span>(container, policy, data) {\n  <span style=\"color:#00a\">if<\/span> (data.name === <span style=\"color:#a50\">'_user_id'<\/span>) {\n    <span style=\"color:#00a\">throw<\/span>(<span style=\"color:#a50\">'You are not allowed to query _user_id on this page!'<\/span>);\n  }\n  <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n});\n<\/code><\/pre>\n<\/div>\n<blockquote>\n<p>Don\u2019t be confused by the <code>gtag()<\/code> command &#8211; policies use the <code>gtag()<\/code> method, which is essentially a helper to push the arguments into <code>dataLayer<\/code>. You do <strong>not<\/strong> need to download the gtag.js library to be able to run policies on the site template.<\/p>\n<\/blockquote>\n<p>Now when the tag is run and the <code>getCookie('_user_id')<\/code> code is executed, the policy you created will activate. This policy checks if the requested cookie was named <code>_user_id<\/code>, and reacts by throwing an error. Perhaps the developers have deemed it too risky to allow GTM to query the <code>_user_id<\/code> cookie like this.<\/p>\n<p>You don\u2019t <strong>need<\/strong> policies to work with Google Tag Manager\u2019s Custom Templates. However, given how popular Custom Templates are likely to become, I do expect to see more and more policies defined, too.<\/p>\n<p>Be sure to check out the <a href=\"#policy-reference\">policy reference<\/a> at the end of this guide for more details on how individual policies should be set.<\/p>\n<h3 id=\"tests\">Tests<\/h3>\n<p><strong>Tests<\/strong> allow you to write <em>unit tests<\/em> for your template code directly in the editor. The <strong>tests<\/strong> feature comprises a number of APIs you can use to, for example, mock the data object and write assertions against the compiled and executed template code.<\/p>\n<div style=\"aspect-ratio: 611 \/ 288;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/11\/template-test-example.jpg\" title=\"Tests\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"288\" width=\"611\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/11\/template-test-example.jpg#ZgotmplZ\" alt=\"Tests\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>For more information about how to write and run tests with custom templates, see this guide:<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/writing-tests-for-custom-templates-google-tag-manager\/\">Writing Tests For Custom Templates In Google Tag Manager<\/a><\/p>\n<h2 id=\"official-documentation\">Official documentation<\/h2>\n<p>When working with <strong>Custom Templates<\/strong>, you should have two documents at hand:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api\"><strong>Custom template APIs reference<\/strong><\/a> &#8211; This document introduces the various APIs you\u2019ll need to use if you want your code to run beyond the boundaries of the sandbox.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/permissions\"><strong>Custom template permissions reference<\/strong><\/a> &#8211; This reference lists the permissions the APIs require, and which are used to create <strong>policies<\/strong> with which web pages can deploy an additional layer of governance for running custom templates.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/api\">**Custom template APIs for Server-side tagging<\/a> &#8211; This document lists the APIs available for Client and tag templates in <a href=\"https:\/\/www.simoahava.com\/analytics\/server-side-tagging-google-tag-manager\/\">Server-side tagging<\/a>.<\/p>\n<p>Keep those documents open when working with Custom Templates. I won\u2019t repeat their contents in this guide, but I do refer to them where necessary.<\/p>\n<h2 id=\"the-editor\">The editor<\/h2>\n<p>Let\u2019s jump right in! To start creating a new template, click the <strong>Templates<\/strong> menu option.<\/p>\n<div style=\"aspect-ratio: 1406 \/ 968;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/templates-menu.jpg\" title=\"Templates in the menu\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"968\" width=\"1406\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/templates-menu.jpg#ZgotmplZ\" alt=\"Templates in the menu\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, click <strong>New<\/strong> in the right corner of the <strong>Tag Templates<\/strong> card.<\/p>\n<div style=\"aspect-ratio: 1986 \/ 218;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-templates-new.jpg\" title=\"Tag templates new\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"218\" width=\"1986\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-templates-new.jpg#ZgotmplZ\" alt=\"Tag templates new\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>What you see now is the <strong>template<\/strong> editor. There are several views and menus here, so let\u2019s start with a quick overview.<\/p>\n<div style=\"aspect-ratio: 3838 \/ 1242;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/editor-overview.jpg\" title=\"Editor overview\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1242\" width=\"3838\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/editor-overview.jpg#ZgotmplZ\" alt=\"Editor overview\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>1<\/strong> &#8211; The main navigation of the editor. If you have <strong>Show advanced settings<\/strong> checked in the editor menu, you\u2019ll also see the <strong>Notes<\/strong> tab here.<\/p>\n<p><strong>2<\/strong> &#8211; The editor view for the selected tab. If you have <strong>Show advanced settings<\/strong> checked in the editor menu, you might see extra options here.<\/p>\n<p><strong>3<\/strong> &#8211; Template Preview shows what the template will look like when saved. If you\u2019ve made changes to the template, you\u2019ll see a <strong>Refresh<\/strong> link here, which will update the preview when clicked.<\/p>\n<p><strong>4<\/strong> &#8211; The Console will log information about template performance when you <strong>Test<\/strong> the template. Additionally, any calls to the <code>logging<\/code> API will be output here, too.<\/p>\n<p>If you select <strong>Show Test Page<\/strong> from the editor menu, you\u2019ll see the <strong>Test Page<\/strong> window between the Template Preview and Console.<\/p>\n<p><strong>5<\/strong> &#8211; Click Test to execute the template code with the settings you have entered in the preview. If you\u2019ve chosen <strong>Show Test Page<\/strong> from the editor menu, then any code that modifies the page will impact what the Test Page shows.<\/p>\n<p><strong>6<\/strong> &#8211; Save the template. The template cannot be saved if the code has syntax errors or invalid JavaScript. You need to fix the errors before saving. Note that the template can be saved even if you have incorrect permissions for the APIs you use.<\/p>\n<p><strong>7<\/strong> &#8211; The editor menu. The editor menu has options for managing the template and for customizing the editor.<\/p>\n<p>The editor for <strong>tag templates<\/strong> and <strong>variable templates<\/strong> is largely the same. The main difference is the absence of an icon\/logo selector in the <a href=\"#info-view\">info view<\/a> and how the code editor is utilized. With tags, the code editor needs <code>data.gtmOnSuccess()<\/code> for successful execution and <code>data.gtmOnFailure()<\/code> (if necessary) for a failure. Variables, on the other hand, don\u2019t use this. You just need a <code>return<\/code> statement that returns whatever the variable is supposed to return.<\/p>\n<h3 id=\"info-view\">Info view<\/h3>\n<p>The <strong>Info view<\/strong> is where you\u2019ll customize what the template looks like. Verbosity is not a sin &#8211; try to be as clear and descriptive in the template name and description as possible.<\/p>\n<div style=\"aspect-ratio: 2002 \/ 908;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/info-view.jpg\" title=\"Info view\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"908\" width=\"2002\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/info-view.jpg#ZgotmplZ\" alt=\"Info view\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The <strong>Name<\/strong> of the template is what appears in the tag\/variable selection menu as well as in the template itself when you create a new instance from it.<\/p>\n<p>The <strong>Description<\/strong> will appear in the tag\/variable selection menu below the template name.<\/p>\n<p>Tag templates allow you to choose an <strong>image<\/strong> for the template. This image will appear in the tag selection menu and the template itself.<\/p>\n<div style=\"aspect-ratio: 1382 \/ 500;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-template-menu.jpg\" title=\"Tag template menu\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"500\" width=\"1382\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-template-menu.jpg#ZgotmplZ\" alt=\"Tag template menu\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>At the bottom of the Info view is the checkbox for approving the terms of service for the <strong>Community Template Gallery<\/strong>. You only need to check this if you want to submit your template to the <a href=\"https:\/\/tagmanager.google.com\/gallery\/\">gallery<\/a>.<\/p>\n<div style=\"aspect-ratio: 1142 \/ 932;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/10\/terms-of-service-template.jpg\" title=\"TOS template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"932\" width=\"1142\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/10\/terms-of-service-template.jpg#ZgotmplZ\" alt=\"TOS template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>If you have <strong>Show advanced settings<\/strong> selected, you\u2019ll also see the template <strong>version<\/strong> as well as the <strong>contexts<\/strong> in which the template works.<\/p>\n<p>You\u2019ll also see a <strong>Source<\/strong> toggle in the top of the view. By clicking the toggle, you\u2019ll see the JSON representation of the template info, which you can edit (if you want to change the context, for example).<\/p>\n<div style=\"aspect-ratio: 1912 \/ 630;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/source-toggle-info.jpg\" title=\"Source toggle for info\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"630\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/source-toggle-info.jpg#ZgotmplZ\" alt=\"Source toggle for info\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h3 id=\"fields-editor\">Fields editor<\/h3>\n<p>The <strong>Fields editor<\/strong> is where you\u2019ll spend a lot of your time. You use this editor to establish what the tag or variable user interface will look like, and how individual fields interact with each other.<\/p>\n<p>For each field you create, you need to specify (at least) a name with which you can refer to the field value in the code editor. The field name must be <strong>unique<\/strong>, since all fields (even those nested within other fields) will be directly accessible using the field name as a property of the <code>data<\/code> object. For example, to access the value of a field whose name is <code>gaTrackingId<\/code>, you\u2019d use this in the code editor:<\/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> ua = data.gaTrackingId;\nlog(ua); <span style=\"color:#aaa;font-style:italic\">\/\/ logs UA-12345-1 or whatever the user set the value of the field to.\n<\/span><\/code><\/pre>\n<\/div>\n<p>Furthermore, each field has a <strong>field configuration<\/strong> that you\u2019ll use to establish how the field functions in the user interface of the template itself.<\/p>\n<div style=\"aspect-ratio: 1908 \/ 564;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/field-editor.jpg\" title=\"Field editor view\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"564\" width=\"1908\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/field-editor.jpg#ZgotmplZ\" alt=\"Field editor view\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Below the <strong>field name<\/strong> are the options and settings for the field. You\u2019ll see more of these as you add additional <strong>configurations<\/strong>.<\/p>\n<p>In the top right corner of each field row you\u2019ll see a <strong>trash can<\/strong> for deleting the field.<\/p>\n<p>There\u2019s also a <strong>cogwheel<\/strong> which opens the <strong>field configuration<\/strong> options.<\/p>\n<p>The <strong>more options<\/strong> menu opens options for manipulating the positioning of the field (see screenshot above), and the <strong>caret<\/strong> at the very right lets you collapse and expand the field in the editor.<\/p>\n<p>If you have <strong>Show advanced settings<\/strong> enabled, you can toggle the <strong>Source<\/strong> toggle in the top corner of the view to see a JSON representation of the fields.<\/p>\n<div style=\"aspect-ratio: 1922 \/ 592;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/source-toggle-fields.jpg\" title=\"Source toggle for fields\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"592\" width=\"1922\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/source-toggle-fields.jpg#ZgotmplZ\" alt=\"Source toggle for fields\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h4 id=\"field-configuration\">Field configuration<\/h4>\n<p>Whenever you add a field in the editor, you have the option of configuring field-specific rules and settings by clicking the <strong>cogwheel<\/strong> icon next to the field.<\/p>\n<div style=\"aspect-ratio: 1904 \/ 242;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/field-configuration-intro.jpg\" title=\"Field configuration\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"242\" width=\"1904\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/field-configuration-intro.jpg#ZgotmplZ\" alt=\"Field configuration\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Depending on the field you opened the configuration for, you\u2019ll see a set of toggles that you can toggle on or off. Some toggles are on by default, again depending on the field you are configuring.<\/p>\n<div style=\"aspect-ratio: 1960 \/ 890;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-configuration.jpg\" title=\"Text input configuration\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"890\" width=\"1960\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-configuration.jpg#ZgotmplZ\" alt=\"Text input configuration\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>As you read through the field descriptions below, I\u2019ve added the configuration options for each field. Furthermore, at the end of this guide there\u2019s a <a href=\"#field-configuration-reference\">field configuration reference<\/a> which lists all the possible configuration options in more detail.<\/p>\n<p>Note that some fields can be <strong>nested<\/strong>, and some fields actually include nested fields by default (e.g. the <a href=\"#param-table\">Param table<\/a> field). In these cases, the nested fields are treated as their own fields with their own configurations. The only difference between an isolated and nested field is that the latter is subservient to the field configurations of its parent. For example, if the parent is disabled due to enabling conditions not validating, the nested fields will be disabled, too.<\/p>\n<h4 id=\"text-input\">Text input<\/h4>\n<h5 id=\"description\">Description<\/h5>\n<p>The <strong>Text input<\/strong> field is a simple input box to which the user can write text.<\/p>\n<div style=\"aspect-ratio: 1906 \/ 306;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-1.jpg\" title=\"Text input field in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"306\" width=\"1906\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-1.jpg#ZgotmplZ\" alt=\"Text input field in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Text input field in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 608 \/ 18;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-2.jpg\" title=\"Text input field in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"18\" width=\"608\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/text-input-2.jpg#ZgotmplZ\" alt=\"Text input field in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Text input field in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output\">Code editor output<\/h5>\n<p>The property <code>data.fieldName<\/code> will resolve to whatever the user typed in the field, or whatever a GTM variable used in the field resolves to.<\/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:#aaa;font-style:italic\">\/\/ Using the example from the screenshot above\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> textFieldValue = data.textToWriteToConsole;\n<\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#allow-empty-strings\">Allow empty strings<\/a> &#8211; Convert and unfilled field into an empty string. OFF by default.<\/li>\n<li><a href=\"#always-in-summary\">Always in summary<\/a> &#8211; Show the field and its current value in the summary view of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-line-count\">Display line count<\/a> &#8211; Line count of greater than 1 turns the field into a text area. OFF by default.<\/li>\n<li><a href=\"#display-message-when-not-set\">Display message when not set<\/a> &#8211; When the field is untouched, show this text in the summary view. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#text-as-list\">Text as list<\/a> &#8211; When the text field is a text area (see <strong>Display line count<\/strong> above), store the value of the field as an array, where each item represents a row of input. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<li><a href=\"#value-hint\">Value hint<\/a> &#8211; Text shown as a placeholder help text in the field before the user starts editing it. OFF by default.<\/li>\n<li><a href=\"#value-unit\">Value unit<\/a> &#8211; Text shown next to the field. Useful to specify a format or type, for example. OFF by default.<\/li>\n<\/ul>\n<h5 id=\"description-1\">Description<\/h5>\n<p>The <strong>Drop-down menu<\/strong> field provides a menu where only <strong>a single item can be selected<\/strong>. It\u2019s often a combination of predefined items (such as <code>True<\/code> and <code>False<\/code>), and all the Google Tag Manager variables in the container.<\/p>\n<div style=\"aspect-ratio: 1812 \/ 748;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/dropdown-menu-1.jpg\" title=\"Drop-down menu in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"748\" width=\"1812\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/dropdown-menu-1.jpg#ZgotmplZ\" alt=\"Drop-down menu in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Drop-down menu in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 1170 \/ 496;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/drop-down-menu-2.jpg\" title=\"Drop-down menu in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"496\" width=\"1170\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/drop-down-menu-2.jpg#ZgotmplZ\" alt=\"Drop-down menu in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Drop-down menu in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-1\">Code editor output<\/h5>\n<p>The <code>data.fieldName<\/code> property will resolve to the value of the item selected from the drop-down menu. If the item was one of those you defined in the template editor, then what you wrote in the Value field is what the property resolves to. If the user selected a GTM variable, then the value returned by that variable is what the property resolves to.<\/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> dropDownFieldValue = data.dropDownMenu1;\nlog(dropDownFieldValue); <span style=\"color:#aaa;font-style:italic\">\/\/ logs true if an item whose Value is true is selected.\n<\/span><\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-1\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#not-set-option\">\u201cNot set\u201d option<\/a> &#8211; Show a placeholder value in the menu before the user has selected anything. If menu is left untouched, the field returns an empty string. OFF by default.<\/li>\n<li><a href=\"#always-in-summary\">Always in summary<\/a> &#8211; Show the field and its current value in the summary view of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#include-variables\">Include variables<\/a> &#8211;\u00a0Check this box if you want to include all GTM variables in the drop-down menu. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#nested-fields\">Nested fields<\/a> &#8211; Nested fields are useful if you want to show fields related to a specific value of the parent field only under certain conditions, for example. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<li><a href=\"#value-unit\">Value unit<\/a> &#8211; Text shown next to the field. Useful to specify a format or type, for example. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"checkbox\">Checkbox<\/h4>\n<h5 id=\"description-2\">Description<\/h5>\n<p>The <strong>Checkbox<\/strong> field should be self-explanatory. The checkbox doesn\u2019t have a display name by default. Instead, text you type in the <strong>Checkbox text<\/strong> field will be shown next to the box in the UI.<\/p>\n<div style=\"aspect-ratio: 1146 \/ 304;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/checkbox-1.jpg\" title=\"Checkbox in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"304\" width=\"1146\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/checkbox-1.jpg#ZgotmplZ\" alt=\"Checkbox in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Checkbox in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 734 \/ 208;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/checkbox-2.jpg\" title=\"Checkbox in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"208\" width=\"734\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/checkbox-2.jpg#ZgotmplZ\" alt=\"Checkbox in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Checkbox in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-2\">Code editor output<\/h5>\n<p>The <code>data.fieldName<\/code> property resolves to <code>true<\/code> if the checkbox was checked and <code>false<\/code> if not.<\/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> checkBoxValue = data.useDataLayer;\nlog(checkBoxValue); <span style=\"color:#aaa;font-style:italic\">\/\/ true\n<\/span><\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-2\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#always-in-summary\">Always in summary<\/a> &#8211; Show the field and its current value in the summary view of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. OFF by default.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#nested-fields\">Nested fields<\/a> &#8211; Nested fields are useful if you want to show fields related to a specific value of the parent field only under certain conditions, for example. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"radio-buttons\">Radio buttons<\/h4>\n<h5 id=\"description-3\">Description<\/h5>\n<p>You can add one or more radio buttons into a single radio button group. The radio button group is treated as a single field. Each radio button has a name (displayed next to the button) and a value (what is returned if the button is selected). The user can only select one button from the group. You can expand <strong>advanced settings<\/strong> to add a help text and to add nested fields under each radio button selection.<\/p>\n<div style=\"aspect-ratio: 1736 \/ 1158;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/radio-buttons-1.jpg\" title=\"Radio buttons in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1158\" width=\"1736\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/radio-buttons-1.jpg#ZgotmplZ\" alt=\"Radio buttons in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Radio buttons in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 784 \/ 390;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/radio-buttons-2.jpg\" title=\"Radio buttons in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"390\" width=\"784\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/radio-buttons-2.jpg#ZgotmplZ\" alt=\"Radio buttons in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Radio buttons in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-3\">Code editor output<\/h5>\n<p>The <code>data.fieldName<\/code> property, where <code>fieldName<\/code> is the name of the entire radio button group, will resolve to the value of the selected radio button.<\/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> selectedButton = data.gaEventType;\n<span style=\"color:#00a\">if<\/span> (selectedButton === <span style=\"color:#a50\">'pageView'<\/span>) {\n  <span style=\"color:#00a\">const<\/span> gaId = data.trackingId;\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Do something with gaId\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-3\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#nested-fields\">Nested fields<\/a> &#8211; Nested fields are useful if you want to show fields related to a specific value of the parent field only under certain conditions, for example. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"simple-table\">Simple table<\/h4>\n<h5 id=\"description-4\">Description<\/h5>\n<p>With a <strong>simple table<\/strong>, you can define columns (either <a href=\"#text-input\">text input<\/a> fields or <a href=\"#drop-down-menu\">drop-down menus<\/a>), and the users can add and remove rows to and from the table as they wish.<\/p>\n<p>You can specify that all values in a column must be unique (i.e. the user can\u2019t add multiple rows with the same value in such a column), and you can add things like default values and validation rules to each column, once you have selected to <strong>Show advanced settings<\/strong> for the column.<\/p>\n<div style=\"aspect-ratio: 1876 \/ 1368;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/simple-table-1.jpg\" title=\"Simple table in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1368\" width=\"1876\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/simple-table-1.jpg#ZgotmplZ\" alt=\"Simple table in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Simple table in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 1776 \/ 348;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/simple-table-2.jpg\" title=\"Simple table in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"348\" width=\"1776\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/simple-table-2.jpg#ZgotmplZ\" alt=\"Simple table in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Simple table in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-4\">Code editor output<\/h5>\n<p>The <code>data.fieldName<\/code> property will resolve to an array of objects, where each object represents a row the user has added in the UI. Furthermore, each row object will have key-value pairs for every column, where the key is the column name and the value is the value of the input (the selection value if a drop-down menu or the input text if a text field).<\/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\">log(data.cookieSettings); \n<span style=\"color:#aaa;font-style:italic\">\/* Logs:\n<\/span><span style=\"color:#aaa;font-style:italic\">[\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"cookieOption\":\"cookieDomain\",\"optionValue\":\"simoahava.com\"},\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"cookieOption\":\"cookieName\",\"optionValue\":\"myCookie\"}\n<\/span><span style=\"color:#aaa;font-style:italic\">]\n<\/span><span style=\"color:#aaa;font-style:italic\">*\/<\/span>\n<\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-4\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#new-row-button-text\">\u201cNew row\u201d button text<\/a> &#8211; Change the value of the \u201cAdd row\u201d button text. OFF by default.<\/li>\n<li><a href=\"#always-in-summary\">Always in summary<\/a> &#8211; Show the field and its current value in the summary view of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-message-when-not-set\">Display message when not set<\/a> &#8211; When the field is untouched, show this text in the summary view. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"param-table\">Param table<\/h4>\n<h5 id=\"description-5\">Description<\/h5>\n<p>A <strong>Param table<\/strong> is a more complicated table. Instead of being able to edit individual column values in the table itself, a param table requires you to input all the values of the row in a special overlay menu that pops up when you click to add a row. The individual columns can be any of the supported field types, and thus you can add far more complexity into the table than you could with a regular <a href=\"#simple-table\">simple table<\/a> field.<\/p>\n<div style=\"aspect-ratio: 1876 \/ 1634;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/param-table-1.jpg\" title=\"Param table in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1634\" width=\"1876\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/param-table-1.jpg#ZgotmplZ\" alt=\"Param table in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Param table in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 1010 \/ 1864;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/param-table-2.jpg\" title=\"Param table in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1864\" width=\"1010\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/param-table-2.jpg#ZgotmplZ\" alt=\"Param table in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Param table in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-5\">Code editor output<\/h5>\n<p>Similar to the <a href=\"#simple-table\">simple table<\/a>, the <code>data.fieldName<\/code> property resolves to an array of objects, where each object represents a row in the table. Each row object has key-value pairs for each column, and the value is whatever the column field returns. For example, the screenshot above would render as:<\/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\">log(data.userSelection);\n<span style=\"color:#aaa;font-style:italic\">\/* Logs:\n<\/span><span style=\"color:#aaa;font-style:italic\">[\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"genderSelect\": \"male\", \"nameInput\": \"Simo Ahava\"},\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"genderSelect\": \"female\", \"nameInput\": \"Simona Ahava\"}\n<\/span><span style=\"color:#aaa;font-style:italic\">]\n<\/span><span style=\"color:#aaa;font-style:italic\">*\/<\/span>\n<\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-5\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#edit-row-dialog-title\">\u201cEdit row\u201d dialog title<\/a> &#8211; You can change what the heading of the \u201cEdit row\u201d overlay is. OFF by default.<\/li>\n<li><a href=\"#new-row-button-text\">\u201cNew row\u201d button text<\/a> &#8211; Change the value of the \u201cAdd row\u201d button text. OFF by default.<\/li>\n<li><a href=\"#new-row-dialog-title\">\u201cNew row\u201d dialog title<\/a> &#8211; You can change what the heading text is in the overlay you see when adding a new row. OFF by default.<\/li>\n<li><a href=\"#always-in-summary\">Always in summary<\/a> &#8211; Show the field and its current value in the summary view of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#clear-on-copy\">Clear on copy<\/a> &#8211; Prevent filled field values from being copied when a copy is made of the tag or variable. OFF by default.<\/li>\n<li><a href=\"#default-value\">Default value<\/a> &#8211; The value of the field until the user decides to change it. OFF by default.<\/li>\n<li><a href=\"#display-message-when-not-set\">Display message when not set<\/a> &#8211; When the field is untouched, show this text in the summary view. OFF by default.<\/li>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<li><a href=\"#validation-rules\">Validation rules<\/a>&#8211; One or more rules against which the field must validate before the user can save the tag or variable. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"group\">Group<\/h4>\n<h5 id=\"description-6\">Description<\/h5>\n<p>A <strong>Group<\/strong> is simply a logical way to group different fields together. The main benefit is that it offers you a <strong>Group style<\/strong> selection.<\/p>\n<ul>\n<li>\n<p><strong>Simple section<\/strong> &#8211; This style simply shows the nested fields in the group without any collapsing.<\/p>\n<\/li>\n<li>\n<p><strong>Collapsible section \u2013 Open<\/strong> &#8211; This style shows the nested fields in a collapsible section which is open initially.<\/p>\n<\/li>\n<li>\n<p><strong>Collapsible section \u2013 Closed<\/strong> &#8211; This style shows the nested fields in a collapsible section which is collapsed initially.<\/p>\n<\/li>\n<li>\n<p><strong>Collapsible section \u2013 Open if not default<\/strong> &#8211; This style shows the nested fields in a collapsible section which is open if the nested field(s) don\u2019t have default values (i.e. the user has changed the value of the fields).<\/p>\n<\/li>\n<\/ul>\n<p>A Group is useful if you want to section a set of fields separately, because you can also control the entire groups visibility with the <strong>Enabling condition<\/strong> field configuration.<\/p>\n<div style=\"aspect-ratio: 1896 \/ 854;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/more-settings-1.jpg\" title=\"Collapsible group in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"854\" width=\"1896\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/more-settings-1.jpg#ZgotmplZ\" alt=\"Collapsible group in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Collapsible group in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 1778 \/ 568;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/more-settings-2.jpg\" title=\"Collapsible group in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"568\" width=\"1778\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/more-settings-2.jpg#ZgotmplZ\" alt=\"Collapsible group in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Collapsible group in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-6\">Code editor output<\/h5>\n<p>The <strong>Group<\/strong> doesn\u2019t bring anything extra to the code editor. The nested fields are accessed directly as properties of the <code>data<\/code> object &#8211; the group itself is not present in the object in any way.<\/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\">log(data);\n<span style=\"color:#aaa;font-style:italic\">\/* Logs:\n<\/span><span style=\"color:#aaa;font-style:italic\">[\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"cookieSettings\": [{\"cookieOption\": \"cookieDomain\", \"optionValue\": \"auto\"}]},\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\"trackerName\": \"_ga_tracker\"}\n<\/span><span style=\"color:#aaa;font-style:italic\">]\n<\/span><span style=\"color:#aaa;font-style:italic\">*\/<\/span>\n<\/code><\/pre>\n<\/div>\n<h5 id=\"available-field-configurations-6\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<li><a href=\"#group-style\">Group style<\/a> &#8211; How the group section is rendered in the GTM UI (simple vs. collapsed vs. open). <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#help-text\">Help text<\/a> &#8211; Add text to a question mark tooltip shown next to the field. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"label\">Label<\/h4>\n<h5 id=\"description-7\">Description<\/h5>\n<p>The <strong>Label<\/strong> field is extremely simple. It\u2019s just text that you show in the GTM UI when the instance is opened. The <strong>Display name<\/strong> configuration determines the text that is shown. Additionally, a Label field has only one other configuration: an <strong>Enabling condition<\/strong> which you can use to conditionally show the text.<\/p>\n<div style=\"aspect-ratio: 1844 \/ 528;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/label-1.jpg\" title=\"Label in the editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"528\" width=\"1844\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/label-1.jpg#ZgotmplZ\" alt=\"Label in the editor\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Label in the editor<\/span><\/p>\n<\/div>\n<div style=\"aspect-ratio: 308 \/ 116;\" class=\"figure \">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/label-2.jpg\" title=\"Label in the UI\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"116\" width=\"308\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/label-2.jpg#ZgotmplZ\" alt=\"Label in the UI\"\/><\/p>\n<p>    <\/a><\/p>\n<p>    <span class=\"caption\">Label in the UI<\/span><\/p>\n<\/div>\n<h5 id=\"code-editor-output-7\">Code editor output<\/h5>\n<p>There is no way to access the label in the code editor.<\/p>\n<h5 id=\"available-field-configurations-7\">Available field configurations<\/h5>\n<blockquote>\n<p>Click the configuration name to jump to details about the configuration in the reference at the end of this guide.<\/p>\n<\/blockquote>\n<ul>\n<li><a href=\"#display-name\">Display name<\/a> &#8211; The label of the field shown in the GTM UI. <strong>ON by default<\/strong>.<\/li>\n<li><a href=\"#enabling-conditions\">Enabling conditions<\/a> &#8211; Establish conditions (based on other field inputs) for showing this particular field. OFF by default.<\/li>\n<\/ul>\n<h4 id=\"utilizing-apis\">Utilizing APIs<\/h4>\n<p><strong>Template APIs<\/strong> are methods in the Google Tag Manager sandboxed JavaScript which let you invoke commonly used utilities of the browser. GTM restricts direct access to global methods to improve the stability and reliability of the code, and to optimize the way the code is delivered in the browser.<\/p>\n<p>When working with the code editor, remember to always have the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api\">API reference<\/a> document open in your browser.<\/p>\n<p>Because the official documentation is pretty thorough, I won\u2019t do an exhaustive overview of all the APIs. Instead, I\u2019ll point out <strong>quirks<\/strong> or <strong>things you should know<\/strong> about some of the APIs, listed below in their separate chapters.<\/p>\n<h5 id=\"the-require-api\">The <code>require<\/code> API<\/h5>\n<p>To invoke a template API, you must first <strong>require<\/strong> it in the editor. If you\u2019ve been working with <a href=\"https:\/\/nodejs.org\/en\/\">Node.js<\/a>, you\u2019ll recognize the <code>require()<\/code> method as a way to include JavaScript <strong>modules<\/strong> into your code.<\/p>\n<p>In GTM templates, <code>require()<\/code> is used to gain access to template APIs, so the functionality is similar even if quite a bit more restricted, as the list of APIs you can integrate is limited.<\/p>\n<p>To utilize an API, you simply run <code>const method = require(name);<\/code>, where <code>name<\/code> is the name of the API you want to use, and <code>method<\/code> is the name of the variable to which you will locally scope the API function.<\/p>\n<p>For example, to make it possible to log to the console and to set cookies in the template code, you would need to require the respective APIs:<\/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> log = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n<span style=\"color:#00a\">const<\/span> setCookie = require(<span style=\"color:#a50\">'setCookie'<\/span>);\n<\/code><\/pre>\n<\/div>\n<p>When you require an API that is governed by a set of <strong>permissions<\/strong>, those permissions will automatically appear in the <a href=\"#permissions\">Permissions<\/a> tab of the template UI. When you use the API, you need to make sure that the permissions allow you to perform the tasks you are trying to perform.<\/p>\n<h5 id=\"the-querypermission-api\">The <code>queryPermission<\/code> API<\/h5>\n<p>Especially if you\u2019ve written the template for public use, you might want to utilize the <code>queryPermission<\/code> API to wrap your code in a validator that only runs if the required permissions have been set.<\/p>\n<p>For example, if you want to make sure you can actually set some cookie, you might want to use this type of syntax:<\/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> queryPermission = require(<span style=\"color:#a50\">'queryPermission'<\/span>);\n<span style=\"color:#00a\">const<\/span> setCookie = require(<span style=\"color:#a50\">'setCookie'<\/span>);\n\n<span style=\"color:#00a\">const<\/span> options = {\n  domain: <span style=\"color:#a50\">'www.simoahava.com'<\/span>\n};\n\n<span style=\"color:#aaa;font-style:italic\">\/\/ Check whether it's possible to write the cookie before writing it\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">if<\/span> (queryPermission(<span style=\"color:#a50\">'set_cookies'<\/span>, <span style=\"color:#a50\">'_gaClientId'<\/span>, options)) {\n  setCookie(<span style=\"color:#a50\">'_gaClientId'<\/span>, <span style=\"color:#a50\">'abc123'<\/span>, options);\n}\n<\/code><\/pre>\n<\/div>\n<p>The <code>setCookie()<\/code> API code is only run if the permissions allow you to write a cookie named <code>_gaClientId<\/code> on the domain <code>www.simoahava.com<\/code>. This is a good way to avoid your tag running into errors.<\/p>\n<h5 id=\"the-copyfromdatalayer-api\">The <code>copyFromDataLayer<\/code> API<\/h5>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api\/#copyfromdatalayer\">This API<\/a> is relatively straightforward &#8211; it fetches the item from GTM\u2019s data model that you requested. For example, to fetch the current value for <code>gtm.elementUrl<\/code>, you\u2019d run:<\/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> copyFromDataLayer = require(<span style=\"color:#a50\">'copyFromDataLayer'<\/span>);\n<span style=\"color:#00a\">const<\/span> clickUrl = copyFromDataLayer(<span style=\"color:#a50\">'gtm.elementUrl'<\/span>);\n<\/code><\/pre>\n<\/div>\n<p>This code would fetch the value from the data model at the time that the tag was run.<\/p>\n<p>However, there\u2019s a very important <strong>catch<\/strong> here.<\/p>\n<p>If the template code fetching the <code>dataLayer<\/code> value is run <strong>asynchronously<\/strong> (e.g. with the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api\/#calllater\"><code>callLater<\/code> API<\/a>), or if the tag built from the template is part of a <a href=\"https:\/\/www.simoahava.com\/analytics\/understanding-tag-sequencing-in-google-tag-manager\/\"><strong>tag sequence<\/strong><\/a>, the value fetched from <code>dataLayer<\/code> will be <strong>whatever is currently stored in the data model<\/strong>. In all other scenarios, the code is run synchronously, relative to the <code>dataLayer.push()<\/code>, so the value returned by <code>copyFromDataLayer<\/code> will reflect what was included in the pushed object.<\/p>\n<p>To illustrate, consider the following code executed on the site:<\/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:#0aa\">window<\/span>.dataLayer.push({\n  event: <span style=\"color:#a50\">'fire'<\/span>,\n  key: <span style=\"color:#a50\">'value'<\/span>\n});\n\n<span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n  event: <span style=\"color:#a50\">'fire'<\/span>,\n  key: <span style=\"color:#a50\">'otherValue'<\/span>\n});\n<\/code><\/pre>\n<\/div>\n<p>These two  <code>dataLayer.push()<\/code> calls are run one after the other. If you\u2019ve built a tag that fires on the \u201cfire\u201d event, and the template for that tag uses <code>copyFromDataLayer<\/code> to fetch the value for <code>key<\/code>, then in most cases it will always return whatever the value of <code>key<\/code> was during the trigger push.<\/p>\n<p>In other words, the first time the tag fires, <code>key<\/code> will be set to <code>value<\/code>, and the second time the tag fires, <code>key<\/code> will return <code>otherValue<\/code>. This is understandable, and it\u2019s how Google Tag Manager has always worked.<\/p>\n<p>However, if the template uses <code>copyFromDataLayer<\/code> in an asynchronous method, or if the tag is part of a sequence, then when the first tag fires, it\u2019s possible that <code>key<\/code> will actually return <code>otherValue<\/code>, because by the time the tag resolves that code, the second push will have happened and the values stored in GTM\u2019s data model will have been updated.<\/p>\n<p>This is something to be mindful of. I hope that we get the chance to control this behavior by providing a flag that lets us choose whether to use this asynchronous behavior or to fall back to the original, synchronous process.<\/p>\n<h5 id=\"the-global-variable-apis\">The \u201cglobal variable\u201d APIs<\/h5>\n<p>Templates offer you a handful of APIs that all interact with the global namespace (namely, the <code>window<\/code> object). These APIs are:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#aliasinwindow\"><code>aliasInWindow<\/code><\/a> for creating a copy of a global variable in another global variable.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#callinwindow\"><code>callInWindow<\/code><\/a> for executing a global function.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#copyfromwindow\"><code>copyFromWindow<\/code><\/a> for creating a local copy (a <strong>proper copy<\/strong>, NOT a <strong>reference<\/strong> to the original) of the global variable.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#createargumentsqueue\"><code>createArgumentsQueue<\/code><\/a> for creating an array as well as a helper function that passes its arguments to the array.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#createqueue\"><code>createQueue<\/code><\/a> for creating an array as a global variable.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#setinwindow\"><code>setInWindow<\/code><\/a> for setting a global variable.<\/p>\n<\/li>\n<\/ul>\n<p>These APIs have a number of permissions associated with them, so you need to make sure you make <a href=\"#accesses-global-variables\">the necessary modifications<\/a> to the template permissions.<\/p>\n<p>Another thing to keep in mind is that when you access these global variables in the context of the templates, GTM creates a <strong>local copy<\/strong> of each and does NOT copy objects by reference, which is the typical way of handling JavaScript objects.<\/p>\n<p>See this example:<\/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> copy = require(<span style=\"color:#a50\">'copyFromWindow'<\/span>)\n<span style=\"color:#00a\">const<\/span> obj = copy(<span style=\"color:#a50\">'someObject'<\/span>);\n\nobj.someProperty = <span style=\"color:#00a\">true<\/span>;\n<\/code><\/pre>\n<\/div>\n<p>This sets <code>someProperty<\/code> on the object to <code>true<\/code> <strong>only in the template code<\/strong>. It doesn\u2019t change it to <code>true<\/code> in the global object itself. That\u2019s because GTM creates a clone of the global variable rather than a reference to it.<\/p>\n<p>Finally, GTM handles <strong>functions<\/strong> in a special way. When you try to run <code>setInWindow('someVariable', someFunction)<\/code>, where <code>someFunction<\/code> is a function you have created, what gets set in the global variable <code>someVariable<\/code> is <strong>not<\/strong> the actual function, but rather a wrapper created by GTM which ends up calling the function.<\/p>\n<p>This shouldn\u2019t be a big deal &#8211; since the end result is always the same. Whatever you call the global variable with gets executed in the function you created.<\/p>\n<p>However, it does mean that you won\u2019t be able to <strong>set individual properties to that function<\/strong>. Take this example:<\/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> func = str =&gt; str + <span style=\"color:#a50\">\" Simo\"<\/span>;\nfunc.loaded = <span style=\"color:#00a\">true<\/span>;\n\nsetInWindow(<span style=\"color:#a50\">'someFunction'<\/span>, func);\n<\/code><\/pre>\n<\/div>\n<p>If you now call <code>window.someFunction('Hello');<\/code>, the code ends up returning <code>\"Hello Simo\"<\/code>, so it works. However, if you check <code>someFunction.loaded<\/code>, you\u2019ll notice it\u2019s undefined when it should be <code>true<\/code>.<\/p>\n<h5 id=\"the-maketablemap-api\">The <code>makeTableMap<\/code> API<\/h5>\n<p>The <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#maketablemap\"><code>makeTableMap<\/code><\/a> API makes the <a href=\"#simple-table\">simple table<\/a> field more manageable.<\/p>\n<p>The simple table field itself returns an array of objects, where each object represents a <strong>row<\/strong> of the table and is comprised of key-value pairs. Each key-value pair corresponds to a column.<\/p>\n<p>For example, if the simple table had two columns:<\/p>\n<p><strong>Column 1:<\/strong> fieldToSetName<br \/><strong>Column 2:<\/strong> fieldToSetValue<\/p>\n<p>The resulting <code>data<\/code> object would look like this:<\/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-json\" data-lang=\"json\">[\n  {\n    <span style=\"color:#1e90ff;font-weight:bold\">\"fieldToSetName\"<\/span>: <span style=\"color:#a50\">\"page\"<\/span>,\n    <span style=\"color:#1e90ff;font-weight:bold\">\"fieldToSetValue\"<\/span>: <span style=\"color:#a50\">\"\/home\/\"<\/span>\n  },\n  {\n    <span style=\"color:#1e90ff;font-weight:bold\">\"fieldToSetName\"<\/span>: <span style=\"color:#a50\">\"userId\"<\/span>,\n    <span style=\"color:#1e90ff;font-weight:bold\">\"fieldToSetValue\"<\/span>: <span style=\"color:#a50\">\"abc123\"<\/span>\n  }\n]<\/code><\/pre>\n<\/div>\n<p>The <code>makeTableMap<\/code> API turns this into a single object whose contents are mapped from the values the user input. Naturally, this means that the column you use as the \u201ckey\u201d of this new map must have unique values.<\/p>\n<p>To continue the example from above, if you run <code>makeTableMap<\/code> against the array above, this is the result:<\/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> makeTableMap = require(<span style=\"color:#a50\">'makeTableMap'<\/span>);\n<span style=\"color:#00a\">const<\/span> log = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n\n<span style=\"color:#00a\">const<\/span> data = data.properties; <span style=\"color:#aaa;font-style:italic\">\/\/ This is the array from the example above\n<\/span><span style=\"color:#aaa;font-style:italic\"\/><span style=\"color:#00a\">const<\/span> newMap = makeTableMap(data, <span style=\"color:#a50\">'fieldToSetName'<\/span>, <span style=\"color:#a50\">'fieldToSetValue'<\/span>);\n\nlog(newMap);\n<span style=\"color:#aaa;font-style:italic\">\/* LOGS:\n<\/span><span style=\"color:#aaa;font-style:italic\">  {\n<\/span><span style=\"color:#aaa;font-style:italic\">    \"page\": \"\/home\",\n<\/span><span style=\"color:#aaa;font-style:italic\">    \"userId\": \"abc123\"\n<\/span><span style=\"color:#aaa;font-style:italic\">  }\n<\/span><span style=\"color:#aaa;font-style:italic\">*\/<\/span>\n<\/code><\/pre>\n<\/div>\n<h4 id=\"the-data-object\">The <code>data<\/code> object<\/h4>\n<p>If you want to access values the user has input into the template fields, you need to use the <code>data<\/code> object. Furthermore, to signal <strong>tag<\/strong> template completion (or failure), you will also need to use the <code>data<\/code> object in your template code.<\/p>\n<p>Every single user input in the template fields is encoded in the <code>data<\/code> object as properties, where the property name matches the <strong>field name<\/strong> you gave in the editor.<\/p>\n<div style=\"aspect-ratio: 962 \/ 190;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/field-name.jpg\" title=\"Field name\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"190\" width=\"962\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/field-name.jpg#ZgotmplZ\" alt=\"Field name\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>To access the values the user input into the <code>cookieSettings<\/code> field above, you would use this syntax:<\/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> input = data.cookieSettings;\n<\/code><\/pre>\n<\/div>\n<p>You don\u2019t need to <code>require()<\/code> any API to access the user input &#8211; the <code>data<\/code> object is always available for fetching the values the user has entered. Read through the <a href=\"#fields-editor\">Fields editor<\/a> chapter to see how each different field type is encoded into the <code>data<\/code>object.<\/p>\n<h4 id=\"variable-templates-in-the-code-editor\">Variable templates in the code editor<\/h4>\n<p>Variable templates have just one requirement, similar to Custom JavaScript variables in GTM: they must <strong>return<\/strong> a value. If you don\u2019t have a <code>return<\/code> statement in the template, the variable will always return <code>undefined<\/code> (not very useful).<\/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> userInput = data.someNumber;\n\n<span style=\"color:#00a\">return<\/span> userInput * <span style=\"color:#099\">2<\/span>;\n<\/code><\/pre>\n<\/div>\n<p>The variable template above would take the value entered by user into the <code>someNumber<\/code> field and return it multiplied by 2.<\/p>\n<h4 id=\"tag-templates-in-the-code-editor\">Tag templates in the code editor<\/h4>\n<p>With tag templates, you <strong>must<\/strong> invoke one of two methods in the code:<\/p>\n<p>I recommend to always have <code>data.gtmOnSuccess()<\/code> (after all, why create a tag that doesn\u2019t indicate successful completion). If there is a clear point of failure, such as something you want to block a <a href=\"https:\/\/www.simoahava.com\/analytics\/understanding-tag-sequencing-in-google-tag-manager\/\">tag sequence<\/a> with, you should also add a <code>data.gtmOnFailure()<\/code> call into the code.<\/p>\n<p>Try to avoid paths in the code that do not lead to either <code>data.gtmOnSuccess()<\/code> or <code>data.gtmOnFailure()<\/code>, as the tag will be in \u201cStill running\u201d status for perpetuity.<\/p>\n<p>Here\u2019s an example. Let\u2019s say the template\u2019s purpose is to write a cookie into the browser storage. If the template permissions allow the cookie to be written, <code>data.gtmOnSuccess()<\/code> is called after the write. If the permissions prevent this, a warning is logged into the console and <code>data.gtmOnFailure()<\/code> is run instead.<\/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> log = require(<span style=\"color:#a50\">'logToConsole'<\/span>);\n<span style=\"color:#00a\">const<\/span> setCookie = require(<span style=\"color:#a50\">'setCookie'<\/span>);\n<span style=\"color:#00a\">const<\/span> queryPermission = require(<span style=\"color:#a50\">'queryPermission'<\/span>);\n\n<span style=\"color:#00a\">if<\/span> (queryPermission(<span style=\"color:#a50\">'set_cookies'<\/span>, <span style=\"color:#a50\">'_gaClientId'<\/span>)) {\n  setCookie(<span style=\"color:#a50\">'_gaClientId'<\/span>, <span style=\"color:#a50\">'abc123'<\/span>);\n  data.gtmOnSuccess();\n} <span style=\"color:#00a\">else<\/span> {\n  log(<span style=\"color:#a50\">'Unable to write cookie due to missing permissions!'<\/span>);\n  data.gtmOnFailure();\n}\n<\/code><\/pre>\n<\/div>\n<p>Tag success\/failure\/incompletion status is shown in Preview mode, too.<\/p>\n<div style=\"aspect-ratio: 823 \/ 658;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/firing-status.jpg\" title=\"Firing status in debug mode\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"658\" width=\"823\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/firing-status.jpg#ZgotmplZ\" alt=\"Firing status in debug mode\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h4 id=\"client-templates-in-the-code-editor\">Client templates in the code editor<\/h4>\n<p>With <strong>Client<\/strong> templates, you need to invoke the <a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/api#claimrequest\"><code>claimRequest<\/code> API<\/a> when you want the Client to parse the HTTP request and not let other Clients use it any longer. For example, if you have a Client that is designed to handle requests coming to <code>\/my-pixel\/<\/code>, you\u2019d build a Client like this:<\/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> getRequestPath = require(<span style=\"color:#a50\">'getRequestPath'<\/span>);\n<span style=\"color:#00a\">const<\/span> claimRequest = require(<span style=\"color:#a50\">'claimRequest'<\/span>);\n\n<span style=\"color:#00a\">if<\/span> (getRequestPath() === <span style=\"color:#a50\">'\/my-pixel\/'<\/span>) {\n  claimRequest();\n}\n<\/code><\/pre>\n<\/div>\n<p>When the Client has done its work, it must return a response back to the source of the request. This is done with the <a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/api#returnresponse\"><code>returnResponse<\/code> API<\/a>.<\/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\">runContainer(event, () =&gt; {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ onComplete callback called, return the response.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  returnResponse();\n});\n<\/code><\/pre>\n<\/div>\n<p>I do recommend to read <a href=\"https:\/\/www.simoahava.com\/gtm-tips\/build-custom-universal-analytics-client-server-side-tagging\/\">this article<\/a> for an overview of how Client templates work.<\/p>\n<h3 id=\"permissions\">Permissions<\/h3>\n<p>When you add one of the <strong>supported APIs<\/strong> using the <code>require<\/code> method in the code editor, the associated permissions for that API are automatically displayed in the <strong>Permissions<\/strong> tab.<\/p>\n<div style=\"aspect-ratio: 1048 \/ 482;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/tag-template-permissions-tab.jpg\" title=\"Permissions tab\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"482\" width=\"1048\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/tag-template-permissions-tab.jpg#ZgotmplZ\" alt=\"Permissions tab\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Read <a href=\"https:\/\/developers.google.com\/tag-manager\/serverside\/permissions\">this document<\/a> for a comprehensive list of permissions used by <strong>Server-side tagging<\/strong> templates.<\/p>\n<p>Permissions are described at length <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/permissions\">in the official documentation<\/a>. Nevertheless, in this chapter I\u2019ll show what the UI for each permission looks like, and what the different settings are used for.<\/p>\n<p>Note that you can <strong>save<\/strong> a template with code that conflicts with a permission. It\u2019s not until the tag is run that an error is thrown, and this error is surfaced in the <a href=\"https:\/\/www.simoahava.com\/analytics\/new-errors-tab-preview-mode\/\">Errors tab<\/a> in Preview mode, signalling that there was a permissions conflict within the tag.<\/p>\n<h4 id=\"accesses-global-variables\">Accesses Global Variables<\/h4>\n<div style=\"aspect-ratio: 1900 \/ 508;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-access-global-variables.jpg\" title=\"Accesses global variables\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"508\" width=\"1900\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-access-global-variables.jpg#ZgotmplZ\" alt=\"Accesses global variables\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Accesses Global Variables permission allows the code to <strong>Read<\/strong> (see what value is assigned to the variable), <strong>Write<\/strong> (update the value assigned to the variable), and <strong>Execute<\/strong> (if the variable is a function, execute it) global variables. The <strong>Key<\/strong> is the name of the global variable, accessed via <code>window[key]<\/code>.<\/p>\n<p>Here are the APIs and the relevant permissions for them:<\/p>\n<table>\n<thead>\n<tr>\n<th>API example<\/th>\n<th>Permission<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>aliasInWindow('copyTo', 'copyFrom')<\/code><\/td>\n<td><strong>Write<\/strong> on <code>copyTo<\/code>, <strong>Read<\/strong> on <code>copyFrom<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>callInWindow('someFunction')<\/code><\/td>\n<td><strong>Execute<\/strong> on <code>someFunction<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>copyFromWindow('copyFrom')<\/code><\/td>\n<td><strong>Read<\/strong> on <code>copyFrom<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>createArgumentsQueue('helper', 'queue')<\/code><\/td>\n<td><strong>ReadWrite<\/strong> on <code>helper<\/code>, <strong>ReadWrite<\/strong> on <code>queue<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>createQueue('someArray')<\/code><\/td>\n<td><strong>ReadWrite<\/strong> on <code>someArray<\/code>.<\/td>\n<\/tr>\n<tr>\n<td><code>setInWindow('someVariable', 'someValue', true)<\/code><\/td>\n<td><strong>ReadWrite<\/strong> on <code>someVariable<\/code> (regardless of third parameter).<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In other words, if your code needs to access any global variable using e.g. <code>setInWindow<\/code> or <code>copyFromWindow<\/code>, you need to add those variables into these permission settings, and you need to specify if the code can read, write, and\/or execute the variable in question.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#access_globals\"><code>access_globals<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"accesses-local-storage\">Accesses Local Storage<\/h4>\n<div style=\"aspect-ratio: 1912 \/ 436;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-access-local-storage.jpg\" title=\"Accesses Local Storage\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"436\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-access-local-storage.jpg#ZgotmplZ\" alt=\"Accesses Local Storage\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Accesses Local Storage permission allows the code to <strong>Read<\/strong> (get items from <code>localStorage<\/code>) and <strong>Write<\/strong> (set items in <code>localStorage<\/code>) items in the browser\u2019s <code>localStorage<\/code>, by utilizing the <code>localStorage<\/code> template API.<\/p>\n<p>If your code needs to access <code>localStorage<\/code>,  you need to specify Read and\/or Write permissions for every key in <code>localStorage<\/code> the template needs to access.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#access_local_storage\"><code>access_local_storage<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"accesses-template-storage\">Accesses Template Storage<\/h4>\n<div style=\"aspect-ratio: 1910 \/ 188;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-accesses-template-storage.jpg\" title=\"Accesses Template Storage\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"188\" width=\"1910\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-accesses-template-storage.jpg#ZgotmplZ\" alt=\"Accesses Template Storage\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Accesses Template Storage permission allows the code to Read and Write to a temporary storage which exists for the current page load. It\u2019s useful if you need to persist information that persists across template executions.<\/p>\n<p>For example, if you want to make sure your template doesn\u2019t run some code more than once per page load, you could use <code>templateStorage<\/code> like this:<\/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> templateStorage = require(<span style=\"color:#a50\">'templateStorage'<\/span>);\n<span style=\"color:#00a\">const<\/span> ids = templateStorage.getItem(<span style=\"color:#a50\">'ids'<\/span>) || [];\n<span style=\"color:#00a\">if<\/span> (!ids.includes(data.id)) {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Run code\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  ...\n  ids.push(data.id);\n  templateStorage.setItem(<span style=\"color:#a50\">'ids'<\/span>, ids);\n}\n<\/code><\/pre>\n<\/div>\n<p>The permission has no configuration &#8211; read, write, and delete operations are always permitted.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#access_template_storage\"><code>access_template_storage<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-cookie-values\">Reads Cookie Value(s)<\/h4>\n<div style=\"aspect-ratio: 1912 \/ 344;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-cookie-values.jpg\" title=\"Reads cookie values\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"344\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-cookie-values.jpg#ZgotmplZ\" alt=\"Reads cookie values\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Reads Cookie Value(s) permission lists all the first-party cookies the tag or variable code can access with the <code>getCookieValues<\/code> API. To allow the code to read from a first-party cookie, you need to list all the cookie names that can be accessed on <strong>their own line<\/strong> in the text box in the permission settings.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#get_cookies\"><code>get_cookies<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-referrer-url\">Reads Referrer URL<\/h4>\n<div style=\"aspect-ratio: 1910 \/ 472;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/05\/permissions-gets-referrer.jpg\" title=\"Gets referrer\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"472\" width=\"1910\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/05\/permissions-gets-referrer.jpg#ZgotmplZ\" alt=\"Gets referrer\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Reads Referrer URL permission allows template code to access any or only parts of the referring page URL (from <code>document.referrer<\/code>. You can restrict access to any combination of its URL components. Since the permission model is the same as for the <a href=\"#reads-url\">Reads URL<\/a> permission, please read the very next section for more details.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#get_referrer\"><code>get_referrer<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-url\">Reads URL<\/h4>\n<div style=\"aspect-ratio: 1916 \/ 462;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-url.jpg\" title=\"Reads URL\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"462\" width=\"1916\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-url.jpg#ZgotmplZ\" alt=\"Reads URL\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The Reads URL permission allows template code to access any or only parts of the current page URL. You can restrict access to any combination of the following URL components:<\/p>\n<table>\n<thead>\n<tr>\n<th>Component<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>protocol<\/td>\n<td><code>http<\/code>, <code>https<\/code>, or <code>file<\/code><\/td>\n<\/tr>\n<tr>\n<td>host<\/td>\n<td><code>blog.simoahava.com<\/code><\/td>\n<\/tr>\n<tr>\n<td>port<\/td>\n<td><code>443<\/code><\/td>\n<\/tr>\n<tr>\n<td>path<\/td>\n<td><code>\/analytics\/articles\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>extension<\/td>\n<td><code>html<\/code><\/td>\n<\/tr>\n<tr>\n<td>fragment<\/td>\n<td><code>about-us<\/code><\/td>\n<\/tr>\n<tr>\n<td>query<\/td>\n<td><code>gclid=1.2.3.4<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>After selecting <strong>query<\/strong>, You can specify which <strong>query keys<\/strong> the <code>getUrl<\/code> API is allowed to access, or you can leave it to its default setting which is any query keys.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#get-url\"><code>get_url<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"injects-hidden-iframes\">Injects Hidden Iframes<\/h4>\n<div style=\"aspect-ratio: 1908 \/ 344;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-injects-hidden-iframes.jpg\" title=\"Injects Hidden Iframes\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"344\" width=\"1908\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-injects-hidden-iframes.jpg#ZgotmplZ\" alt=\"Injects Hidden Iframes\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can list a number of URL patterns, each on its own row, that must match those in the code editor used to inject hidden iframes on the page. The <code>src<\/code> attribute of the iframe the editor wants to inject must match one of these parameters.<\/p>\n<p>The URL patterns must include <code>https:\/\/<\/code>, a valid hostname, and a valid path. Hostnames can use asterisk to wildcard match any subdomains, and paths can use asterisk to wildcard match any characters. Path ending with a <code>\/<\/code> is also a wildcard match for anything that follows.<\/p>\n<p>For example, given these three patterns:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/*.simoahava.com\/tracker.html<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/*tracker.html<\/code><\/p>\n<\/li>\n<\/ul>\n<p>Any of these will be <strong>valid<\/strong> matches:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/simoahava.com\/tracker.html<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/blog.tracker.simoahava.com\/tracker.html<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/track\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/tracking\/this\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/tracker.html<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/track\/superdupertracker.html<\/code><\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#inject_hidden_iframe\"><code>inject_hidden_iframe<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"injects-scripts\">Injects Scripts<\/h4>\n<div style=\"aspect-ratio: 1910 \/ 362;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-injects-scripts.jpg\" title=\"Injects Scripts\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"362\" width=\"1910\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-injects-scripts.jpg#ZgotmplZ\" alt=\"Injects Scripts\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can list a number of URL patterns, each on its own row, that must match those in the code editor used to inject scripts on the page. The <code>src<\/code> attribute of the script the editor wants to inject must match one of these patterns.<\/p>\n<p>The URL patterns must include <code>https:\/\/<\/code>, a valid hostname, and a valid path. Hostnames can use asterisk to wildcard match any subdomains, and paths can use asterisk to wildcard match any characters. Path that only consists of a <code>\/<\/code> is also a wildcard match for anything that follows.<\/p>\n<p>For example, given these three patterns:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/*.simoahava.com\/tracker.js<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/*tracker.js<\/code><\/p>\n<\/li>\n<\/ul>\n<p>Any of these will be <strong>valid<\/strong> matches:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/simoahava.com\/tracker.js<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/blog.tracker.simoahava.com\/tracker.js<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/tracking\/gtmtracker.js<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/tracker.js<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/track\/superdupertracker.js<\/code><\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#inject_script\"><code>inject_script<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"logs-to-console\">Logs To Console<\/h4>\n<div style=\"aspect-ratio: 1912 \/ 370;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-logs-to-console.jpg\" title=\"Logs to Console\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"370\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-logs-to-console.jpg#ZgotmplZ\" alt=\"Logs to Console\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can choose whether the <code>logToConsole<\/code> API can log into the browser console only when in preview\/debug mode, or whether it can log to console whenever the tag fires, regardless of debug context.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#logging\"><code>logging<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-data-layer\">Reads Data Layer<\/h4>\n<div style=\"aspect-ratio: 1910 \/ 344;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-data-layer.jpg\" title=\"Reads Data Layer\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"344\" width=\"1910\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-data-layer.jpg#ZgotmplZ\" alt=\"Reads Data Layer\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In the permission configuration, add the Data Layer keys the code has access to, each on its own row.<\/p>\n<p>You can use wildcards to allow the code access to any subproperties of the key. For example, a permission like this:<\/p>\n<p>Will allow the code editor to read <code>ecommerce<\/code>, <code>ecommerce.purchase.actionField.id<\/code>, <code>ecommerce.purchase.products<\/code>, and any other key nested under <code>ecommerce<\/code>.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#read_data_layer\"><code>read_data_layer<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-document-character-set\">Reads Document Character Set<\/h4>\n<div style=\"aspect-ratio: 1912 \/ 194;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-document-character-set.jpg\" title=\"Reads Document Character Set\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"194\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-document-character-set.jpg#ZgotmplZ\" alt=\"Reads Document Character Set\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>An extremely simple permission for an extremely simple API. This permission governs whether or not the code editor can use the <code>readCharacterSet<\/code> API, which, in turn, returns the value of <code>document.characterSet<\/code>.<\/p>\n<p>There are no configuration options you can pass to the permission, so it\u2019s always permitted (unless a policy is used to block it).<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#read_character_set\"><code>read_character_set<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-container-data\">Reads Container Data<\/h4>\n<div style=\"aspect-ratio: 1912 \/ 186;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-reads-container-data.jpg\" title=\"Reads container data\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"186\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2020\/08\/permissions-reads-container-data.jpg#ZgotmplZ\" alt=\"Reads container data\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Very simple permission (nothing to configure), which is used when the template code needs to use the <code>getContainerVersion<\/code> API.<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#read_container_data\"><code>read_container_data<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-event-metadata\">Reads Event Metadata<\/h4>\n<div style=\"aspect-ratio: 956 \/ 96;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/07\/reads-event-metadata.jpg\" title=\"Reads Event Metadata\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"96\" width=\"956\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/07\/reads-event-metadata.jpg#ZgotmplZ\" alt=\"Reads Event Metadata\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>This permission allows the code to use the <code>addEventCallback<\/code> API, which updates the <code>eventCallback<\/code> of the <code>dataLayer.push()<\/code> that triggered the tag created from this template. A data object of tags that fired for the <code>dataLayer<\/code> event is passed as an argument to the callback.<\/p>\n<p>Take a look at <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-monitor\/\">this article<\/a> for more details on how this API works.<\/p>\n<p>This permission doesn\u2019t take any configuration options, so it\u2019s always permitted (unless a policy is used to block it).<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#read_event_metadata\"><code>read_event_metadata<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"reads-document-title\">Reads Document Title<\/h4>\n<div style=\"aspect-ratio: 1906 \/ 178;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-document-title.jpg\" title=\"Reads Document Title\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"178\" width=\"1906\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-reads-document-title.jpg#ZgotmplZ\" alt=\"Reads Document Title\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Another really simple permission for a really simple API. This permission allows the code to use the <code>readTitle<\/code> API, which returns the value of <code>document.title<\/code>.<\/p>\n<p>This permission doesn\u2019t take any configuration options, so it\u2019s always permitted (unless a policy is used to block it).<\/p>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#read_title\"><code>read_title<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"sends-pixels\">Sends Pixels<\/h4>\n<div style=\"aspect-ratio: 1908 \/ 362;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-sends-pixels.jpg\" title=\"Sends Pixels\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"362\" width=\"1908\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-sends-pixels.jpg#ZgotmplZ\" alt=\"Sends Pixels\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You can provide a list of URL patterns (each on its own row), and when using the the <code>sendPIxel<\/code> API, the URL the pixel is dispatched to must match one of these patterns.<\/p>\n<p>For example, given these three patterns:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/*.simoahava.com\/collect<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/*\/track<\/code><\/p>\n<\/li>\n<\/ul>\n<p>Any of these will be <strong>valid<\/strong> matches:<\/p>\n<ul>\n<li>\n<p><code>https:\/\/simoahava.com\/collect<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/blog.tracker.simoahava.com\/collect<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.gtmtools.com\/tracking\/collect<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/tracker\/track<\/code><\/p>\n<\/li>\n<li>\n<p><code>https:\/\/www.tracksimo.com\/collect\/analytics\/track<\/code><\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#send_pixel\"><code>send_pixel<\/code><\/a>.<\/p>\n<\/blockquote>\n<h4 id=\"sets-a-cookie-value\">Sets A Cookie Value<\/h4>\n<div style=\"aspect-ratio: 1914 \/ 476;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-sets-a-cookie-value.jpg\" title=\"Sets a Cookie Value\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"476\" width=\"1914\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/permissions-sets-a-cookie-value.jpg#ZgotmplZ\" alt=\"Sets a Cookie Value\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>This permission lets you configure which cookies the template code is allowed to set. You can also configure the following parameters per cookie:<\/p>\n<ul>\n<li>\n<p><strong>Domain<\/strong> &#8211; on which domain the cookie can be written on or <code>*<\/code> for any.<\/p>\n<\/li>\n<li>\n<p><strong>Path<\/strong> &#8211; on which path the cookie can be written on or <code>*<\/code> for any.<\/p>\n<\/li>\n<li>\n<p><strong>Secure<\/strong> &#8211; whether the cookie must be set with the <code>secure<\/code> flag, without the <code>secure<\/code> flag, or either.<\/p>\n<\/li>\n<li>\n<p><strong>Session<\/strong> &#8211; whether the cookie must be a session cookie, a cookie with an expiration, or either.<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>Name used with the <a href=\"#the-querypermission-api\"><code>queryPermission<\/code><\/a> API and <a href=\"#policies-reference\">policies<\/a>: <a href=\"#set_cookies\"><code>set_cookies<\/code><\/a>.<\/p>\n<\/blockquote>\n<h3 id=\"tests-1\">Tests<\/h3>\n<p>For more information on writing and running <strong>tests<\/strong> against your template code, see <a href=\"#tests\">this chapter<\/a>, and read <a href=\"https:\/\/www.simoahava.com\/analytics\/writing-tests-for-custom-templates-google-tag-manager\/\">this article<\/a>.<\/p>\n<h3 id=\"template-preview\">Template preview<\/h3>\n<p>The <strong>Template Preview<\/strong> window is where you can see what your template user interface looks like in its current state, and you can also try filling in the inputs before <a href=\"#testing-the-template\">testing<\/a> the template.<\/p>\n<div style=\"aspect-ratio: 1884 \/ 714;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-preview-editor.jpg\" title=\"Template preview editor\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"714\" width=\"1884\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-preview-editor.jpg#ZgotmplZ\" alt=\"Template preview editor\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>When you make changes to the template, whether in the <strong>Info<\/strong>, <strong>Fields<\/strong>, <strong>Code<\/strong>, or <strong>Permission<\/strong> tabs, the <strong>Refresh<\/strong> icon appears. By clicking this icon, the template preview is updated to reflect the changes you have made to the template in the editor.<\/p>\n<p>Other than that, the template preview should perform exactly as the real thing. In the <strong>summary view<\/strong>, i.e. before you click it for editing, the template will show you only those fields that are included in summary. You can manually toggle this with the <a href=\"#always-in-summary\">Always in summary<\/a> field configuration.<\/p>\n<p>The template preview is the perfect place to try out your template user interface before testing how the template actually runs, and finally saving it into the template library of your container.<\/p>\n<h3 id=\"importing-and-exporting\">Importing and exporting<\/h3>\n<p><strong>Importing and exporting<\/strong> templates will almost certainly be one of the most useful things you can do with templates. By exporting your custom templates, you can create a store or library of Google Tag Manager templates for others to use. By importing templates, you can add custom templates created by others into your own template library.<\/p>\n<p><strong>To export a template<\/strong>, click open the editor menu and choose <strong>Export<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1178 \/ 490;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/export-import-template.jpg\" title=\"Export and import template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"490\" width=\"1178\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/export-import-template.jpg#ZgotmplZ\" alt=\"Export and import template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Your browser should automatically download a file named <code><your template=\"\" name=\"\">.tpl<\/your><\/code>. The <strong>TPL<\/strong> suffix is a custom file format for Google Tag Manager templates. If you open the file in a text editor, you can see that it\u2019s a combination of JSON objects and plain text.<\/p>\n<div style=\"aspect-ratio: 1710 \/ 872;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-export-file.jpg\" title=\"Template export file\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"872\" width=\"1710\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/template-export-file.jpg#ZgotmplZ\" alt=\"Template export file\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>To import a template<\/strong>, click open the editor menu and choose <strong>Import<\/strong>. When importing a template, it\u2019s a good idea to first <strong>create a new template<\/strong> which will host the imported item. Unless of course you are deliberately updating an existing template with a newer version of the import.<\/p>\n<p>Once you\u2019ve chosen the file, a pop-up will warn you that importing the file will overwrite the template currently being edited.<\/p>\n<p>Why is this significant? Well, an <strong>import completely overwrites the template to which it is imported<\/strong>. So if you expect some sort of \u201cmerging\u201d being an option, well, at the time of writing there\u2019s no such feature.<\/p>\n<h3 id=\"advanced-settings\">Advanced settings<\/h3>\n<p>When you select <strong>Show Advanced Settings<\/strong> from the editor menu, a number of changes takes place in the UI.<\/p>\n<div style=\"aspect-ratio: 1326 \/ 374;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-advanced-settings-editor.jpg\" title=\"Show advanced settings\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"374\" width=\"1326\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-advanced-settings-editor.jpg#ZgotmplZ\" alt=\"Show advanced settings\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<ol>\n<li>A <strong>Notes<\/strong> option becomes visible in the editor navigation. You can write anything you want into this text area, such as developer documentation, instructions for use, etc. The <strong>Notes<\/strong> field contents are included with the template export\/import.<\/li>\n<\/ol>\n<div style=\"aspect-ratio: 1308 \/ 376;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/editor-notes.jpg\" title=\"Editor Notes\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"376\" width=\"1308\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/editor-notes.jpg#ZgotmplZ\" alt=\"Editor Notes\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<ol start=\"2\">\n<li>The <strong>Info<\/strong> tab will now show the <strong>Version<\/strong> (of the templating system itself) and the <strong>Container Context<\/strong> (whether the template is for web containers or for app containers). You can\u2019t change either of these values &#8211; they are set when you start creating the template. The <strong>Info<\/strong> tab will also show the <strong>Brand Name<\/strong> field.<\/li>\n<\/ol>\n<div style=\"aspect-ratio: 836 \/ 306;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/version-context-info.jpg\" title=\"Version and context info\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"306\" width=\"836\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/version-context-info.jpg#ZgotmplZ\" alt=\"Version and context info\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<ol start=\"3\">\n<li>In the <strong>Info<\/strong> and <strong>Fields<\/strong> tabs, you can directly edit the JSON source. Note that even though this lets you edit anything you want in the source, trying to change things that can\u2019t be changed (such as <strong>Version<\/strong> and <strong>Container Context<\/strong> from above) will result in the template issuing a warning when you try to refresh it in the preview or save it.<\/li>\n<\/ol>\n<div style=\"aspect-ratio: 1934 \/ 692;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/source-toggle.jpg\" title=\"Source toggler\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"692\" width=\"1934\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/source-toggle.jpg#ZgotmplZ\" alt=\"Source toggler\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h3 id=\"running-the-template-code\">Running the template code<\/h3>\n<p>Whenever you want to test how the template actually <strong>runs<\/strong>, you can click the <strong>Run code<\/strong> button in the Template Preview window. This executes the tag\/variable template code itself, outputting any debug messages into the console.<\/p>\n<div style=\"aspect-ratio: 1912 \/ 438;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-example.jpg\" title=\"Test example\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"438\" width=\"1912\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-example.jpg#ZgotmplZ\" alt=\"Test example\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>For <strong>tag templates<\/strong>, the console will tell you when the preview was last refreshed. It will also output any test logs, such as test start and completion (with elapsed time), as well as any errors.<\/p>\n<p>If you don\u2019t change anything in the <a href=\"#code-editor\">code editor<\/a>, the default code snippet will output the contents of the <code>data<\/code> object into the console.<\/p>\n<p>Generally, the console will display any strings you write into the console using the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/api#logtoconsole\"><code>logToConsole<\/code><\/a> API.<\/p>\n<div style=\"aspect-ratio: 1754 \/ 580;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-in-console.jpg\" title=\"Error in console\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"580\" width=\"1754\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/error-in-console.jpg#ZgotmplZ\" alt=\"Error in console\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Furthermore, when you choose to <strong>Show test page<\/strong> in the editor menu, a content area will pop up which you can <strong>inspect<\/strong> to find any changes the tag code has made to the page on which the tag runs. This is useful if you want to check if and how your hidden iframe was added to the page, for example.<\/p>\n<div style=\"aspect-ratio: 2058 \/ 820;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-test-page.jpg\" title=\"Show test page\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"820\" width=\"2058\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/show-test-page.jpg#ZgotmplZ\" alt=\"Show test page\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>To find your modifications to the test page, right-click it in your browser and choose <strong>Inspect<\/strong> (this may vary by browser). Start drilling down the DOM until you find an iframe with GTM\u2019s sandbox HTML file. The <code\/> of that iframe should contain any modifications your tag did to the page.<\/p>\n<div style=\"aspect-ratio: 2314 \/ 582;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-page-inspect.jpg\" title=\"Inspect test page\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"582\" width=\"2314\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-page-inspect.jpg#ZgotmplZ\" alt=\"Inspect test page\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Variable templates<\/strong> differ in that they don\u2019t modify the underlying page (or, they SHOULDN\u2019T modify the underlying page). Instead, when you <strong>test<\/strong> the template, the console outputs what the variable will return.<\/p>\n<div style=\"aspect-ratio: 1916 \/ 1448;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-template-variable.jpg\" title=\"Test variable template\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1448\" width=\"1916\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/test-template-variable.jpg#ZgotmplZ\" alt=\"Test variable template\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h2 id=\"templates-in-gtms-preview-mode\">Templates in GTM\u2019s Preview mode<\/h2>\n<p>In <strong>Preview<\/strong> mode, tag and variable templates work just like their built-in template counterparts.<\/p>\n<p>For <strong>tags<\/strong>, you\u2019ll see the tag <strong>name<\/strong> and <strong>properties<\/strong>.<\/p>\n<p>Two default properties are always included:<\/p>\n<ol>\n<li>\n<p><strong>Type<\/strong> &#8211; which is the template name, basically.<\/p>\n<\/li>\n<li>\n<p><strong>Firing Status<\/strong> &#8211; which will show \u201cSucceeded\u201d if <code>data.gtmOnSuccess()<\/code> was reached in the tag code, \u201cFailure\u201d if <code>data.gtmOnFailure()<\/code> was reached in the tag code, and <code>Still running<\/code> if neither was reached or if the tag is, actually, still running (due to e.g. the endpoint timing out).<\/p>\n<\/li>\n<\/ol>\n<p>The rest of the properties mirror the fields and <a href=\"#field-configuration-reference\">field configurations<\/a> you have generated. In the example below, a <a href=\"#text-input\">text input<\/a> field named <strong>Iframe URL<\/strong> has been populated with the value <code>https:\/\/www.gtmtools.com\/<\/code>, and a <a href=\"#param-table\">param table<\/a> field named <strong>Iframe parameters<\/strong> has been populated with the values you see.<\/p>\n<div style=\"aspect-ratio: 1492 \/ 588;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/tag-template-parameters.jpg\" title=\"Tag template parameters\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"588\" width=\"1492\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/tag-template-parameters.jpg#ZgotmplZ\" alt=\"Tag template parameters\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>For <strong>variables<\/strong>, the output can be found in the <strong>Variables<\/strong> tab of Preview mode, and you can see the return value of each custom variable in exactly the same way you can see the return values for all predefined variable templates.<\/p>\n<p>The variable template <strong>type<\/strong> will be the name of the custom template (\u201cMultiply\u201d in the example below).<\/p>\n<div style=\"aspect-ratio: 1966 \/ 296;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/04\/variable-template-example.jpg\" title=\"Variable template example\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"296\" width=\"1966\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/04\/variable-template-example.jpg#ZgotmplZ\" alt=\"Variable template example\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The <strong>Errors<\/strong> tab will surface any errors thrown by <a href=\"#policies-reference\">policies<\/a> or if the template failed a <a href=\"#permissions\">permission<\/a> check.<\/p>\n<div style=\"aspect-ratio: 1066 \/ 227;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-errors.jpg\" title=\"Tag errors\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"227\" width=\"1066\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/01\/tag-errors.jpg#ZgotmplZ\" alt=\"Tag errors\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h2 id=\"field-configuration-reference\">Field configuration reference<\/h2>\n<p>This chapter lists all the <strong>Field configuration<\/strong> options you can configure for individual fields. Remember to check out the <a href=\"#fields-editor\">Fields editor<\/a> chapter for a detailed description of the fields and the configurations available to them.<\/p>\n<div style=\"aspect-ratio: 3178 \/ 550;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/field-configuration.jpg\" title=\"Field configuration\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"550\" width=\"3178\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/field-configuration.jpg#ZgotmplZ\" alt=\"Field configuration\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<h3 id=\"edit-row-dialog-title\">\u201cEdit row\u201d dialog title<\/h3>\n<div style=\"aspect-ratio: 3004 \/ 662;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-edit-row.jpg\" title=\"Edit row dialog title\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"662\" width=\"3004\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-edit-row.jpg#ZgotmplZ\" alt=\"Edit row dialog title\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>\u201cEdit row\u201d dialog title<\/strong> is available in fields where the user adds rows to a table and can edit those rows in an overlay. Defaults to \u201cEdit row\u201d.<\/p>\n<p><strong>How it works<\/strong>: The text you write into the configuration field will appear as the title of the overlay which pops out when the user <strong>edits<\/strong> a row they have already added to the table.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"new-row-button-text\">\u201cNew row\u201d button text<\/h3>\n<div style=\"aspect-ratio: 1964 \/ 732;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-new-row.jpg\" title=\"New row button text\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"732\" width=\"1964\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-new-row.jpg#ZgotmplZ\" alt=\"New row button text\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>\u201cNew row\u201d button text<\/strong> determines the button text with which the user can add a new row to a table field.<\/p>\n<p><strong>How it works<\/strong>: The text you type into the configuration field will be the text of the button below the table, which the user can use to add new rows to the table. Defaults to \u201cAdd row\u201d.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#param-table\">Param table<\/a>, <a href=\"#simple-table\">Simple table<\/a>.<\/p>\n<h3 id=\"new-row-dialog-title\">\u201cNew row\u201d dialog title<\/h3>\n<div style=\"aspect-ratio: 1978 \/ 566;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-new-row-dialog.jpg\" title=\"New row dialog title\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"566\" width=\"1978\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-new-row-dialog.jpg#ZgotmplZ\" alt=\"New row dialog title\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>\u201cNew row\u201d dialog title<\/strong> determines the text you see as the heading of the overlay that pops out when you choose to add a new row into a table. Defaults to \u201cNew row\u201d.<\/p>\n<p><strong>How it works<\/strong>: Type the new title into the configuration field, and it will show as the heading of the overlay the user sees when adding a new row to a table that uses overlays for data input.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"not-set-option\">\u201cNot set\u201d option<\/h3>\n<div style=\"aspect-ratio: 1224 \/ 308;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-not-set-option.jpg\" title=\"not set option\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"308\" width=\"1224\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-not-set-option.jpg#ZgotmplZ\" alt=\"not set option\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Before the user chooses an item in the drop-down list, you can use the <strong>\u201cNot set\u201d option<\/strong> to show a placeholder value.<\/p>\n<p><strong>How it works<\/strong>: The <strong>\u201cNot set\u201d option<\/strong> is a selectable option in the drop-down list, which also shows up if the user hasn\u2019t made any selection yet. If the user leaves the \u201cNot set\u201d option as the selected item, the value of the field in the code editor will be a <strong>blank string<\/strong>.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#drop-down-menu\">Drop-down menu<\/a>.<\/p>\n<h3 id=\"allow-empty-strings\">Allow empty strings<\/h3>\n<p><strong>Description<\/strong>: The <strong>Allow empty strings<\/strong> checkbox lets you determine whether or not an empty text input field shows up as an empty string when accessing the field value in the <code>data<\/code> object.<\/p>\n<p><strong>How it works<\/strong>: If the checkbox is checked, the text input field value in the code editor will be an empty string. If unchecked or if the configuration hasn\u2019t been added to the field, the value will be <code>undefined<\/code> for empty text fields.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a><\/p>\n<h3 id=\"always-in-summary\">Always in summary<\/h3>\n<div style=\"aspect-ratio: 1854 \/ 962;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-always-in-summary.jpg\" title=\"Always in summary\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"962\" width=\"1854\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-always-in-summary.jpg#ZgotmplZ\" alt=\"Always in summary\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>Always in summary<\/strong> configuration determines whether the field name and current value will show up in the summary view of the item.<\/p>\n<p><strong>How it works<\/strong>: When the checkbox is toggled, the user will see the name (if <a href=\"#display-name\">Display name<\/a> is configured) and current value of the field in the summary view if the item. The summary is view what you see when the tag or variable is not in edit mode.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"clear-on-copy\">Clear on copy<\/h3>\n<p><strong>Description<\/strong>: With <strong>Clear on copy<\/strong>, you can toggle whether or not the field will retain or clear its value if a copy is made of the tag or variable.<\/p>\n<p><strong>How it works<\/strong>: If <strong>Clear on copy<\/strong> is checked, then when the user makes a copy of an item created with this template, the field will have its value cleared (returned to its initial state) in the copy. If <strong>Clear on copy<\/strong> is unchecked or missing, the value of the field from the original item will be preserved in the copy.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"default-value\">Default value<\/h3>\n<div style=\"aspect-ratio: 1356 \/ 438;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-default-value.jpg\" title=\"Default value\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"438\" width=\"1356\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-default-value.jpg#ZgotmplZ\" alt=\"Default value\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>Default value<\/strong> option determines what the value of the field is before the user inputs anything into the field.<\/p>\n<p><strong>How it works<\/strong>: <strong>Default value<\/strong> represents the <em>initial<\/em> value of the field. It is considered a true value, meaning if the user doesn\u2019t delete or change it, the default value will be what the field returns in the code editor.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"display-line-count\">Display line count<\/h3>\n<div style=\"aspect-ratio: 1750 \/ 764;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-line-count.jpg\" title=\"Line count\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"764\" width=\"1750\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-line-count.jpg#ZgotmplZ\" alt=\"Line count\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Set the height of the text input area, and whether or not a multi-line value can be given.<\/p>\n<p><strong>How it works<\/strong>: If <strong>Display line count<\/strong> is set to <code>1<\/code>, then only one row of data can be input into the field. Anything larger than <code>1<\/code>, and the height of the text area grows as a result, and the user can type on multiple rows in the text input field.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>.<\/p>\n<h3 id=\"display-message-when-not-set\">Display message when not set<\/h3>\n<div style=\"aspect-ratio: 1844 \/ 958;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-display-message-not-set.jpg\" title=\"Display message when not set\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"958\" width=\"1844\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-display-message-not-set.jpg#ZgotmplZ\" alt=\"Display message when not set\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>Display message when not set<\/strong> allows you to show a \u201cdefault value\u201d for the field when in the summary view and the field doesn\u2019t have a value.<\/p>\n<p><strong>How it works<\/strong>: The text will show up only in the summary view when the field is not set, i.e. has no determinable value. It will not impact what the code editor returns as the field value.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"display-name\">Display name<\/h3>\n<div style=\"aspect-ratio: 1804 \/ 484;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-display-name.jpg\" title=\"Display name\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"484\" width=\"1804\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-display-name.jpg#ZgotmplZ\" alt=\"Display name\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The <strong>Display name<\/strong> configuration lets you set a label for the field.<\/p>\n<p><strong>How it works<\/strong>: The text you input in the <strong>Display name<\/strong> is shown as a label for the field when both in edit mode and the summary view.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>, <a href=\"#group\">Group<\/a>, <a href=\"#label\">Label<\/a>.<\/p>\n<h3 id=\"enabling-conditions\">Enabling conditions<\/h3>\n<div style=\"aspect-ratio: 2674 \/ 544;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-enabling-conditions.jpg\" title=\"Enabling conditions\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"544\" width=\"2674\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-enabling-conditions.jpg#ZgotmplZ\" alt=\"Enabling conditions\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: You can establish a dependency with <strong>Enabling conditions<\/strong>. The field will only be visible in the UI if the enabling condition validates.<\/p>\n<p><strong>How it works<\/strong>: An <em>Enabling condition<\/em> is essentially a check against <strong>some other field\u2019s value<\/strong>. You can use it to check whether some checkbox is unchecked, for example (as in the screenshot above).<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>, <a href=\"#group\">Group<\/a>, <a href=\"#label\">Label<\/a>.<\/p>\n<h3 id=\"group-style\">Group style<\/h3>\n<div style=\"aspect-ratio: 2592 \/ 696;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-group-style.jpg\" title=\"Group style\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"696\" width=\"2592\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-group-style.jpg#ZgotmplZ\" alt=\"Group style\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Use the <strong>Group style<\/strong> configuration to determine how the <a href=\"#group\">Group<\/a> field works.<\/p>\n<p><strong>How it works<\/strong>: The options you can choose are:<\/p>\n<ol>\n<li>\n<p>Simple section: the fields are simply grouped without UI impact. This is useful if you simply want to have the field configurations for the group impact the nested fields within.<\/p>\n<\/li>\n<li>\n<p>Collapsible section \u2013 Open: The fields are in a section that can be collapsed, and the section defaults to being open.<\/p>\n<\/li>\n<li>\n<p>Collapsible section \u2013 Closed: The fields are in a section that can be collapsed, and the section defaults to being closed.<\/p>\n<\/li>\n<li>\n<p>Collapsible section \u2013 Open if not default: The fields are in a section that can be collapsed, and if the fields have not been edited, the section is closed.<\/p>\n<\/li>\n<\/ol>\n<p><strong>Used in<\/strong>: <a href=\"#group\">Group<\/a>.<\/p>\n<h3 id=\"help-text\">Help text<\/h3>\n<div style=\"aspect-ratio: 3112 \/ 434;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-help-text.jpg\" title=\"Help text\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"434\" width=\"3112\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-help-text.jpg#ZgotmplZ\" alt=\"Help text\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Use <strong>Help text<\/strong> to show a little tooltip when hovering over the question mark icon next to the field in the UI.<\/p>\n<p><strong>How it works<\/strong>: The text you type into the <strong>Help text<\/strong> configuration field will appear in the UI when the user hovers the mouse cursor over the little question mark icon.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>, <a href=\"#group\">Group<\/a>.<\/p>\n<h3 id=\"include-variables\">Include variables<\/h3>\n<div style=\"aspect-ratio: 1956 \/ 458;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-include-variables.jpg\" title=\"Include variables\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"458\" width=\"1956\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-include-variables.jpg#ZgotmplZ\" alt=\"Include variables\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: When checked, <strong>Include variables<\/strong> will make the full list of GTM variables available for selection as the field value.<\/p>\n<p><strong>How it works<\/strong>: The drop-down menu will include all the GTM variables as selectable options if this field configuration is checked.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#drop-down-menu\">Drop-down menu<\/a>.<\/p>\n<h3 id=\"nested-fields\">Nested fields<\/h3>\n<div style=\"aspect-ratio: 2192 \/ 680;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-nested-fields.jpg\" title=\"Nested fields\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"680\" width=\"2192\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-nested-fields.jpg#ZgotmplZ\" alt=\"Nested fields\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: When you add <strong>Nested fields<\/strong> to a field, those fields become dependent on the enabling condition set for the parent field. Also, visually they will be placed closer to the parent field compared to if they were regular, non-nested fields.<\/p>\n<p><strong>How it works<\/strong>: Toggle <strong>Nested fields<\/strong> on, and you can add any available field type as a nested field of the current field. After that, if the parent field is disabled due to an invalid <a href=\"#enabling-conditions\">Enabling condition<\/a>, for example, the nested fields will be disabled, too.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>.<\/p>\n<h3 id=\"text-as-list\">Text as list<\/h3>\n<div style=\"aspect-ratio: 2468 \/ 550;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-text-as-list.jpg\" title=\"Text as list\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"550\" width=\"2468\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-text-as-list.jpg#ZgotmplZ\" alt=\"Text as list\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Use this with <a href=\"#line-count\">Line count<\/a> to access the field value as an array of strings (where each row corresponds to an item in the array).<\/p>\n<p><strong>How it works<\/strong>: When <strong>Text as list<\/strong> is checked, then each row in a <a href=\"#text-input\">Text input<\/a> field (when Line count is also configured) will be an item in the array of the resulting <code>data<\/code> object. Without <strong>Text as list<\/strong>, a multi-line input will result in a single string, where each row is separated with the newline character (<code>\\n<\/code>).<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>.<\/p>\n<h3 id=\"validation-rules\">Validation rules<\/h3>\n<div style=\"aspect-ratio: 2962 \/ 790;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-validation-rules.jpg\" title=\"Validation rules\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"790\" width=\"2962\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/reference-validation-rules.jpg#ZgotmplZ\" alt=\"Validation rules\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Use the <strong>Validation rules<\/strong> configuration to establish validation criteria for the field.<\/p>\n<p><strong>How it works<\/strong>: When you add a <strong>Validation rule<\/strong> to the field, the field must pass the validation, or the user won\u2019t be able to save the tag or variable. The available rules are:<\/p>\n<table>\n<thead>\n<tr>\n<th>Rule<\/th>\n<th>How to fail validation<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u2026cannot be empty<\/td>\n<td>User does not input anything into the field.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a string of the required length<\/td>\n<td>User inputs a string that is less than the minimum or more than the maximum length.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a number<\/td>\n<td>User inputs a value that is not an <strong>integer<\/strong> number.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a positive number<\/td>\n<td>User inputs an <strong>integer<\/strong> number that is equal to or less than 0.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a positive number or 0<\/td>\n<td>User inputs an <strong>integer<\/strong> number that is less than 0.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be an integer between 0 and 100 (inclusive)<\/td>\n<td>User inputs an <strong>integer<\/strong> number that is less than 0 or more than 100.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a number between 0 and 1 (inclusive)<\/td>\n<td>User inputs a number (integer or floating point) which is less than 0.0 or more than 1.0.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must match a regular expression<\/td>\n<td>User inputs a value that does not match the given <strong>regular expression<\/strong>. The RegEx accepts <strong>full matches only<\/strong>, so don\u2019t forget to add leading and\/or trailing <code>.*<\/code> if you want it to be an open-ended match.<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a valid GA tracking ID<\/td>\n<td>User inputs a value that does not match the GA tracking ID format (UA-11111-1).<\/td>\n<\/tr>\n<tr>\n<td>\u2026must be a list of the required length<\/td>\n<td>User inputs rows into a table fewer than the minimum length or more than the maximum length. Applies also to a Text input field where <a href=\"#text-as-list\">Text as list<\/a> is being used.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<blockquote>\n<p><strong>NOTE!<\/strong> For fields that are governed by <a href=\"#enabling-conditions\">enabling conditions<\/a>, the validation rule will only apply if the field has been enabled.<\/p>\n<\/blockquote>\n<p>You can click the <strong>action menu<\/strong> for the Validation rule configuration to <strong>Show advanced settings<\/strong>.<\/p>\n<div style=\"aspect-ratio: 1796 \/ 358;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/02\/validation-show-advanced-settings.jpg\" title=\"Show advanced settings\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"358\" width=\"1796\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/02\/validation-show-advanced-settings.jpg#ZgotmplZ\" alt=\"Show advanced settings\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The advanced settings include:<\/p>\n<ul>\n<li>\n<p><strong>Error messages<\/strong>: You can customize the error message that is shown if the field does not pass validation.<\/p>\n<\/li>\n<li>\n<p><strong>Enabling conditions<\/strong>: You can add <a href=\"#enabling-conditions\">enabling conditions<\/a> to the <strong>validation rule itself<\/strong>, meaning <strong>if the enabling conditions do not pass<\/strong>, the <strong>validation rule is ignored<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>, <a href=\"#checkbox\">Checkbox<\/a>, <a href=\"#radio-buttons\">Radio buttons<\/a>, <a href=\"#simple-table\">Simple table<\/a>, <a href=\"#param-table\">Param table<\/a>.<\/p>\n<h3 id=\"value-hint\">Value hint<\/h3>\n<div style=\"aspect-ratio: 2316 \/ 718;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/reference-value-hint.jpg\" title=\"Value hint\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"718\" width=\"2316\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/reference-value-hint.jpg#ZgotmplZ\" alt=\"Value hint\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: The text you enter here will be shown as a <em>placeholder<\/em> value in the field before the user has added any input.<\/p>\n<p><strong>How it works<\/strong>: The text will simply be a placeholder &#8211; it will not be the value of the field if saved without any input.<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>.<\/p>\n<h3 id=\"value-unit\">Value unit<\/h3>\n<div style=\"aspect-ratio: 2328 \/ 666;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2019\/03\/reference-value-unit.jpg\" title=\"Value unit\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"666\" width=\"2328\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2019\/03\/reference-value-unit.jpg#ZgotmplZ\" alt=\"Value unit\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>Description<\/strong>: Use this to guide the users on what type of value is expected in the field.<\/p>\n<p><strong>How it works<\/strong>: The text will be displayed to the right of the field, giving users indication what type of value is expected in the field. The text can be anything (i.e. isn\u2019t restricted to e.g. JavaScript types).<\/p>\n<p><strong>Used in<\/strong>: <a href=\"#text-input\">Text input<\/a>, <a href=\"#drop-down-menu\">Drop-down menu<\/a>.<\/p>\n<h2 id=\"policies-reference\">Policies reference<\/h2>\n<p><strong>Policies<\/strong> are directives the site admin adds to the page template (or, if necessarily, dynamically with JavaScript), which dictate the type of API permissions each custom template can use.<\/p>\n<p>They differ from <a href=\"#permissions\">Permissions<\/a> in one critical detail: where permissions are built into the template, and specify a broader set of API configurations the template can run with, policies are implemented by the site where these templates are run.<\/p>\n<p>In other words, template permissions come from the vendor, template policies come from the site owner. Both have the capability to delimit or restrict the types of templates that can run on any given page.<\/p>\n<p>To provide a policy, you need to use some <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/gtagjs\/\"><code>gtag.js<\/code> code<\/a> (note, you do <strong>not<\/strong> have to install the <code>gtag.js<\/code> snippet!) where you specify the permission requests your site will listen to.<\/p>\n<p>For example, if you have a template that is trying to send a pixel to an endpoint whitelisted in the template\u2019s permissions, you can use a policy to make sure that the template can actually only send the request to one specific endpoint. See the example below.<\/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:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n<span style=\"color:#00a\">function<\/span> gtag(){dataLayer.push(arguments);}\n\ngtag(<span style=\"color:#a50\">'policy'<\/span>, <span style=\"color:#a50\">'send_pixel'<\/span>, <span style=\"color:#00a\">function<\/span>(container, policy, data) {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Only restrict the policy to one specific container by returning true\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#aaa;font-style:italic\">\/\/ for all other containers\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (container !== <span style=\"color:#a50\">'GTM-ABCDE'<\/span>) {\n    <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n  }\n\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Check if the URL of the pixel request is a specific endpoint,\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#aaa;font-style:italic\">\/\/ and if it isn't throw an error and prevent the tag from working.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (data.url !== <span style=\"color:#a50\">'https:\/\/snowplow.simoahava.com\/i'<\/span>) {\n    <span style=\"color:#00a\">throw<\/span>(<span style=\"color:#a50\">'Invalid pixel endpoint!'<\/span>);\n  } <span style=\"color:#00a\">else<\/span> {\n    <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n  }\n});\n<\/code><\/pre>\n<\/div>\n<p>Note: The policy <strong>must<\/strong> return <code>true<\/code> explicitly if you want the check to pass. The policy will always default to returning <code>false<\/code> and preventing the template from working.<\/p>\n<p>You can add more than one policy to the page, each in its own <code>gtag()<\/code> command, or you can check against ALL permissions requests by setting the policy name to <code>all<\/code> as below:<\/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:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n<span style=\"color:#00a\">function<\/span> gtag(){dataLayer.push(arguments);}\n\ngtag(<span style=\"color:#a50\">'policy'<\/span>, <span style=\"color:#a50\">'all'<\/span>, <span style=\"color:#00a\">function<\/span>(container, policy, data) {\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Prevent sending pixels and injecting iframes\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#00a\">if<\/span> (policy === <span style=\"color:#a50\">'send_pixel'<\/span> || policy === <span style=\"color:#a50\">'inject_hidden_iframe'<\/span>) {\n    <span style=\"color:#00a\">throw<\/span> <span style=\"color:#a50\">'Sending pixels and injecting hidden iframes blocked!'<\/span>;\n  } <span style=\"color:#00a\">else<\/span> {\n    <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n  }\n});\n<\/code><\/pre>\n<\/div>\n<p>Please read the <a href=\"https:\/\/developers.google.com\/tag-manager\/templates\/policies\">official policy documentation<\/a> for more details on how policies work.<\/p>\n<p>Below are listed all the policy names and what the <code>data<\/code> object comprises for each.<\/p>\n<h3 id=\"access_globals\">access_globals<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"key\"<\/span>: <span style=\"color:#a50\">\"some_global_var\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ name of the key the permission tries to access\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#a50\">\"read\"<\/span>: <span style=\"color:#00a\">true<\/span> || <span style=\"color:#00a\">false<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ does the key have read access\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#a50\">\"write\"<\/span>: <span style=\"color:#00a\">true<\/span> || <span style=\"color:#00a\">false<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ does the key have write access\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#a50\">\"execute\"<\/span>: <span style=\"color:#00a\">true<\/span> || <span style=\"color:#00a\">false<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ does the key have execute access\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"get_cookies\">get_cookies<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"name\"<\/span>: <span style=\"color:#a50\">\"some_cookie_name\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ name of the cookie being accessed\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"get_referrer\">get_referrer<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"component\"<\/span>: <span style=\"color:#a50\">\"query\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ the component of the referrer URL being accessed\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"get_url\">get_url<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"component\"<\/span>: <span style=\"color:#a50\">\"protocol\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ the URL component name being accessed\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"inject_hidden_iframe\">inject_hidden_iframe<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"url\"<\/span>: <span style=\"color:#a50\">\"https:\/\/some-iframe.com\/\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ the URL of the iframe being injected\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"inject_script\">inject_script<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"url\"<\/span>: <span style=\"color:#a50\">\"https:\/\/some-script.com\/script.js\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ the URL of the script being loaded\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"logging\">logging<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong>There is no <code>data<\/code> object associated with this permission.<\/strong><\/p>\n<h3 id=\"read_character_set\">read_character_set<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong>There is no <code>data<\/code> object associated with this permission.<\/strong><\/p>\n<h3 id=\"read_data_layer\">read_data_layer<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"key\"<\/span>: <span style=\"color:#a50\">\"some.variable.name\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ name of the Data Layer Variable being accessed\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"read_event_metadata\">read_event_metadata<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong>There is no <code>data<\/code> object associated with this permission.<\/strong><\/p>\n<h3 id=\"read_title\">read_title<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong>There is no <code>data<\/code> object associated with this permission.<\/strong><\/p>\n<h3 id=\"send_pixel\">send_pixel<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"url\"<\/span>: <span style=\"color:#a50\">\"https:\/\/some-endpoint.com\/endpoint\"<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ the URL of the pixel request endpoint\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<h3 id=\"set_cookies\">set_cookies<\/h3>\n<p><strong>Triggered by APIs<\/strong>:<\/p>\n<p><strong><code>data<\/code> object composition<\/strong>:<\/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\">{\n  <span style=\"color:#a50\">\"name\"<\/span>: <span style=\"color:#a50\">\"some_cookie_name\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ the name of the cookie\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  <span style=\"color:#a50\">\"options\"<\/span>: {\n    <span style=\"color:#a50\">\"domain\"<\/span>: <span style=\"color:#a50\">\"somedomain.com\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ the domain of the cookie\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#a50\">\"path\"<\/span>: <span style=\"color:#a50\">\"\/some-path\/\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ the path of the cookie\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#a50\">\"max-age\"<\/span>: <span style=\"color:#a50\">\"15000\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ the maximum age of the cookie (in seconds)\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#a50\">\"expires\"<\/span>: <span style=\"color:#a50\">\"Sun, 11 Aug 2019 10:00:00 GMT\"<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ UTC date string of the cookie's expiration\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#a50\">\"secure\"<\/span>: <span style=\"color:#00a\">true<\/span> || <span style=\"color:#00a\">false<\/span>, <span style=\"color:#aaa;font-style:italic\">\/\/ Secure cookie\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#a50\">\"sameSite\"<\/span>: <span style=\"color:#00a\">true<\/span> || <span style=\"color:#00a\">false<\/span> <span style=\"color:#aaa;font-style:italic\">\/\/ sameSite cookie\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  }\n}\n<\/code><\/pre>\n<\/div>\n<h2 id=\"final-thoughts\">Final thoughts<\/h2>\n<p>It\u2019s difficult to compose any sort of summary to what I consider to be the most extensive and fundamental Google Tag Manager update since the programmatic API was released almost five years ago.<\/p>\n<p>Custom templates are, for now, a completely <strong>optional<\/strong> feature. No one is forcing you to use them, and you can continue as a happy GTM user without having to bother about the new <strong>Templates<\/strong> menu.<\/p>\n<p>However, I have a hunch that there is a huge incentive for the GTM team to get rid of the Custom HTML tag and the Custom JavaScript variable. When talking about governance and the existing prejudices towards GTM, especially from developers, it often boils down to being able to inject <strong>any<\/strong> arbitrary JavaScript code on the site, using the outdated and questionable <code>eval()<\/code> method, no less.<\/p>\n<p>With custom templates, many of the problems around governance are presented with a solution:<\/p>\n<ol>\n<li>\n<p>The template code is compiled into JavaScript when the container is created, so <code>eval()<\/code> is no longer used to run the code.<\/p>\n<\/li>\n<li>\n<p>Template-specific permissions (created by the template author) can delimit what the template does <strong>and<\/strong> what types of user input are valid and accepted.<\/p>\n<\/li>\n<li>\n<p>Page-specific policies (created by the site admin) can be used to further restrict what <strong>any<\/strong> template can do on the site.<\/p>\n<\/li>\n<\/ol>\n<p>But these are mostly how templates address <strong>negative<\/strong> qualities of GTM &#8211; it would be foolish to ignore their net <strong>positive<\/strong> effect.<\/p>\n<p>Google Tag Manager is a UI-driven tool. Brands can now use custom templates to encapsulate their complicated JavaScript activation mechanisms under a user interface, thus minimizing the possibility of human error, and demystifying how the vendor JavaScript runs. Thus, instead of sharing a JavaScript snippet the user has to copy-paste to a Custom HTML tag, the brand can share a template export that can be added to the container directly, with all the code in the correct place.<\/p>\n<p>I can\u2019t wait to see what the community comes up with, too! I\u2019m waiting for a library of custom templates to emerge, hopefully sanctioned by Google but moderated by the community (with brands being able to add <strong>verified<\/strong> templates, too).<\/p>\n<p>So now, brave traveller. You have reached the end, though I can only assume you skipped most of the above. What do you think about custom templates? Is my hyperbolic exuberance (yet again) unwarranted?<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Last updated 12 August 2020: Added details about server-side tagging. As I have finally managed to pick up my jaw from the floor, it\u2019s now time to tell you what\u2019s got me so excited. Google Tag Manager recently released a new feature called Custom Templates. Actually, it\u2019s not fair to call it a feature. It\u2019s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":99259,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[834,1531,2059,14495,1791,11455],"dealstore":[],"offerexpiration":[],"class_list":["post-99258","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-custom","tag-google","tag-guide","tag-manager","tag-tag","tag-templates"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Custom Templates Guide For Google Tag Manager - 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:\/\/accountants4yourbusiness.co.uk\/?p=99258\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom Templates Guide For Google Tag Manager - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"Last updated 12 August 2020: Added details about server-side tagging. As I have finally managed to pick up my jaw from the floor, it\u2019s now time to tell you what\u2019s got me so excited. Google Tag Manager recently released a new feature called Custom Templates. Actually, it\u2019s not fair to call it a feature. It\u2019s [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-02-20T10:43:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"918\" \/>\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=\"91 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#article\",\"isPartOf\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/b8eaddeb20a8727558e0d0cddcca426e\"},\"headline\":\"Custom Templates Guide For Google Tag Manager\",\"datePublished\":\"2025-02-20T10:43:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\"},\"wordCount\":16249,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#organization\"},\"image\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage\"},\"thumbnailUrl\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg\",\"keywords\":[\"Custom\",\"Google\",\"Guide\",\"Manager\",\"TAG\",\"Templates\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\",\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\",\"name\":\"Custom Templates Guide For Google Tag Manager - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage\"},\"image\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage\"},\"thumbnailUrl\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg\",\"datePublished\":\"2025-02-20T10:43:35+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage\",\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg\",\"contentUrl\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg\",\"width\":2560,\"height\":918},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/accountants4yourbusiness.co.uk\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Custom Templates Guide For Google Tag Manager\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#website\",\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/\",\"name\":\"Som2ny Network\",\"description\":\"Daily Deals\",\"publisher\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/accountants4yourbusiness.co.uk\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#organization\",\"name\":\"Som2ny Network\",\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"contentUrl\":\"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"width\":300,\"height\":86,\"caption\":\"Som2ny Network\"},\"image\":{\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/b8eaddeb20a8727558e0d0cddcca426e\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Faccountants4yourbusiness.co.uk%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%2Faccountants4yourbusiness.co.uk%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png\",\"caption\":\"admin\"},\"sameAs\":[\"https:\/\/accountants4yourbusiness.co.uk\"],\"url\":\"https:\/\/accountants4yourbusiness.co.uk\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Custom Templates Guide For Google Tag Manager - 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:\/\/accountants4yourbusiness.co.uk\/?p=99258","og_locale":"en_US","og_type":"article","og_title":"Custom Templates Guide For Google Tag Manager - Som2ny Network","og_description":"Last updated 12 August 2020: Added details about server-side tagging. As I have finally managed to pick up my jaw from the floor, it\u2019s now time to tell you what\u2019s got me so excited. Google Tag Manager recently released a new feature called Custom Templates. Actually, it\u2019s not fair to call it a feature. It\u2019s [&hellip;]","og_url":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258","og_site_name":"Som2ny Network","article_published_time":"2025-02-20T10:43:35+00:00","og_image":[{"width":2560,"height":918,"url":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg","type":"image\/jpeg"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"91 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#article","isPartOf":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258"},"author":{"name":"admin","@id":"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/b8eaddeb20a8727558e0d0cddcca426e"},"headline":"Custom Templates Guide For Google Tag Manager","datePublished":"2025-02-20T10:43:35+00:00","mainEntityOfPage":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258"},"wordCount":16249,"commentCount":0,"publisher":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/#organization"},"image":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage"},"thumbnailUrl":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg","keywords":["Custom","Google","Guide","Manager","TAG","Templates"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/accountants4yourbusiness.co.uk\/?p=99258#respond"]}]},{"@type":"WebPage","@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258","url":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258","name":"Custom Templates Guide For Google Tag Manager - Som2ny Network","isPartOf":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/#website"},"primaryImageOfPage":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage"},"image":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage"},"thumbnailUrl":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg","datePublished":"2025-02-20T10:43:35+00:00","breadcrumb":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/accountants4yourbusiness.co.uk\/?p=99258"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#primaryimage","url":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg","contentUrl":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2025\/02\/custom-templates-google-tag-manager-scaled.jpg","width":2560,"height":918},{"@type":"BreadcrumbList","@id":"https:\/\/accountants4yourbusiness.co.uk\/?p=99258#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/accountants4yourbusiness.co.uk\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Custom Templates Guide For Google Tag Manager"}]},{"@type":"WebSite","@id":"https:\/\/accountants4yourbusiness.co.uk\/#website","url":"https:\/\/accountants4yourbusiness.co.uk\/","name":"Som2ny Network","description":"Daily Deals","publisher":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/accountants4yourbusiness.co.uk\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/accountants4yourbusiness.co.uk\/#organization","name":"Som2ny Network","url":"https:\/\/accountants4yourbusiness.co.uk\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/logo\/image\/","url":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","contentUrl":"https:\/\/accountants4yourbusiness.co.uk\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","width":300,"height":86,"caption":"Som2ny Network"},"image":{"@id":"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/b8eaddeb20a8727558e0d0cddcca426e","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/accountants4yourbusiness.co.uk\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Faccountants4yourbusiness.co.uk%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%2Faccountants4yourbusiness.co.uk%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png","caption":"admin"},"sameAs":["https:\/\/accountants4yourbusiness.co.uk"],"url":"https:\/\/accountants4yourbusiness.co.uk\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/99258","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=99258"}],"version-history":[{"count":0,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/99258\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=\/wp\/v2\/media\/99259"}],"wp:attachment":[{"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=99258"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=99258"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=99258"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=99258"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/accountants4yourbusiness.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=99258"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}