# Custom template permissions

This document outlines the permissions for Web custom templates.

*** ** * ** ***

Each permission is:

- Checked by APIs that require them.
- Automatically detected in sandboxed JavaScript, based on what APIs are used. This happens as edits are made in the custom template editor (for a fast feedback loop), and when code is compiled (to validate that the correct permissions are enforced).
- Editable in the custom template editor, to make the permission more specific.
- Queryable in sandboxed JavaScript via the `queryPermission` API.

## access_globals

**Display name:** Accesses global variables

**Description:** Allows access to a global variable (potentially including
sensitive APIs).

**Configuration:** List of keys that can be accessed. Each key is a dot
separated path. For example: `foo.bar` The first token in each path must not be
a predefined key on browser global scope, nor a JavaScript keyword. Has read,
write, and execute checkboxes that govern access.


**Required by:** [`setInWindow`](https://developers.google.com/tag-platform/tag-manager/templates/api#setinwindow), [`copyFromWindow`](https://developers.google.com/tag-platform/tag-manager/templates/api#copyfromwindow), [`callInWindow`](https://developers.google.com/tag-platform/tag-manager/templates/api#callinwindow),
[`createQueue`](https://developers.google.com/tag-platform/tag-manager/templates/api#createqueue), [`createArgumentsQueue`](https://developers.google.com/tag-platform/tag-manager/templates/api#createargumentsqueue)

**Query signature:** `queryPermission('access_globals', 'read', <key to read
from>)` or `queryPermission('access_globals', 'write', <key to write to>)` or
`queryPermission('access_globals', 'readwrite', <key to read and write>)` or
`queryPermission('access_globals', 'execute', <key of function to execute>)`

**Notes:** Controls whether a custom template can read and/or write to global
values.

**Example code**

    const queryPermission = require('queryPermission');
    const createQueue = require('createQueue');
    if (queryPermission('access_globals', 'readwrite', 'dataLayer')) {
      const dataLayerPush = createQueue('dataLayer');
    }

## access_local_storage

**Display name:** Accesses local storage

**Description:** Allows access to the specified keys in local storage.

**Configuration:** List of local storage keys that can be accessed. This is a
simple array of keys, with no wildcards. Has read and write checkboxes that
govern access.

**Required by:** [`localStorage`](https://developers.google.com/tag-platform/tag-manager/templates/api#localstorage)

**Query signature:** `queryPermission('access_local_storage', 'read', <key to
read from>)` or `queryPermission('access_local_storage', 'write', <key to write
to>)` or `queryPermission('access_local_storage', 'readwrite', <key to read and
write>)`

**Example code**

    const queryPermission = require('queryPermission');
    const localStorage = require('localStorage');
    const key = 'my_key';
    if (queryPermission('access_local_storage', 'read', key)) {
      const value = localStorage.getItem(key);
    }

## access_template_storage

**Display name:** Accesses template storage

**Description:** Allows access to temporary storage for templates that can
persist for the lifetime of the page.

**Configuration:** None

**Required by:** [`templateStorage`](https://developers.google.com/tag-platform/tag-manager/templates/api#templatestorage)

**Query signature:** `queryPermission('access_template_storage')`

**Example code**

    const queryPermission = require('queryPermission');
    const templateStorage = require('templateStorage');
    const key = 'my_key';
    if (queryPermission('access_template_storage')) {
      const value = templateStorage.getItem(key);
    }

## get_cookies

**Display name:** Reads cookie value(s)

**Description:** Reads the values of the cookies with the specified name.

**Configuration:** List of names of cookies permitted for reading.

**Required by:** [`getCookieValues`](https://developers.google.com/tag-platform/tag-manager/templates/api#getcookievalues)

**Query signature:** `queryPermission('get_cookies', <name>)`

**Notes:** Governs whether a cookie can be read, depending on its name.

**Example code**

    const queryPermission = require('queryPermission');
    const getCookieValues = require('getCookieValues');
    const cookieName = 'info';
    let cookieValues;
    if (queryPermission('get_cookies', cookieName)) {
      cookieValues = getCookieValues(cookieName);
    }

## get_referrer

**Display name:** Reads referrer URL

**Description:** Permits read access to narrowed portions of the referrer.

**Configuration:** The following booleans govern which part of the referrer can
be read. A given part of the referrer can only be read if the corresponding part
is `true`. The caller can call `getReferrerUrl` without a component specified to
get the full referrer URL if all these booleans are set to `true`. If no value
is set, the default value is `all`. If a value is set, the value must be an
array of components where a component is one of the following: `protocol`,
`host`, `port`, `path`, `query`, or `extension`.

*`queryKeys`:*
If query is selected, then the template author may further limit the set of
query keys they can read from. This is a simple array of keys, with no
wildcards.

> [!NOTE]
> **Note:** Since the feature that utilizes `queryKeys` is still a work in progress, the ideal setting is to allow any query key.

**Required by:** [`getReferrerUrl`](https://developers.google.com/tag-platform/tag-manager/templates/api#getreferrerurl), [`getReferrerQueryParameters`](https://developers.google.com/tag-platform/tag-manager/templates/api#getreferrerqueryparameters)

**Query signature:** `queryPermission('get_referrer', <url_component>)`

**Example code**

    const queryPermission = require('queryPermission');
    const getReferrerUrl = require('getReferrerUrl');
    let referrer;
    if (queryPermission('get_referrer', 'query')) {
      referrer = getReferrerUrl('queryParams');
    }

## get_url

**Display name:** Reads URL

**Description:** Returns part or all of the URL of the current page.

**Configuration:** The following booleans govern which part of the URL can be
read. A given part of the URL can only be read if the corresponding part is
true. The caller can call `getUrl` without a component specified to get the
entire URL if and only if all these booleans are set to `true`. If no value is
set, the default value is `all`. If a value is set, the value must be an array
of components where a component is one of the following: `protocol`, `host`,
`port`, `path`, `query`, `extension`, or `fragment`.

*`queryKeys`:*
If query is selected, then the template author may further limit the set of
query keys they can read from. This is a simple array of keys, with no
wildcards.

> [!NOTE]
> **Note:** Since the feature that utilizes `queryKeys` is still a work in progress, the ideal setting is to allow any query key.

**Required by:** [`getUrl`](https://developers.google.com/tag-platform/tag-manager/templates/api#geturl)

**Query signature:** `queryPermission('get_url', <optional url component>,
<optional query key>)`

If supplied, Url component should be one of `'protocol'`, `'host'`, `'port'`,
`'path'`, `'query'`, `'extension'`, `'fragment'`. If omitted, the permission
query is a request for access to the whole URL.

If supplied, query key should be the query string argument that the template
code wants to read.

**Notes:** Controls whether a custom template can read from the current
location. Allows limiting to a specific part of the location.

**Example code**

    const queryPermission = require('queryPermission');
    const getUrl = require('getUrl');
    if (queryPermission('get_url', 'query', 'gclid')) {
      const gclid = getUrl('query', false, null, 'gclid');
    }

## inject_hidden_iframe

**Display name:** Injects hidden iframes

**Description:** Injects an invisible iframe with a given URL.

**Configuration:** List of URL patterns

**Required by:** [`injectHiddenIframe`](https://developers.google.com/tag-platform/tag-manager/templates/api#injecthiddeniframe)

**Query signature:** `queryPermission('inject_hidden_iframe', <url>)`

**Notes:** Governs whether a custom template can inject an invisible iFrame, and
from which origin it can do so.

**Example code**

    const queryPermission = require('queryPermission');
    const injectHiddenIframe = require('injectHiddenIframe');
    const url = 'https://www.example.com/iframes';
    if (queryPermission('inject_hidden_iframe', url)) {
      injectHiddenIframe(url);
    }

## inject_script

**Display name:** Injects scripts

**Description:** Injects a script into the page.

**Configuration:** List of URL patterns

**Required by:** [`injectScript`](https://developers.google.com/tag-platform/tag-manager/templates/api#injectscript)

**Query signature:** `queryPermission('inject_script', <url>)`

**Notes:** Governs whether a custom template can inject JavaScript, and from
what origin it can do so.

**Example code**

    const queryPermission = require('queryPermission');
    const injectScript = require('injectScript');
    const url = 'https://www.example.com?api.js';
    if (queryPermission('inject_script', url)) {
      injectScript(url);
    }

## logging

**Display name:** Logs to console

**Description:** Logs to the developer console and GTM's preview mode.

**Configuration:** Option to enable logging in production. Defaults to only
enable logging in debug/preview. If permission is denied, `logToConsole` will
not throw an error, but will suppress the log message.

**Required by:** [`logToConsole`](https://developers.google.com/tag-platform/tag-manager/templates/api#logtoconsole)

**Query signature:** `queryPermission('logging')`

**Notes:** Controls whether a custom template can log to the developer console.

**Example code**

    const queryPermission = require('queryPermission');
    const logToConsole = require('logToConsole');
    // Note that it's fine to call log, since the log call will be ignored if
    // logging isn't permitted in the current environment.
    logToConsole('diagnostic info');

## read_data_layer

**Display name:** Reads data layer

**Description:** Reads data from the dataLayer.

**Configuration:** Set of key match expressions, where a key match can be a
leading series of dotted references, with a trailing wildcard. Key match
expressions govern which properties may be read from the data layer.

**Required by:** [`copyFromDataLayer`](https://developers.google.com/tag-platform/tag-manager/templates/api#copyfromdatalayer)

**Query signature:** `queryPermission('read_data_layer', <data layer key to read
from>)`

**Notes:** Controls whether a custom template can read from the data layer.

**Example code**

    const queryPermission = require('queryPermission');
    const copyFromDataLayer = require('copyFromDataLayer');
    const dlKey = 'foo.bar';
    if (queryPermission('read_data_layer', dlKey)) {
      const dlContents = copyFromDataLayer(dlKey);
    }

## read_analytics_storage

**Display name:** Reads analytics storage

**Description:** This allows templates to read stored analytics data such as
Client IDs.

**Configuration:** None

**Required by:** [`readAnalyticsStorage`](https://developers.google.com/tag-platform/tag-manager/templates/api#readanalyticsstorage)

**Query signature:** `queryPermission('read_analytics_storage')`

**Notes:** Governs whether a custom template can read from analytics storage.

**Example code**

    const queryPermission = require('queryPermission');
    const readAnalyticsStorage = require('readAnalyticsStorage');
    if (queryPermission('read_analytics_storage')) {
      const value = readAnalyticsStorage();
    }

## read_character_set

**Display name:** Reads document character set

**Description:** Reads `document.characterSet`.

**Configuration:** None

**Required by:** [`readCharacterSet`](https://developers.google.com/tag-platform/tag-manager/templates/api#readcharacterset)

**Query signature:** `queryPermission('read_character_set')`

**Notes:** Governs whether a custom template can read `document.characterSet`.

**Example code**

    const queryPermission = require('queryPermission');
    const readCharacterSet = require('readCharacterSet');
    if (queryPermission('read_character_set')) {
      const characterSet = readCharacterSet();
    }

## read_container_data

**Display name:** Reads container data

**Description:** Reads data about the container.

**Configuration:** None

**Required by:** [`getContainerVersion`](https://developers.google.com/tag-platform/tag-manager/templates/api#getcontainerversion)

**Query signature:** `queryPermission('read_container_data')`

**Notes:** Controls whether a custom template can read data about the container.

**Example code**

    const queryPermission = require('queryPermission');
    const getCookieValues = require('getContainerVersion');
    let version;
    if (queryPermission('read_container_data')) {
      version = getContainerVersion();
    }

## read_event_metadata

**Display name:** Reads event metadata

**Description:** Reads event metadata in Event Callbacks

**Configuration:** None

**Required by:** [`addEventCallback`](https://developers.google.com/tag-platform/tag-manager/templates/api#addeventcallback)

**Query signature:** `queryPermission('read_event_metadata')`

**Notes:** Controls whether a custom template can read event metadata in
callbacks.

**Example code**

    const queryPermission = require('queryPermission');
    const addEventCallback = require('addEventCallback');
    if (queryPermission('read_event_metadata')) {
      addEventCallback((containerId, eventMetadata) => {
        // Read event metadata.
      });
    }

## read_title

**Display name:** Reads document title

**Description:** Reads `document.title`.

**Configuration:** None

**Required by:** [`readTitle`](https://developers.google.com/tag-platform/tag-manager/templates/api#readtitle)

**Query signature:** `queryPermission('read_title')`

**Notes:** Governs whether a custom template can read the `document.title`.

**Example code**

    const queryPermission = require('queryPermission');
    const readTitle = require('readTitle');
    if (queryPermission('read_title')) {
      const title = readTitle();
    }

## send_pixel

**Display name:** Sends pixels

**Description:** Sends a GET request to a specified URL. Response is not
processed.

**Configuration:** List of allowed URL patterns.

**Required by:** [`sendPixel`](https://developers.google.com/tag-platform/tag-manager/templates/api#sendpixel)

**Query signature:** `queryPermission('send_pixel', <url>)`

**Notes:** Governs whether a custom template can send a GET request, and to
which origin it can do so.

**Example code**

    const queryPermission = require('queryPermission');
    const sendPixel = require('sendPixel');
    const url = 'https://www.example.com?foo=3';
    if (queryPermission('send_pixel', url)) {
      sendPixel(url);
    }

## set_cookies

**Display name:** Sets a cookie

**Description:** Sets a cookie with the specified name and parameters.

**Configuration:** A table of allowed cookie names, each with optional
restrictions on name, domain, path, `secure` attribute, and expiration.

**Required by:** [`setCookie`](https://developers.google.com/tag-platform/tag-manager/templates/api#setcookie)

**Query signature:** `queryPermission('set_cookies', <name>, <options>)`

**Notes:** Governs whether a cookie can be written, depending on the cookie
name, domain, path, `secure` attribute, and expiration.

**Example code**

    const queryPermission = require('queryPermission');
    const setCookie = require('setCookie');
    const options = {
      'domain': 'www.example.com',
      'path': '/',
      'max-age': 60*60*24*365,
      'secure': true
    };
    if (queryPermission('set_cookies', 'info', options)) {
      setCookie('info', 'xyz', options);
    }

## write_data_layer

**Display name:** Writes data layer

**Description:** Writes data to the dataLayer.

**Configuration:** Set of key match expressions, where a key match can be a
leading series of dotted references, with a trailing wildcard. Key match
expressions govern which properties may write to the data layer.

**Required by:** [`gtagSet`](https://developers.google.com/tag-platform/tag-manager/templates/api#gtagSet)

**Query signature:** `queryPermission('write_data_layer', <data layer key to
write from>)`

**Notes:** Controls whether a custom template can write to the data layer.

**Example code**

    const queryPermission = require('queryPermission');
    const gtagSet = require('gtagSet');
    const dlKey = 'foo.bar';
    if (queryPermission('write_data_layer', dlKey)) {
      gtagSet({dlKey: 'baz'});
    }