This document outlines the permissions for server-side 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_bigquery

**Display name:** Accesses BigQuery

**Description:** Allows access to BigQuery on Google Cloud Platform.

**Configuration:** Option to allow specified project, dataset, and table
combinations to be used with BigQuery. Setting a project ID configuration of
`GOOGLE_CLOUD_PROJECT` will allow using the `GOOGLE_CLOUD_PROJECT` environment
variable as the project ID when `projectId` is excluded from the [`BigQuery API
parameter`](https://developers.google.com/tag-platform/tag-manager/server-side/api#bigquery_parameters).

**Required by:** [`BigQuery`](https://developers.google.com/tag-platform/tag-manager/server-side/api#bigquery)

**Query signature:**
`queryPermission('access_bigquery', <operation>, <options>)`

**Notes:** `<operation>` is a string and can have the following values:

- write

`<options>` is an object containing the following items:

    {
      'projectId': <project_id>,
      'datasetId': <dataset_id>,
      'tableId': <table_id>
    }

**Example code**

    const BigQuery = require('BigQuery');
    const queryPermission = require('queryPermission');

    const connectionInfo = {
      'projectId': 'gcp-cloud-project-id',
      'datasetId': 'destination-dataset',
      'tableId': 'destination-table',
    };

    if (queryPermission('access_bigquery', 'write', connectionInfo)) {
      const rows = [{
        'column1': 'String1',
        'column2': 1234,
      }];
      const options = {
        'ignoreUnknownValues': true,
        'skipInvalidRows': false,
      };

      BigQuery.insert(connectionInfo, rows, options)
          .then(data.gtmOnSuccess, data.gtmOnFailure);
    }

## access_firestore

**Display name:** Accesses Google Firestore

**Description:** Allows access to Google Firestore.

**Configuration:** Option to allow specified project and path (wildcard syntax
supported) combinations to be used with Firestore. Setting a project ID
configuration of `GOOGLE_CLOUD_PROJECT` will allow using the
`GOOGLE_CLOUD_PROJECT` environment variable as the project ID when `projectId`
is excluded from the [`Firestore API parameter`](https://developers.google.com/tag-platform/tag-manager/server-side/api#firestore_read_parameters).

**Required by:** [`Firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/api#firestore)

**Query signature:**
`queryPermission('access_firestore', <operation>, <options>)`

**Notes:** `<operation>` is a string and can have the following values:

- read - Grants access to read and query APIs
- write - Grants access to write API
- read_write - Grants access to read, write, and query APIs

`<options>` is an object containing the following items:

    {
      'projectId': <project_id>,
      'path': <path>
    }

**Example code**

    const Firestore = require('Firestore');
    const queryPermission = require('queryPermission');

    const options = {
      'projectId': 'gcp-cloud-project-id',
      'path': 'collection/document',
    };

    if (queryPermission('access_firestore', 'read', options)) {
      Firestore.read('collection/document', {
        projectId: 'gcp-cloud-project-id',
      }).then(data.gtmOnSuccess, data.gtmOnFailure);
    }

## access_response

**Display name:** Accesses response

**Description:** Accesses the response body, headers, or status.

**Configuration:** Option to allow any or specific access, with sub-options for
controlling access to various subcomponents.

**Required by:** [`setPixelResponse`](https://developers.google.com/tag-platform/tag-manager/server-side/api#setpixelresponse), [`setResponseBody`](https://developers.google.com/tag-platform/tag-manager/server-side/api#setresponsebody),
[`setResponseHeader`](https://developers.google.com/tag-platform/tag-manager/server-side/api#setresponseheader), [`setResponseStatus`](https://developers.google.com/tag-platform/tag-manager/server-side/api#setresponsestatus)

**Query signature:**
`queryPermission('access_response', 'write', <component>[, <optional component name>])`

**Notes:** Governs whether the outgoing HTTP response component can be accessed.

**Example code**

    const queryPermission = require('queryPermission');
    const setResponseBody = require('setResponseBody');
    const setResponseHeader = require('setResponseHeader');
    const setResponseStatus = require('setResponseStatus');
    if (queryPermission('access_response', 'write', 'header', 'Content-Type')) {
      setResponseHeader('Content-Type', 'text/plain');
    }
    if (queryPermission('access_response', 'write', 'body')) {
      setResponseBody('Not Found');
    }
    if (queryPermission('access_response', 'write', 'status')) {
      setResponseStatus(404);
    }

## access_template_storage

**Display name:** Accesses Template Storage

**Description:** Allows access to temporary storage for templates that can
persist for the lifetime of the server-side process.

**Configuration:** None

**Required by:** [`templateDataStorage`](https://developers.google.com/tag-platform/tag-manager/server-side/api#templatedatastorage)

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

**Example code**

    const queryPermission = require('queryPermission');
    const templateDataStorage = require('templateDataStorage');
    const key = 'my_key';
    if (queryPermission('access_template_storage')) {
      const value = templateDataStorage.getItemCopy(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/server-side/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);
    }

## logging

**Display name:** Logs to console

**Description:** Logs to the developer console and Tag Manager'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/server-side/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');

## use_message

**Display name:** Uses messages

**Description:** Sends or receives messages using the `addMessageListener` or
`sendMessage` APIs.

**Configuration:** Option to specify the message type and whether the template
can listen, send, or both.

**Required by:** [`addMessageListener`](https://developers.google.com/tag-platform/tag-manager/server-side/api#addmessagelistener), [`sendMessage`](https://developers.google.com/tag-platform/tag-manager/server-side/api#sendmessage)

**Query signature:** `queryPermission('use_message', <usage>, <message type>)`

**Notes:** Usage can be one of `listen`, `send`, or `listen_and_send`.

**Example code**

    const queryPermission = require('queryPermission');
    const sendMessage = require('sendMessage');
    if (queryPermission('use_message', 'send', 'set_cookie')) {
      sendMessage('set_cookie', {name: 'foo', value: 'bar'});
    }

## read_container_data

**Display name:** Reads container data

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

**Configuration:** None.

**Required by:** [`getClientName`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getclientname), [`getContainerVersion`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getcontainerversion)

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

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

**Example code**

    const getContainerVersion = require('getContainerVersion');
    const queryPermission = require('queryPermission');
    if (queryPermission('read_container_data')) {
      return getContainerVersion();
    }

## read_event_data

**Display name:** Reads event data

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

**Configuration:** Option to allow any access, or specific access controlled by
a list of allowed key paths (wildcard syntax supported).

**Required by:** [`getAllEventData`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getalleventdata), [`getEventData`](https://developers.google.com/tag-platform/tag-manager/server-side/api#geteventdata)

**Query signature:** `queryPermission('read_event_data'[, <optional key>])`

**Notes:** Controls whether a custom template can read event data at a given key
path (or all the event data, if no key path is given).

**Example code**

    const getAllEventData = require('getAllEventData');
    const queryPermission = require('queryPermission');
    if (queryPermission('read_event_data')) {
      return getAllEventData();
    }

    const getEventData = require('getEventData');
    const queryPermission = require('queryPermission');
    const keyPath = 'parentField.childField';
    if (queryPermission('read_event_data', keyPath)) {
      return getEventData(keyPath);
    }

## 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/server-side/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_request

**Display name:** Reads HTTP request

**Description:** Reads the request headers, query parameters, body, path, or
remote IP address.

**Configuration:** Option to allow any or specific access, with sub-options for
controlling access to various subcomponents.

**Required by:** [`extractEventsFromMpv1`](https://developers.google.com/tag-platform/tag-manager/server-side/api#extracteventsfrommpv1), [`extractEventsFromMpv2`](https://developers.google.com/tag-platform/tag-manager/server-side/api#extracteventsfrommpv2),
[`getRemoteAddress`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getremoteaddress), [`getRequestBody`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestbody), [`getRequestHeader`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestheader),
[`getRequestPath`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestpath), [`getRequestQueryParameter`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestqueryparameter), [`getRequestQueryParameters`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestqueryparameters),
[`getRequestQueryString`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getrequestquerystring)

**Query signature:**
`queryPermission('read_request', <component>[, <optional component name>])`

**Notes:** Governs whether the incoming HTTP response component can be accessed.

**Example code**

    const queryPermission = require('queryPermission');
    const getRequestBody = require('getRequestBody');
    const getRequestHeader = require('getRequestHeader');
    let body, contentType;
    if (queryPermission('read_request', 'body')) {
      body = getRequestBody();
    }
    if (queryPermission('read_request', 'header', 'content-type')) {
      contentType = getRequestHeader('content-type');
    }
    if (body && contentType == 'application/json') { ... }

## return_response

**Display name:** Returns response

**Description:** Returns response to the caller.

**Configuration:** None

**Required by:** [`returnResponse`](https://developers.google.com/tag-platform/tag-manager/server-side/api#returnresponse)

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

**Notes:** This permission has no fields to narrow, and is typically not queried
for.

## run_container

**Display name:** Runs the container

**Description:** Runs the container with an event

**Configuration:** None

**Required by:** [`runContainer`](https://developers.google.com/tag-platform/tag-manager/server-side/api#runcontainer)

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

**Notes:** This permission has no fields to narrow, and is typically not queried
for.

## send_http

**Display name:** Sends HTTP requests

**Description:** Sends an HTTP request to a specified URL.

**Required by:** [`getGoogleScript`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getgooglescript), [`sendEventToGoogleAnalytics`](https://developers.google.com/tag-platform/tag-manager/server-side/api#sendeventtogoogleanalytics),
[`sendHttpGet`](https://developers.google.com/tag-platform/tag-manager/server-side/api#sendhttpget), [`sendHttpRequest`](https://developers.google.com/tag-platform/tag-manager/server-side/api#sendhttprequest)

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

**Notes:** Governs whether an HTTP request can be made, depending on the URL.
To ensure a secure connection, only secure (HTTPS) URLs are permitted.

**Example code**

    const queryPermission = require('queryPermission');
    const sendHttpGet = require('sendHttpGet');
    const url = 'https://example.com/search?query=foo&results=10';
    if (queryPermission('send_http', url)) {
      sendHttpGet(url);
    }

## send_pixel_from_browser

**Display name:** Sends pixels from browsers

**Description:** Sends a GET request to a specified URL from the browser.

**Required by:** [`sendPixelFromBrowser`](https://developers.google.com/tag-platform/tag-manager/server-side/api#sendpixelfrombrowser)

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

**Notes:** Governs whether a request can be sent from the browser, depending on
the URL.

**Example code**

    const queryPermission = require('queryPermission');
    const sendPixelFromBrowser = require('sendPixelFromBrowser');
    const url = 'https://example.com/search?query=foo&results=10';
    if (queryPermission('send_pixel_from_browser', url)) {
      sendPixelFromBrowser(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/server-side/api#setcookie)

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

**Notes:** Governs whether a given 'Set-Cookie' header can be added to the
response, 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);
    }

## use_custom_private_keys

**Display name:** Uses custom private keys

**Description:** Uses private keys from a JSON key file for cryptographic
operations.

**Configuration:** A list of allowed key IDs. The IDs must match the keys in
the JSON key file referenced by the `SGTM_CREDENTIALS` environment variable
on the server.

**Required by:** [`hmacSha256`](https://developers.google.com/tag-platform/tag-manager/server-side/api#hmacsha256)

**Query signature:** `queryPermission('use_custom_private_keys', <key id>)`

**Notes:** Governs the list of allowed private keys.

**Example code**

    const hmacSha256= require('hmacSha256');
    const queryPermission = require('queryPermission');
    const keyId = 'key1';

    let result;
    if (queryPermission('use_custom_private_keys', keyId)) {
      result = hmacSha256('my_data', keyId);
    }

## use_google_credentials

**Display name:** Uses Google Application Default Credentials

**Description:** Uses the Google default credentials to make calls to Google
APIs.

**Configuration:** A list of allowed [Google OAuth 2.0 scopes](https://developers.google.com/identity/protocols/oauth2/scopes).

**Required by:** [`getGoogleAuth`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getgoogleauth)

**Query signature:** `queryPermission('use_google_credentials', <scopes>)`

**Notes:** Restricts the allowed Google OAuth 2.0 scopes for use with Google
APIs.

**Example code**

    const getGoogleAuth = require('getGoogleAuth');
    const queryPermission = require('queryPermission');

    const scopes = [
      'https://www.googleapis.com/auth/datastore'
    ];

    let auth;
    if (queryPermission('use_google_credentials', scopes)) {
      auth = getGoogleAuth(scopes);
    }

## user_ip

**Display name:** Reads user IP address

**Description:** Reads the IP address of the user.

**Configuration:** None

**Required by:** [`getAnonymizedIpAddress`](https://developers.google.com/tag-platform/tag-manager/server-side/api#getanonymizedipaddress)

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

**Notes:** Controls whether a custom template can read the IP address of the
user.

**Example code**

    const getAnonymizedIpAddress = require('getAnonymizedIpAddress');
    const queryPermission = require('queryPermission');

    if (queryPermission('user_ip')) {
      return getAnonymizedIpAddress();
    }