Server-side custom template permissions

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_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, setResponseBody, setResponseHeader, 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

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

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 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

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, 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, 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, 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

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, extractEventsFromMpv2, getRemoteAddress, getRequestBody, getRequestHeader, getRequestPath, getRequestQueryParameter, getRequestQueryParameters, 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

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

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, sendEventToGoogleAnalytics, sendHttpGet, sendHttpRequest

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

Notes: Governs whether an HTTP request can be made, depending on the URL.

Example code

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

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

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);
}