This document outlines the APIs for server-side tagging.

*** ** * ** ***

## `addEventCallback`

Registers a callback function that will be invoked at the end of an event. The
callback will be invoked when all the tags for the event have executed. The
callback is passed two values: the id of the container that invokes the function
and an object that contains information about the event.

When this API is used in a tag, it is associated to the current event. When this
API is used in a client, it must be bound to a specific event using the
`runContainer` API's `bindToEvent` function. See the
[example](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#addEventCallback_example) for more details.

**Syntax**

```javascript
const addEventCallback = require('addEventCallback');

addEventCallback((containerId, eventData) => {
  // Take some action based on the event data.
});
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`callback`** | *function* | The function to invoke at the end of the event. |

The `eventData` object contains the following data:

| Key Name | Type | Description |
|---|---|---|
| **`tags`** | *Array* | An array of tag data objects. Every tag that fired during the event will have an entry in this array. The tag data object contains the tag's ID (`id`), its execution status (`status`), and its execution time (`executionTime`). The tag data will also include additional tag metadata that was configured on the tag. |

**Example**

In a client:

```javascript
const addEventCallback = require('addEventCallback');
const claimRequest = require('claimRequest');
const extractEventsFromMpv1 = require('extractEventsFromMpv1');
const logToConsole = require('logToConsole');
const returnResponse = require('returnResponse');
const runContainer = require('runContainer');

claimRequest();

const events = extractEventsFromMpv1();
let eventsCompleted = 0;
events.forEach((evt, i) => {
  runContainer(evt, /* onComplete= */ (bindToEvent) => {
    bindToEvent(addEventCallback)((containerId, eventData) => {
      logToConsole('Event Number: ' + i);
      eventData.tags.forEach((tag) => {
        logToConsole('Tag ID: ' + tag.id);
        logToConsole('Tag Status: ' + tag.status);
        logToConsole('Tag Execution Time: ' + tag.executionTime);
      });
    });
    if (events.length === ++eventsCompleted) {
      returnResponse();
    }
  });
});
```

In a tag:

```javascript
const addEventCallback = require('addEventCallback');

addEventCallback((containerId, eventData) => {
  // This will be called at the end of the current event.
});
```

**Associated permissions**

[`read_event_metadata`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_event_metadata)

*** ** * ** ***

## `callLater`

Schedules a call to a function to occur asynchronously. The function will be
called after the current code returns. This is equivalent to
`setTimeout(<function>, 0)`.

**Example**

```javascript
const callLater = require('callLater');
const logToConsole = require('logToConsole');

callLater(() => {
  logToConsole('Logged asynchronously');
});
```

**Syntax**

`callLater(function)`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`function`** | *function* | The function to call. |

**Associated permissions**

None.

*** ** * ** ***

## `claimRequest`

Use this API in a client to claim the request. Once a request is claimed, the
container does not run additional clients.

This API throws an exception if called in a tag or variable. This API throws an
exception if called after the client returns (e.g. if called in an async
callback such as in `callLater` or the `runContainer` `onComplete` function).

A client should claim the request using this API before calling the
`runContainer` API.

**Example**

```javascript
const claimRequest = require('claimRequest');

claimRequest();
```

**Syntax**

```javascript
claimRequest();
```

**Associated permissions**

None.

*** ** * ** ***

## `computeEffectiveTldPlusOne`

Returns the effective top-level domain + 1 (eTLD+1) of the given domain or URL.
The eTLD+1 is computed by evaluating the domain against the [Public Suffix List](https://publicsuffix.org/)
rules. The eTLD+1 is typically the highest-level domain on which you can set a
cookie.

If the argument is null or undefined, then the argument value is returned
unaltered. Otherwise the argument is coerced to a string. If the argument is not
a valid domain or URL, then a blank string is returned. If the server is unable
to fetch the public suffix list, then the argument value is returned unaltered.

**Example**

```javascript
const computeEffectiveTldPlusOne = require('computeEffectiveTldPlusOne');

// Returns 'example.co.uk'
computeEffectiveTldPlusOne('analytics.example.co.uk');

// Returns 'example.co.uk'
computeEffectiveTldPlusOne('https://analytics.example.co.uk/path');
```

**Syntax**

```javascript
computeEffectiveTldPlusOne(domainOrUrl);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`domainOrUrl`** | *string* | A domain or URL on which to compute the eTLD+1. |

**Associated permissions**

None.

*** ** * ** ***

## `createRegex`

Creates a new regex instance and returns it wrapped in an object. You cannot
access the regex directly. However, you can pass it into the `testRegex` API,
`String.replace()`, `String.match()`, and `String.search()`.

Returns `null` if the regex is invalid or Re2 is unavailable on the server.

This API uses an [Re2](https://github.com/google/re2/wiki/Syntax)
implementation. The server Docker image must be at version [2.0.0](https://developers.google.com/tag-platform/tag-manager/server-side/release-notes.md.txt#2.0.0) or later.

**Example**

```javascript
const createRegex = require('createRegex');

const domainRegex = createRegex('\\w+\\.com', 'i');

// Returns '/foobar'
'example.com/foobar'.replace(domainRegex, '');
```

**Syntax**

```javascript
createRegex(pattern, flags);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`pattern`** | *string* | Text of the regular expression. |
| **`flags`** | *string* | An optional string containing the flags for the regex being created. \`g\` (global) and \`i\` (ignore case) are supported. All other characters are silently ignored. |

**Associated permissions**

None.

**Minimum image version**

[2.0.0](https://developers.google.com/tag-platform/tag-manager/server-side/release-notes.md.txt#2.0.0)

*** ** * ** ***

## `decodeUri`

Decodes any encoded characters in the provided URI. Returns a **string** that
represents the decoded URI. Returns `undefined` when provided with invalid
input.

**Example**

```javascript
const decodeUri = require('decodeUri');

const decodedUrl = decodeUri(data.encodedUrl);
if (decodedUrl) {
  // ...
}
```

**Syntax**

```javascript
decodeUri(encoded_uri);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`encoded_uri`** | *string* | A URI that has been encoded by [`encodeUri()`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#encodeuri) or by other means. |

**Associated permissions**

None.

*** ** * ** ***

## `decodeUriComponent`

Decodes any encoded characters in the provided URI component. Returns a
**string** that represents the decoded URI component. Returns `undefined` when
given invalid input.

**Example**

```javascript
const decodeUriComponent = require('decodeUriComponent');

const decodedQuery = decodeUriComponent(data.query);
if (decodedQuery) {
  // ...
}
```

**Syntax**

```javascript
decodeUriComponent(encoded_uri_component);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`encoded_uri_component`** | *string* | A URI component that has been encoded by [`encodeUriComponent()`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#encodeuricomponent) or by other means. |

**Associated permissions**

None.

*** ** * ** ***

## `encodeUri`

Returns an encoded Uniform Resource Identifier (URI) by escaping special
characters. Returns a **string** that represents the provided string encoded
as a URI.

**Example**

```javascript
const encodeUri = require('encodeUri');
const sendHttpGet = require('sendHttpGet');

sendHttpGet('https://www.example.com/' + encodeUri(pathInput));
```

**Syntax**

```javascript
encodeUri(uri);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`uri`** | *string* | A complete URI. |

**Associated permissions**

None.

*** ** * ** ***

## `encodeUriComponent`

Returns an encoded Uniform Resource Identifier (URI) by escaping special
characters. Returns a **string** that represents the provided string encoded as
a URI.

**Example**

```javascript
const encodeUriComponent = require('encodeUriComponent');
const sendHttpGet = require('sendHttpGet');

sendHttpGet('https://www.example.com/?' + encodeUriComponent(queryInput));
```

**Syntax**

```javascript
encodeUriComponent(str);

```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`str`** | *string* | A component of a URI. |

**Associated permissions**

None.

*** ** * ** ***

## `extractEventsFromMpv1`

Translates an incoming Measurement Protocol V1 request into a list of events in
Unified Schema format. Returns the list of extracted events. Throws an error if
the request is not in the correct format.

**Example**

```javascript
const extractEventsFromMpv1 = require('extractEventsFromMpv1');
const isRequestMpv1 = require('isRequestMpv1');

if (isRequestMpv1()) {
  const events = extractEventsFromMpv1();
  for (let i = 0; i < events.length; ++i) {
    const event = events[i];
    // Process event.
  }
}
```

**Syntax**

```javascript
extractEventsFromMpv1();
```

**Associated permissions**

Requires [`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request) permission. The permission must be configured to
permit access to at least:

- `body`
- `query parameters`

*** ** * ** ***

## `extractEventsFromMpv2`

Translates an incoming Measurement Protocol V2 request into a list of events in
Unified Schema format. Returns the list of extracted events. Throws an error if
the request is not in the correct format.

**Example**

```javascript
const extractEventsFromMpv2 = require('extractEventsFromMpv2');
const isRequestMpv2 = require('isRequestMpv2');

if (isRequestMpv2()) {
  const events = extractEventsFromMpv2();
  for (let i = 0; i < events.length; ++i) {
    const event = events[i];
    // Process event.
  }
}
```

**Syntax**

```javascript
extractEventsFromMpv2();
```

**Associated permissions**

Requires [`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request) permission. The permission must be configured to
permit access to at least:

- `body`
- `query parameters`

*** ** * ** ***

## `fromBase64`

Decodes a base64-encoded string. Returns `undefined` if the input is invalid.

**Syntax**

    fromBase64(base64EncodedString);

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`base64EncodedString`** | *string* | Base64 encoded string. |

**Example**

```javascript
const fromBase64 = require('fromBase64');

const greeting = fromBase64('aGVsbG8=');
if (greeting === 'hello') {
  // ...
}
```

**Associated permissions**

None.

*** ** * ** ***

## `generateRandom`

Returns a random **number** (integer) within the given range.

**Example**

```javascript
const generateRandom = require('generateRandom');

const randomValue = generateRandom(0, 10000000);
```

**Syntax**

```javascript
generateRandom(min, max);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`min`** | *number* | Minimum potential value of the returned integer (inclusive). |
| **`max`** | *number* | Maximum potential value of the returned integer (inclusive). |

**Associated permissions**

None.

*** ** * ** ***

## `getAllEventData`

Returns a copy of the event data.

**Syntax**

```javascript
getAllEventData();
```

**Associated permissions**

[`read_event_data`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_event_data)

*** ** * ** ***

## `getAnonymizedIpAddress`

Returns an anonymized **string** representation of the IP address where the
request originated.

For IPv4 addresses, the last octet is masked to `0` (for example,
`198.51.100.42` becomes `198.51.100.0`). For IPv6 addresses, the last 80 bits
are masked to zeros, retaining the first 48 bits (for example,
`2001:db8:cafe:1234:5678:90ab:cdef:1234` becomes `2001:db8:cafe::`).

Returns `"::"` if the IP address is invalid or cannot be resolved, so the result
is always safe to use as `ip_override`.

**Example**

```javascript
const getAnonymizedIpAddress = require('getAnonymizedIpAddress');

const anonymizedIp = getAnonymizedIpAddress();
```

**Syntax**

```javascript
getAnonymizedIpAddress();
```

**Associated permissions**

[`user_ip`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#user_ip)

*** ** * ** ***

## `getClientName`

Returns a **string** that contains the name of the current client.

**Syntax**

```javascript
getClientName();
```

**Associated permissions**

[`read_container_data`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_container_data)

*** ** * ** ***

## `getContainerVersion`

Returns an **object** containing data about the current container. The returned
object will have the following fields:

```javascript
{
  containerId: string,
  debugMode: boolean,
  environmentName: string,
  environmentMode: boolean,
  previewMode: boolean,
  version: string,
}
```

**Example**

```javascript
const getContainerVersion = require('getContainerVersion');

const containerVersion = getContainerVersion();
const containerId = containerVersion['containerId'];
const isDebug = containerVersion['debugMode'];
```

**Syntax**

```javascript
getContainerVersion();
```

**Associated permissions**

[`read_container_data`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_container_data)

*** ** * ** ***

## `getCookieValues`

Returns an array containing the values of all cookies with the given name.

**Example**

```javascript
const getCookieValues = require('getCookieValues');

const lastVisit = getCookieValues('lastVisit')[0];
if (lastVisit) {
  // ...
}
```

**Syntax**

```javascript
getCookieValues(name[, noDecode]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`name`** | *string* | Name of the cookie. |
| **`noDecode`** | *boolean* | If `true`, the cookie values will not be decoded before being returned. Defaults to `false`. |

**Associated permissions**

[`get_cookies`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#get_cookies)

*** ** * ** ***

## `getEventData`

Returns a copy of the value at the given path in the event data. Returns
`undefined` if there is no event data or if there is no value at the given path.

**Example**

```javascript
const getEventData = require('getEventData');

const campaignId = getEventData('campaign.id');
const itemId = getEventData('items.0.id');
const referrer = getEventData('page_referrer');
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`keyPath`** | *any* | The path of the key, where path components are separated by dots. The path components can be keys in an object or indices in an array. If `keyPath` is not a string, it is coerced into a string. |

**Syntax**

```javascript
getEventData(keyPath);
```

**Associated permissions**

[`read_event_data`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_event_data)

*** ** * ** ***

## `getGoogleAuth`

Returns an authorization object that when used with
[`sendHttpGet`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#sendhttpget) or [`sendHttpRequest`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#sendhttprequest), will
include an authorization header for Google Cloud APIs. This API uses
[Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) to automatically find credentials from
the server environment.

**Example**

```javascript
const getGoogleAuth = require('getGoogleAuth');
const logToConsole = require('logToConsole');
const sendHttpGet = require('sendHttpGet');

const auth = getGoogleAuth({
  scopes: ['https://www.googleapis.com/auth/datastore']
});

sendHttpGet(
  'https://firestore.googleapis.com/v1/projects/my-project/databases/(default)/documents/collection/document',
  {authorization: auth}
).then((result) => {
  if (result.statusCode >= 200 && result.statusCode < 300) {
    logToConsole('Result: ' + result.body);
    data.gtmOnSuccess();
  } else {
    data.gtmOnFailure();
  }
});
```

**Syntax**

```javascript
getGoogleAuth(scopes);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`scopes`** | *Array* | An array of [OAuth 2.0 Google API scopes](https://developers.google.com/identity/protocols/oauth2/scopes.md.txt) to request access for. |

**Associated permissions**

Requires [`use_google_credentials`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#use_google_credentials) permission. The permission must be
configured with one or more allowed scopes.

*** ** * ** ***

## `getGoogleScript`

Retrieves a resource from a predetermined set of Google scripts, and returns a
[promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise) with the script and associated caching metadata.

The promise will resolve to an object containing two keys: `script` and
`metadata`. If the request fails, the promise will reject with a `reason` key.

The `metadata` object will contain the following caching metadata based on the
resource response headers; each field will only be present if the corresponding
header is present in the resource response.

```javascript
{
  'cache-control': string,
  'expires': string,
  'last-modified': string,
}
```

**Example**

```javascript
const getGoogleScript = require('getGoogleScript');

getGoogleScript('ANALYTICS').then((result) => {
  // Operate on result.script and result.metadata here.
});
```

**Syntax**

```javascript
getGoogleScript(script[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`script`** | *string* | The name of the script. Supported scripts are `'ANALYTICS'`, `'GTAG'`, and `'GTM'`. The `'ANALYTICS'` option fetches the Google Analytics script from `https://www.google-analytics.com/analytics.js`. The `'GTAG'` option fetches the global site tag (gtag.js) script from `https://www.googletagmanager.com/gtag/js`. <br /> The `'GTM'` option fetches the Google Tag Manager script from `https://www.googletagmanager.com/gtm.js`. |
| **`options`** | *object* | Optional request options. See below for supported options. |

**Options**

| Option | Type | Description |
|---|---|---|
| **`id`** | *string* | Applicable to `'GTAG'` with the gtag measurement ID and `'GTM'` with the web container ID (ex. GTM-XXXX). |
| **`debug`** | *any* | If truthy, requests and returns the debug version of the measurement script. |
| **`timeout`** | *number* | The request timeout in milliseconds; non-positive values are ignored. If the request times out, the callback will be invoked with `undefined` for the script value and `{}` for the metadata object. |

Unrecognized option keys are ignored.

**Associated permissions**

Requires [`send_http`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#send_http) permission. The permission must be configured to permit
access to at least:

- Allow Google Domains

*** ** * ** ***

## `getRemoteAddress`

Returns a **string** representation of the IP address where the request
originated, e.g. `12.345.67.890` for IPv4 or `2001:0db8:85a3:0:0:8a2e:0370:7334`
for IPv6, by reading request headers such as Forwarded and X-Forwarded-For.
Note: this API makes a best-effort attempt to discover the originating IP, but
it cannot guarantee that the result is accurate.

**Syntax**

```javascript
getRemoteAddress();
```

**Associated permissions**

Requires [`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request) permission. The permission must be configured to
permit access to at least:

- Headers `Forwarded` and `X-Forwarded-For`
- Remote IP Address

*** ** * ** ***

## `getRequestBody`

Returns the request body as a **string** , if present, or `undefined` otherwise.

**Syntax**

```javascript
getRequestBody();
```

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getRequestHeader`

Returns the value of the named request header as a **string** , if present, or
`undefined` otherwise. If the header is repeated, the returned values are joined
together with `', '`.

**Example**

```javascript
const getRequestHeader = require('getRequestHeader');

const host = getRequestHeader('host');
```

**Syntax**

```javascript
getRequestHeader(headerName);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`headerName`** | *string* | The header name. This value is case-insensitive. |

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getRequestMethod`

Returns the request method, e.g. `'GET'` or `'POST'`, as a **string**.

**Example**

```javascript
const getRequestMethod = require('getRequestMethod');

if (getRequestMethod() === 'POST') {
  // Handle the POST request here.
}
```

**Syntax**

```javascript
getRequestMethod();
```

**Associated permissions**

None.

*** ** * ** ***

## `getRequestPath`

Returns the request path without the query string. For example, if the URL is
`'/foo?id=123'`, this returns `'/foo'`. Automatically strips the Server
container URL prefix from the path. For example, if Server container URL is
`https://example.com/analytics` and the request path is `'/analytics/foo'`, this
returns `'/foo'`.

**Example**

```javascript
const getRequestPath = require('getRequestPath');

const requestPath = getRequestPath();
if (requestPath === '/') {
  // Handle a request for the root path.
}
```

**Syntax**

```javascript
getRequestPath();
```

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getRequestQueryParameter`

Returns the decoded value of the named query string parameter as a **string** ,
or `undefined` if the parameter is not present. If the parameter is repeated in
the query string, the first value that appears in the query string will be
returned.

**Example**

```javascript
const getRequestQueryParameter = require('getRequestQueryParameter');

const query = getRequestQueryParameter('query');
if (query) {
  // Process query here.
}
```

**Syntax**

```javascript
getRequestQueryParameter(name);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`name`** | *string* | The query parameter name. |

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getRequestQueryParameters`

Returns the incoming HTTP request's query parameters as an object that maps
query parameter names to the corresponding value or values. The parameter names
and values are decoded.

**Example**

```javascript
const getRequestQueryParameters = require('getRequestQueryParameters');

const queryParameters = getRequestQueryParameters();
if (queryParameters['search']) {
  // Handle the search query here.
  const maxResults = queryParameters['max_results'];
}
```

**Syntax**

```javascript
getRequestQueryParameters();
```

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getRequestQueryString`

Returns the request query as a string, without the leading question mark, or an
empty string if the request URL does not include a query string.

**Example**

```javascript
const getRequestQueryString = require('getRequestQueryString');

const queryString = getRequestQueryString();
if (queryString !== '') {
  // Handle the query string.
}
```

**Syntax**

```javascript
getRequestQueryString();
```

**Associated permissions**

[`read_request`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#read_request)

*** ** * ** ***

## `getTimestamp`

**Deprecated.** Prefer [getTimestampMillis](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#gettimestampmillis).

Returns a **number** that represents the current time in milliseconds since Unix
epoch, as returned by `Date.now()`.

**Syntax**

```javascript
getTimestamp();
```

**Associated permissions**

None.

*** ** * ** ***

## `getTimestampMillis`

Returns a **number** that represents the current time in milliseconds since Unix
epoch, as returned by `Date.now()`.

**Syntax**

```javascript
getTimestampMillis();
```

**Associated permissions**

None.

*** ** * ** ***

## `getType`

Returns a string describing the given value's type.

| Input Type | Returned Value |
|---|---|
| *string* | `'string'` |
| *number* | `'number'` |
| *boolean* | `'boolean'` |
| *null* | `'null'` |
| *undefined* | `'undefined'` |
| *Array* | `'array'` |
| *Object* | `'object'` |
| *Function* | `'function'` |

**Example**

```javascript
const getType = require('getType');

const type = getType(value);
if (type === 'string') {
  // Handle string input.
} else if (type === 'number') {
  // Handle numeric input.
} else {
  logToConsole('Unsupported input type: ', type);
}
```

**Syntax**

```javascript
getType(value);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`value`** | *any* | Input value. |

**Associated permissions**

None.

*** ** * ** ***

## `hmacSha256`

Calculates an encoded signature using Hash-based Message Authentication
Code (HMAC) with SHA-256. Defaults to `base64url` encoding.

To use this API, set the `SGTM_CREDENTIALS` environment variable on the server
to the path of a UTF-8 encoded JSON key file with the following format:

```javascript
{
  "keys": {
    "key1": "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5",
    "key2": "OTg3NjU0MzIxMHp5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2Jh",
    ...
  }
}
```

The values are base64-encoded HMAC keys. The JSON text must not start with a
byte order marker.

**Example**

```javascript
const hmacSha256 = require('hmacSha256');
const toBase64 = require('toBase64');

const header = toBase64('{"alg":"HS256","typ":"JWT"}', {urlEncoding: true});
const claim = toBase64('{"sub":"1234567890","iat":1698164946}', {urlEncoding: true});
const signature = hmacSha256(header + '.' + claim, 'key1');

const jwt = header + "." + claim + '.' + signature;
```

**Syntax**

```javascript
hmacSha256(data, keyId, options)
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`data`** | *string* | The data to compute the HMAC value. |
| **`keyId`** | *string* | A key id from the JSON key file referring to the key to use. |
| **`options`** | *object* | *Optional* API configuration. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#hmacSha256_options) below.) |

**Options**

| Option | Type | Description |
|---|---|---|
| **`outputEncoding`** | *string* | Specifies the encoding format for the return value. Supported formats are `hex`, `base64`, or `base64url`. Defaults to `base64url` if not specified. |

**Associated permissions**

[`use_custom_private_keys`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#use_custom_private_keys)

**Minimum image version**

[1.0.0](https://developers.google.com/tag-platform/tag-manager/server-side/release-notes.md.txt#1.0.0)

*** ** * ** ***

## `isRequestMpv1`

Returns `true` if the incoming request is a Measurement Protocol V1 request, or
`false` otherwise.

**Example**

```javascript
const isRequestMpv1 = require('isRequestMpv1');

if (isRequestMpv1()) {
  // Handle Measurement Protocol V1 request.
  const events = extractEventsFromMpv1();
}
```

**Syntax**

```javascript
isRequestMpv1();
```

**Associated permissions**

None.

*** ** * ** ***

## `isRequestMpv2`

Returns `true` if the incoming request is a Measurement Protocol V2 request, or
`false` otherwise.

**Example**

```javascript
const isRequestMpv2 = require('isRequestMpv2');

if (isRequestMpv2()) {
  // Handle Measurement Protocol V2 request.
  const events = extractEventsFromMpv2();
}
```

**Syntax**

```javascript
isRequestMpv2();
```

**Associated permissions**

None.

*** ** * ** ***

## `logToConsole`

Logs its argument(s) to the console.

These logs are visible within [Logs Explorer](https://cloud.google.com/logging/docs/view/logs-viewer-interface) in the Google Cloud Console.
From Logs Explorer run the query `logName =~ "stdout"` to see log entries
created by this API.

**Example**

```javascript
const logToConsole = require('logToConsole');

const that = 123;
const those = { ... };
logToConsole('that is: ', that, ' and those is: ', those);
```

**Syntax**

```javascript
logToConsole(argument1[, argument2, ...]);
```

**Parameters**

The API takes one or more arguments, each of which is converted to a string, if
necessary, and logged to the console.

**Associated permissions**

[`logging`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#logging)

*** ** * ** ***

## `makeInteger`

Converts the given value to a **number** (integer).

**Syntax**

```javascript
makeInteger(value);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`value`** | *any type* | The value to convert. |

**Associated permissions**

None.

*** ** * ** ***

## `makeNumber`

Converts the given value to a **number**.

**Syntax**

```javascript
makeNumber(value);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`value`** | *any type* | The value to convert. |

**Associated permissions**

None.

*** ** * ** ***

## `makeString`

Returns the given value as a **string**.

**Syntax**

```javascript
makeString(value);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`value`** | *any type* | The value to convert. |

**Associated permissions**

None.

*** ** * ** ***

## `makeTableMap`

Converts a simple table object with two columns to a `Map`. This is used to
change a `SIMPLE_TABLE` template field with two columns into a more manageable
format.

For example, this function could convert a table object:

```javascript
[
  {'key': 'k1', 'value': 'v1'},
  {'key': 'k2', 'value': 'v2'}
]
```

into a Map:

```javascript
{
  'k1': 'v1',
  'k2': 'v2'
}
```

Returns an **Object** : The converted `Map` of key-value pairs have been added to
it, or `null` otherwise.

**Syntax**

```javascript
makeTableMap(tableObj, keyColumnName, valueColumnName);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`tableObj`** | *List* | The table object to convert. It's a list of maps where each `Map` represents a row in the table. Each property name in a row object is the column name, and the property value is the column value in the row. |
| **`keyColumnName`** | *string* | Name of the column whose values will become keys in the converted `Map`. |
| **`valueColumnName`** | *string* | Name of the column whose values will become values in the converted `Map`. |

**Associated permissions**

None.

*** ** * ** ***

## `parseUrl`

Returns an object that contains all of a given URL's component parts, similar to
the `URL` object.

This API will return `undefined` for any malformed URL. For properly formatted
URLs, fields not present in the URL string will have a value of an empty string,
or in the case of `searchParams`, an empty object.

The returned object will have the following fields:

```javascript
{
  href: string,
  origin: string,
  protocol: string,
  username: string,
  password: string,
  host: string,
  hostname: string,
  port: string,
  pathname: string,
  search: string,
  searchParams: Object<string, (string|Array)>,
  hash: string,
}
```

**Example**

```javascript
const parseUrl = require('parseUrl');

const urlObject = parseUrl('https://abc:xyz@example.com:8080/foo?param=val%2Cue#bar');
```

**Syntax**

```javascript
parseUrl(url);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`url`** | *string* | The full url that will be parsed. |

**Associated permissions**

None.

*** ** * ** ***

## `returnResponse`

Flushes the response that was previously set by other templates using the APIs
that modify the response, including [setCookie](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setcookie),
[setPixelResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setpixelresponse), [setResponseBody](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setresponsebody),
[setResponseHeader](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setresponseheader), and
[setResponseStatus](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setresponsestatus). Defaults to an HTTP status code 200,
empty body, and no headers.

It is recommended that this API be used from a client template.

**Syntax**

```javascript
returnResponse();
```

**Example**

See the [`runContainer` example](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#runContainer_example).

**Associated permissions**

[`return_response`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#return_response)

*** ** * ** ***

## `runContainer`

Runs the container logic (variables, triggers, tags) in the scope of an event.
If this API is called during container execution, the container is run again.

The `onComplete` and `onStart` callbacks receive a function called
`bindToEvent`. Use `bindToEvent` to run an API in the context of the event.
See the [addEventCallback example](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#addEventCallback_example) for more details.

It is recommended that this API be used from a client template.

**Example**

```javascript
const returnResponse = require('returnResponse');
const runContainer = require('runContainer');

// Runs the container with a simple pageview event and then returns a response.
runContainer({'event_name': 'pageview'}, () => returnResponse());
```

**Syntax**

```javascript
runContainer(event, onComplete, onStart);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`event`** | *object* | The event parameters. |
| **`onComplete`** | *function* | A callback that is invoked after all the tags finish firing. |
| **`onStart`** | *function* | A callback that is invoked immediately, before the tags start firing. |

**Associated permissions**

[`run_container`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#run_container)

*** ** * ** ***

## `sendEventToGoogleAnalytics`

Sends a single event using [Common Event Data](https://developers.google.com/tag-platform/tag-manager/server-side/common-event-data.md.txt) to Google Analytics and returns a
[promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise) that resolves to an object with a `location` key or
rejects to an object with a `reason` key. The destination, Google Analytics,
is based on the measurement ID in the event data.

The `location` field is set to the `location` header, if present.

**Example**

```javascript
const logToConsole = require('logToConsole');
const sendEventToGoogleAnalytics = require('sendEventToGoogleAnalytics');
const setResponseHeader = require('setResponseHeader');
const setResponseStatus = require('setResponseStatus');

// Sends an event to Google Analytics and returns failure if the request did not
// succeed. Additionally, if the request resulted in a redirect request, the
// code nominates a redirect response to be returned.
sendEventToGoogleAnalytics(event).then((response) => {
  if (response.location) {
    setResponseHeader('location', response.location);
    setResponseStatus(302);
  } else {
    setResponseStatus(200);
  }
  data.gtmOnSuccess();
}).catch((error) => {
  logToConsole(error.reason);
  setResponseStatus(500);
  data.gtmOnFailure();
});
```

**Syntax**

```javascript
sendEventToGoogleAnalytics(event);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`event`** | *object* | The event in Unified Schema format. |

**Associated permissions**

Requires [`send_http`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#send_http) permission. The permission must be configured to permit
access to at least:

- Allow Google Domains

*** ** * ** ***

## `sendHttpGet`

Makes an HTTP GET request to the specified URL, and returns a
[promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise) that resolves with the result once the request completes or
times out.

The resolved result is an object containing three keys: `statusCode`, `headers`,
and `body`. If the request failed (e.g. invalid URL, no route to host,
SSL negotiation failure, etc.), the promise will reject with: `{reason:
'failed'}`. If the `timeout` option was set and the request timed out, the
promise will reject with: `{reason: 'timed_out'}`

**Example**

```javascript
const sendHttpGet = require('sendHttpGet');

// Returns the response body as the value for a variable.
return sendHttpGet('https://example.com/item/' + data.itemId, {
  headers: {key: 'value'},
  timeout: 500,
}).then((result) => result.body, () => undefined);
```

**Syntax**

```javascript
sendHttpGet(url[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`url`** | *string* | The requested URL. |
| **`options`** | *object* | *Optional* request options. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#sendHttpGet_options) below.) |

**Options**

| Option | Type | Description |
|---|---|---|
| **`headers`** | *string* | Additional request headers. |
| **`timeout`** | *number* | The timeout, in milliseconds, before the request is aborted. Defaults to `15000`. |
| **`authorization`** | *object* | *Optional* authorization object from the call to [`getGoogleAuth`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#getgoogleauth) for including authorization headers when making requests to `googleapis.com`. |

**Associated permissions**

[`send_http`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#send_http)

*** ** * ** ***

## `sendHttpRequest`

Makes an HTTP request to the specified URL, and returns a [promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise)
that resolves with the response once the request completes or times out.

The resolved result is an object containing three keys: `statusCode`, `headers`,
and `body`. If the request failed (e.g. invalid URL, no route to host,
SSL negotiation failure, etc.), the promise will reject with: `{reason:
'failed'}`. If the `timeout` option was set and the request timed out, the
promise will reject with: `{reason: 'timed_out'}`

**Example**

```javascript
const sendHttpRequest = require('sendHttpRequest');
const setResponseBody = require('setResponseBody');
const setResponseHeader = require('setResponseHeader');
const setResponseStatus = require('setResponseStatus');

const postBody = 'interaction=click&campaign=promotion&medium=email';
// Sends a POST request and nominates response based on the response to the POST
// request.
sendHttpRequest('https://example.com/collect', {
  headers: {key: 'value'},
  method: 'POST',
  timeout: 500,
}, postBody).then((result) => {
  setResponseStatus(result.statusCode);
  setResponseBody(result.body);
  setResponseHeader('cache-control', result.headers['cache-control']);
});
```

**Syntax**

```javascript
sendHttpRequest(url[, options[, body]]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`url`** | *string* | The requested URL. |
| **`options`** | *object* | *Optional* request options. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#sendHttpRequest_options) below.) |
| **`body`** | *string* | *Optional* request body. |

**Options**

| Option | Type | Description |
|---|---|---|
| **`headers`** | *string* | Additional request headers. |
| **`method`** | *object* | The request method. Defaults to `GET`. |
| **`timeout`** | *number* | The timeout, in milliseconds, before the request is aborted. Defaults to `15000`. |
| **`authorization`** | *object* | *Optional* authorization object from the call to [`getGoogleAuth`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#getgoogleauth) for including authorization headers when making requests to `googleapis.com`. |

**Associated permissions**

[`send_http`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#send_http)

*** ** * ** ***

## `sendPixelFromBrowser`

Sends a command to the browser to load the provided URL as an `<img>` tag. This
command protocol is supported in the **Google Tag** for Google Analytics and
**Google Analytics: GA Event** web tags. You must configure the server container
URL. See [the instructions](https://developers.google.com/tag-platform/tag-manager/server-side/send-data.md.txt#tag_manager) for more details.

This API returns `false` if the incoming request does not support the command
protocol, or if the response has already been flushed. Otherwise this API
returns `true`.

**Example:**

```javascript
const sendPixelFromBrowser = require('sendPixelFromBrowser');

sendPixelFromBrowser('https://example.com/?id=123');
```

**Syntax**

`sendPixelFromBrowser(url)`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`url`** | *string* | The url to send to the browser. |

**Associated permissions**

[`send_pixel_from_browser`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#send_pixel_from_browser)

*** ** * ** ***

## `setCookie`

Sets or deletes a cookie with the specified options.

To delete a cookie, one must set a cookie with the same path and domain that the
cookie was created with, and assign it an expires value that is in the past,
e.g. `"Thu, 01 Jan 1970 00:00:00 GMT"`.

Note that [returnResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#returnresponse) must be called for the response to
be sent back to the client.

**Example**

```javascript
const setCookie = require('setCookie');

// Sets an httpOnly cookie with a max-age of 3600.
setCookie('cookieName', 'cookieValue', {'max-age': 3600, httpOnly: true});
```

**Syntax**

```javascript
setCookie(name, value[, options[, noEncode]]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`name`** | *string* | The cookie name. The name is case-insensitive. |
| **`value`** | *string* | The cookie value. |
| **`options`** | *object* | Optional cookie attributes:**domain** , **expires** , **fallbackDomain** ,**httpOnly** , **max- age** , **path** , **secure** , and**sameSite** . (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#setCookie_options), below.) |
| **`noEncode`** | *boolean* | If true, the cookie value will not be encoded. Defaults to `false`. |

**Options**

- **domain:** The host to which the cookie will be sent. If set to the special
  value 'auto', then the host will be automatically computed using the
  following strategy:

  - eTLD+1 of `Forwarded` header, if present.
  - eTLD+1 of `X-Forwarded-Host` header, if present.
  - eTLD+1 of `Host` header.
- **expires** : The maximum lifetime of the cookie. This must a UTC-formatted
  date string, e.g. "Sat, 26 Oct 1985 08:21:00 GMT". If both `expires` and
  `max-age` are set, `max-age` has precedence.

- **httpOnly** : Forbids JavaScript from accessing the cookie if `true`.

- **max-age** : Number of seconds until the cookie expires. A zero or negative
  number will expire the cookie immediately. If both `expires` and `max-age`
  are set, `max-age` has precedence.

- **path**: A path that must exist in the requested URL, or the browser won't
  send the Cookie header.

- **secure** : If set to `true`, the cookie is only sent to the server when a
  request is made from an `https:` endpoint.

- **sameSite** : Asserts that a cookie must not be sent with cross-origin
  requests. Must be `'strict'`, `'lax'`, or `'none'`.

**Associated permissions**

[`set_cookie`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#set_cookies)

*** ** * ** ***

## `setPixelResponse`

Sets response body to a 1x1 GIF, sets the Content-Type header to 'image/gif',
sets caching headers such that user agents will not cache the response, and sets
the response status to 200.

Note that [returnResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#returnresponse) must be called for the response to
be sent back to the client.

**Syntax**

```javascript
setPixelResponse();
```

**Associated permissions**

Requires [`access_response`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_response) permission. The permission must be configured to
permit access to at least:

- `headers` - Must permit the following keys
  - `content-type`
  - `cache-control`
  - `expires`
  - `pragma`
- `body`
- `status`

*** ** * ** ***

## `setResponseBody`

Sets the response body to the argument.

Note that [returnResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#returnresponse) must be called for the response to
be sent back to the client.

**Syntax**

```javascript
setResponseBody(body[, encoding]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`body`** | *string* | The value to set as the response body. |
| **`encoding`** | *string* | The character encoding of the response body (defaults to `'utf8'`). Supported values include `'ascii'`, `'utf8'`, `'utf16le'`, `'ucs2'`, `'base64'`, `'latin1'`, `'binary'`, and `'hex'`. |

**Associated permissions**

Requires [`access_response`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_response) permission. The permission must be configured to
permit access to at least:

- `body`

*** ** * ** ***

## `setResponseHeader`

Sets a header in the response that will be returned. If a header with this name
(case-insensitive) was previously set by this API, the latter call will
overwrite or clear the value set by the prior caller.

Note that [returnResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#returnresponse) must be called for the response to
be sent back to the client.

**Syntax**

```javascript
setResponseHeader(name, value);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`name`** | *string* | The header name. HTTP header names are case-insensitive, so the header name will be lowercased. |
| **`value`** | *string* *undefined* | The header value. If null or undefined, this clears the named header from the response that will be returned. |

**Associated permissions**

Requires [`access_response`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_response) permission. The permission must be configured to
permit access to at least:

- `headers`

*** ** * ** ***

## `setResponseStatus`

Sets the HTTP status code of the response that will be returned.

Note that [returnResponse](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#returnresponse) must be called for the response to
be sent back to the client.

**Syntax**

```javascript
setResponseStatus(statusCode);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`statusCode`** | *number* | The HTTP status code to be returned. |

**Associated permissions**

Requires [`access_response`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_response) permission. The permission must be configured to
permit access to at least:

- `status`

*** ** * ** ***

## `sha256`

Calculates the SHA-256 digest of the input and invokes a callback with the
digest encoded in base64, unless the `options` object specifies a different
output encoding.

This API signature and behavior matches the [`sha256`](https://developers.google.com/tag-platform/tag-manager/templates/api.md.txt#sha256) API for web containers;
however, Custom Templates in server containers should use the
[`sha256Sync`](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#sha256sync) API for simpler code.

**Example**

```javascript
const encodeUriComponent = require('encodeUriComponent');
const sendHttpGet = require('sendHttpGet');
const sha256 = require('sha256');

sha256('inputString', (digest) => {
  sendHttpGet('https://example.com/collect?id=' + encodeUriComponent(digest));
});

sha256('inputString', (digest) => {
  sendHttpGet('https://example.com/collect?id=' + encodeUriComponent(digest));
}, {outputEncoding: 'hex'});
```

**Syntax**

```javascript
sha256(input, onSuccess, options = undefined);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`input`** | *string* | The string to hash. |
| **`onSuccess`** | *function* | Called with the resulting digest, encoded in base64, unless the `options` object specifies a different output encoding. |
| **`options`** | *object* | *Optional* options object to specify the output encoding. If specified, the object should contain the key `outputEncoding` with value as one of `base64` or `hex`. |

**Associated permissions**

None.

*** ** * ** ***

## `sha256Sync`

Calculates and returns the SHA-256 digest of the input, encoded in base64,
unless the `options` object specifies a different output encoding.

**Example**

```javascript
const encodeUriComponent = require('encodeUriComponent');
const sendHttpGet = require('sendHttpGet');
const sha256Sync = require('sha256Sync');

const digestBase64 = sha256Sync('inputString');
const digestHex = sha256Sync('inputString', {outputEncoding: 'hex'});
sendHttpGet('https://example.com/collect?id=' + encodeUriComponent(digestBase64));
sendHttpGet('https://example.com/collect?id=' + encodeUriComponent(digestHex));
```

**Syntax**

```javascript
sha256Sync(input, options = undefined);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`input`** | *string* | The string to hash. |
| **`options`** | *object* | *Optional* options object to specify the output encoding. If specified, the object should contain the key `outputEncoding` with value as one of `base64` or `hex`. |

**Associated permissions**

None.

*** ** * ** ***

## `templateDataStorage`

Returns an object with methods for accessing template data storage. Template
data storage allows data to be shared across executions of a single template.
Data stored in template data storage persists on the server running the
container. In most cases there are multiple servers running the container, so
storing data in template data storage does not guarantee that every subsequent
request will have access to the data.

The "data" in the name "templateDataStorage" refers to the fact that only plain,
non-function data types may be stored using this API. Any functions or
references to functions passed to the API will be stored as `null` instead.

> [!NOTE]
> **Note:** Requests that come from debug or preview mode, or from the template editor, are given access to template data storage that is initialized to empty and persists only for the lifetime of the request (so as not to mingle debug or test data with production data).

> [!NOTE]
> **Note:** Unlike the [Web Storage API](https://developer.mozilla.org/docs/Web/API/Storage), `templateDataStorage` does not serialize/deserialize data into strings.

**Syntax**

```javascript
const templateDataStorage = require('templateDataStorage');

// Returns a copy of the value stored for the given key, or null if nothing
// is stored with that key.
templateDataStorage.getItemCopy(key);

// Stores a copy of the value for the given key (or removes the data stored
// for the given key if the input value is null).
templateDataStorage.setItemCopy(key, value);

// Removes the value stored for the given key, if present.
templateDataStorage.removeItem(key);

// Deletes all values stored for the current template.
templateDataStorage.clear();
```

**Example**

```javascript
const sendHttpGet = require('sendHttpGet');
const setResponseBody = require('setResponseBody');
const setResponseStatus = require('setResponseStatus');
const templateDataStorage = require('templateDataStorage');

// Check to see if the item is in the cache.
const cachedBody = templateDataStorage.getItemCopy(data.key);
if (cachedBody) {
  setResponseBody(cachedBody);
  data.gtmOnSuccess();
  return;
}

sendHttpGet(data.url).then((result) => {
  if (result.statusCode >= 200 && result.statusCode < 300) {
    setResponseBody(result.body);
    templateDataStorage.setItemCopy(data.key, result.body);
    data.gtmOnSuccess();
  } else {
    data.gtmOnFailure();
  }
  setResponseStatus(result.statusCode);
});
```

**Associated permissions**

[`access_template_storage`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_template_storage)

*** ** * ** ***

## `testRegex`

Tests a string against an regex created via `createRegex` API. Returns `true`
if the regex matches. Returns `false` otherwise.

A regex created with the global flag is stateful. See the
[RegExp](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) documentation for details.

**Example**

```javascript
const createRegex = require('createRegex');
const testRegex = require('testRegex');

const domainRegex = createRegex('\\w+\\.com', 'i');

// createRegex returns null if the regex is invalid or Re2 is not available.
if (domainRegex === null) return;

// Returns true
testRegex(domainRegex, 'example.com/foobar');
```

**Syntax**

```javascript
testRegex(regex, string);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`regex`** | *Object* | The regex to test against, returned from createRegex API. |
| **`string`** | *string* | Test string to test. |

**Associated permissions**

None.

*** ** * ** ***

## `toBase64`

Encodes a string as base64 or base64url. Defaults to base64 encoding.

**Syntax**

```javascript
toBase64(input, options);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`input`** | *string* | String to encode. |
| **`options`** | *object* | *Optional* API configuration. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#toBase64_options) below.) |

**Options**

| Option | Type | Description | Minimum version |
|---|---|---|---|
| **`urlEncoding`** | *boolean* | If true, the result will be encoded using `base64url` format. | [1.0.0](https://developers.google.com/tag-platform/tag-manager/server-side/release-notes.md.txt#1.0.0) |

**Example**

```javascript
const toBase64 = require('toBase64');

const base64Hello = toBase64('hello');
const base64UrlHello = toBase64('hello', {urlEncoding: true});
```

**Associated permissions**

None.

*** ** * ** ***

## `BigQuery`

Returns an object that provides BigQuery functions.

The `BigQuery.insert` function allows writing data into a BigQuery table. It
returns a [promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise) that resolves upon a successful insertion or
rejects upon an error.

When the insertion succeeds, the promise resolves with no arguments.

When the insertion fails, the promise rejects with a list of objects containing
the error reason and possibly a row object if an error occurs. It's possible for
a part of the request to be completed successfully, while other parts are not.
The promise is rejected in this case with a list of errors for each row with a
row object to help distinguish which rows were inserted
(See [Error Examples](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#bigquery_error_examples) below). See
BigQuery's documentation on
[error
messages](https://cloud.google.com/bigquery/docs/error-messages) for more information.

**Syntax**

```javascript
BigQuery.insert(connectionInfo, rows[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`connectionInfo`** | *object* | Defines information required to connect to a BigQuery table. There is one optional parameter and two required parameters: - `projectId` - *Optional* Google Cloud Platform project ID. If omitted, the `projectId` is retrieved from the environment variable `GOOGLE_CLOUD_PROJECT` as long as the [`access_bigquery`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_bigquery) permission setting for the project ID is set to `*` or `GOOGLE_CLOUD_PROJECT`. If the server container is running on Google Cloud, `GOOGLE_CLOUD_PROJECT` will already be set to the Google Cloud project's ID. - `datasetId` - BigQuery Dataset ID. - `tableId` - BigQuery Table ID. |
| **`rows`** | *Array* | The rows to insert into the table. |
| **`options`** | *object* | Optional request options. The supported options are: **ignoreUnknownValues** and **skipInvalidRows** . Unknown option keys are ignored. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#bigquery_options), below.) |

**Options**

| Parameter | Type | Description |
|---|---|---|
| **`ignoreUnknownValues`** | *boolean* | If set to `true`, then accept rows that contain values that do not match the schema. The unknown values are ignored. Defaults to `false`. |
| **`skipInvalidRows`** | *boolean* | If set to `true`, then insert all valid rows of a request, even if invalid rows exist. Defaults to `false`. |

**Error Examples**

A module not found error means that your server container is likely running an
older version of our image that had not included the BigQuery module yet.
Please redeploy your server container with the same settings using our
[deployment script](https://developers.google.com/tag-platform/tag-manager/server-side/app-engine-setup.md.txt#step-2).
The module will be automatically included once the operation finishes.

A non-insertion error typically has one error object with a `reason` key:

```javascript
[{reason: 'invalid'}]
```

An insertion error can contain multiple error objects with an `errors` array
and a `row` object. The following is an example of an error response from
inserting two rows where only one row has an error:

```javascript
[
  {
    "errors": [
      {
        "reason":"invalid"
      }
    ],
    "row": {
      "string_col":"otherString",
      "number_col":-3,
      "bool_col":3
    }
  },
  {
    "errors": [
      {
        "reason":"stopped"
      }
    ],
    "row": {
      "string_col":"stringValue",
      "number_col":5,
      "bool_col:false
    }
  }
]
```

**Example**

```javascript
const BigQuery = require('BigQuery');

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

const rows = [{
  'column1': 'String1',
  'column2': 1234,
}];

const options = {
  'ignoreUnknownValues': true,
  'skipInvalidRows': false,
};

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

**Associated permissions**

[`access_bigquery`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_bigquery)

*** ** * ** ***

## `Firestore`

Returns an object that provides Firestore functions.

This API supports only **Firestore in Native mode** , not **Firestore in
Datastore mode** . Also, the API only supports using [the default database](https://firebase.google.com/docs/firestore/manage-databases#the_default_database).

### `Firestore.read`

The `Firestore.read` function reads data from a Firestore document and
returns a [promise](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#promise) that resolves to an object containing two keys:
`id` and `data`. If the document does not exist, the promise rejects with an
object containing a `reason` key equal to `not_found`.

> [!NOTE]
> **Note:** By default, `Firestore.read` caches its response for the duration of the container execution. To disable caching, see [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_read_options) section below. Caching is automatically disabled during any transaction.

**Syntax**

```javascript
Firestore.read(path[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`path`** | *string* | The path to the document or collection. Must not start or end with a '/'. |
| **`options`** | *object* | *Optional* request options. The supported options are: **projectId** , **disableCache** , and **transaction** . Unknown option keys are ignored. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_read_options), below.) |

**Options**

| Parameter | Type | Description |
|---|---|---|
| **`projectId`** | *string* | *Optional* . Google Cloud Platform project ID. If omitted, the `projectId` is retrieved from the environment variable `GOOGLE_CLOUD_PROJECT` as long as the [`access_firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_firestore) permission setting for the project ID is set to `*` or `GOOGLE_CLOUD_PROJECT`. If the server container is running on Google Cloud, `GOOGLE_CLOUD_PROJECT` will already be set to the Google Cloud project's ID. |
| **`disableCache`** | *boolean* | *Optional*. Determines whether or not to disable the cache. Caching is enabled by default, which will cache the results for the duration of the request. |
| **`transaction`** | *string* | *Optional*. The value retrieved from Firestore.runTransaction(). Marks the operation to be used within a transaction. |

**Example**

```javascript
const Firestore = require('Firestore');

return Firestore.read('collection/document', {
  projectId: 'gcp-cloud-project-id',
}).then((result) => result.data.key, () => undefined);
```

### `Firestore.write`

The `Firestore.write` function writes data to a Firestore document or
collection. If the path is to a collection, a document will be created with a
randomly generated ID. If the path is to a document and it does not exist, it
will be created. This API returns a promise that resolves to the ID of the
document added or modified. If the transaction option is used, the API still
returns a promise, but will not contain the ID since the writes are batched.

**Syntax**

```javascript
Firestore.write(path, input[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`path`** | *string* | The path to the document or collection. Must not start or end with a '/'. |
| **`input`** | *object* | The value to write into the document. If the merge option is set, the API will merge the keys from the input into the document. |
| **`options`** | *object* | *Optional* request options. The supported options are: **projectId** , **merge** , and **transaction** . Unknown option keys are ignored. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_write_options), below.) |

**Options**

| Parameter | Type | Description |
|---|---|---|
| **`projectId`** | *string* | *Optional* . Google Cloud Platform project ID. If omitted, the `projectId` is retrieved from the environment variable `GOOGLE_CLOUD_PROJECT` as long as the [`access_firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_firestore) permission setting for the project ID is set to `*` or `GOOGLE_CLOUD_PROJECT`. If the server container is running on Google Cloud, `GOOGLE_CLOUD_PROJECT` will already be set to the Google Cloud project's ID. |
| **`merge`** | *boolean* | *Optional* . If set to `true`, then merge the keys from the input into the document, otherwise the method will override the whole document. Defaults to `false`. |
| **`transaction`** | *string* | *Optional*. The value retrieved from Firestore.runTransaction(). Marks the operation to be used within a transaction. |

**Example**

```javascript
const Firestore = require('Firestore');

const input = {key1: 'value1', key2: 12345};

Firestore.write('collection/document', input, {
  projectId: 'gcp-cloud-project-id',
  merge: true,
}).then((id) => {
  data.gtmOnSuccess();
}, data.gtmOnFailure);
```

### `Firestore.query`

The `Firestore.query` function queries the given collection and returns a
promise that resolves to an array of Firestore documents that match the query
conditions. The Firestore document object is the same as listed above in
`Firestore.read`. If there are no documents that match the query conditions,
the returned promise will resolve to an empty array.

> [!NOTE]
> **Note:** By default, `Firestore.query` caches its response for the duration of the container execution. To disable caching, see [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_query_options) section below. Caching is automatically disabled during any transaction.

> [!NOTE]
> **Note:** Firestore automatically creates an index for each individual field. In order to query on multiple fields, a composite index might need to be created for the specified collection. For more information, please see [Firestore's documentation on composite indexes](https://firebase.google.com/docs/firestore/query-data/index-overview#composite_indexes).

**Syntax**

```javascript
Firestore.query(collection, queryConditions[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`collection`** | *string* | The path to the collection. Must not start or end with a '/'. |
| **`queryConditions`** | *Array* | An array of query conditions. Each query comes in the form of an array with three values: **key** , **operator** , and **expectedValue** . E.g.: \[\['id', '\<', '5'\], \['state', '==', 'CA'\]\]. The conditions are ANDed together to create the query result. Please refer to [Firestore's query operators](https://firebase.google.com/docs/firestore/query-data/queries#query_operators) for a list of compatible query operators. |
| **`options`** | *object* | *Optional* request options. The supported options are: **projectId** , **disableCache** , **limit** , and **transaction** . Unknown option keys are ignored. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_query_options), below.) |

**Options**

| Parameter | Type | Description |
|---|---|---|
| **`projectId`** | *string* | *Optional* . Google Cloud Platform project ID. If omitted, the `projectId` is retrieved from the environment variable `GOOGLE_CLOUD_PROJECT` as long as the [`access_firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_firestore) permission setting for the project ID is set to `*` or `GOOGLE_CLOUD_PROJECT`. If the server container is running on Google Cloud, `GOOGLE_CLOUD_PROJECT` will already be set to the Google Cloud project's ID. |
| **`disableCache`** | *boolean* | *Optional*. Determines whether or not to disable the cache. Caching is enabled by default, which will cache the results for the duration of the request. |
| **`limit`** | *number* | *Optional* . Changes the maximum number of results returned by the query, defaults to **5**. |
| **`transaction`** | *string* | *Optional*. The value retrieved from Firestore.runTransaction(). Marks the operation to be used within a transaction. |

**Example**

```javascript
const Firestore = require('Firestore');

const queries = const queries = [['id', '==', '5']];

return Firestore.query('collection', queries, {
  projectId: 'gcp-cloud-project-id',
  limit: 1,
}).then((documents) => documents[0].data.key, () => undefined);
```

### `Firestore.runTransaction`

The `Firestore.runTransaction` function allows the user to atomically
read and write from Firestore. If a concurrent write or another transaction
conflict happens, the transaction will be retried up to two times. If it fails
after three total attempts, the API will reject with an error. This API returns
a promise that resolves to an array of document IDs, for each write operation,
if the transaction is successful, and will reject with the error if it fails.

**Syntax**

```javascript
Firestore.runTransaction(callback[, options]);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`callback`** | *function* | A callback that's invoked with a string transaction ID. The transaction ID can be passed into read/write/query API calls. This callback function **must** return a promise. The callback may run up to three times before failing. |
| **`options`** | *object* | *Optional* request options. The supported only supported option is **projectId** . Unknown option keys are ignored. (See [Options](https://developers.google.com/tag-platform/tag-manager/server-side/api.md.txt#firestore_runtransaction_options), below.) |

**Options**

| Parameter | Type | Description |
|---|---|---|
| **`projectId`** | *string* | *Optional* . Google Cloud Platform project ID. If omitted, the `projectId` is retrieved from the environment variable `GOOGLE_CLOUD_PROJECT` as long as the [`access_firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_firestore) permission setting for the project ID is set to `*` or `GOOGLE_CLOUD_PROJECT`. If the server container is running on Google Cloud, `GOOGLE_CLOUD_PROJECT` will already be set to the Google Cloud project's ID. |

**Example**

```javascript
const Firestore = require('Firestore');

const path = 'collection/document';
const projectId = 'gcp-cloud-project-id';

Firestore.runTransaction((transaction) => {
  const transactionOptions = {
    projectId: projectId,
    transaction: transaction,
  };
  // Must return a promise.
  return Firestore.read(path, transactionOptions).then((result) => {
    const newInputCount = result.data.inputCount + 1;
    const input = {key1: 'value1', inputCount: newInputCount};
    return Firestore.write(path, input, transactionOptions);
  });
}, {
  projectId: projectId
}).then((ids) => {
  data.gtmOnSuccess();
}, data.gtmOnFailure);
```

**Error Example**

Errors are available in each Firestore function will be rejected with an object
containing a `reason` key:

```javascript
Firestore.read(...).then(onSuccess, (error) => {
  if (error.reason === 'unknown') {
    // Handle the unknown error here.
  }
});
```

The error reasons can contain but are not limited to [Firestore REST API Error
Codes](https://firebase.google.com/docs/firestore/use-rest-api#error_codes).

**Associated permissions**

[`access_firestore`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#access_firestore)

*** ** * ** ***

## `JSON`

Returns an object that provides JSON functions.

The `parse()` function parses a JSON string to construct the value or object
described by the string. If the value cannot be parsed (e.g. malformed JSON),
the function will return `undefined`. If the input value is not a string, the
input will be coerced to a string.

The `stringify()` function converts the input into a JSON string. If the value
cannot be parsed (e.g. the object has a cycle), the method will return
`undefined`.

**Example**

```javascript
const JSON = require('JSON');

// The JSON input string is converted to an object.
const object = JSON.parse('{"foo":"bar"}');

// The input object is converted to a JSON string.
const str = JSON.stringify({foo: 'bar'});
```

**Syntax**

```javascript
JSON.parse(stringInput);
JSON.stringify(value);
```

**Associated permissions**

None.

*** ** * ** ***

## `Math`

An object providing `Math` functions.

**Syntax**

```javascript
const Math = require('Math');

// Retrieve the absolute value.
const absolute = Math.abs(-3);

// Round the input down to the nearest integer.
const roundedDown = Math.floor(3.6);

// Round the input up to the nearest integer.
const roundedUp = Math.ceil(2.2);

// Round the input to the nearest integer.
const rounded = Math.round(3.1);

// Return the largest argument.
const biggest = Math.max(1, 3);

// Return the smallest argument.
const smallest = Math.min(3, 5);

// Return the first argument raised to the power of the second argument.
const powerful = Math.pow(3, 1);

// Return the square root of the argument.
const unsquared = Math.sqrt(9);
```

**Parameters**

Math function parameters are converted to numbers.

**Associated permissions**

None.

*** ** * ** ***

## `Messages`

The following APIs work together to allow passing messages between different
parts of a container.

*** ** * ** ***

### `addMessageListener`

Adds a function that listens for a message of a particular type. When a message
of that type is sent using the `sendMessage` API (typically by a tag), the
callback will be run synchronously. The callback is run with two parameters:

1. `messageType:string`
2. `message:Object`

If the callback is added in a client, the callback will receive messages across
all of the events that client creates. If the callback should receive messages
from only a certain event, then bind this API to the event using `bindToEvent`
in the `runContainer` API's `onStart` function. See the example.

**Syntax**

```javascript
const addMessageListener = require('addMessageListener');

addMessageListener('send_pixel', (messageType, message) => {
  // This will be run whenever something sends a 'send_pixel' message.
});
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`messageType`** | *string* | The message type to listen for. If the value is not a string, it will be coerced to a string. |
| **`callback`** | *function* | The callback to run when a message of the applicable message type is sent. If the callback is not a function, the API will do nothing. |

**Example**

```javascript
const addMessageListener = require('addMessageListener');
const claimRequest = require('claimRequest');
const extractEventsFromMpv1 = require('extractEventsFromMpv1');
const returnResponse = require('returnResponse');
const runContainer = require('runContainer');

claimRequest();
addMessageListener('send_pixel', (messageType, message) => {
  // This will be run whenever a tag sends a 'send_pixel' message.
});

const events = extractEventsFromMpv1();
let eventsCompleted = 0;
events.forEach((event, i) => {
  runContainer(events[i], /* onComplete= */ () => {
    if (events.length === ++eventsCompleted) {
      returnResponse();
    }
  }, /* onStart= */ (bindToEvent) => {
    if (i === 0) {
      bindToEvent(addMessageListener)('send_pixel', (messageType, message) => {
        // This will be called whenever a tag for the first event sends a
        // 'send_pixel' message.
      });
    }
  });
});
```

**Associated permissions**

Requires [`use_message`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#use_message) permission. The permission must be configured to permit
at least:

- A message type with `Usage` of `listen` or `listen_and_send`.

*** ** * ** ***

### `hasMessageListener`

Returns true if a message listener has been added for the given message type.
Returns false otherwise.

**Syntax**

```javascript
const hasMessageListener = require('hasMessageListener');

hasMessageListener('send_pixel');
```

**Associated permissions**

None.

*** ** * ** ***

### `sendMessage`

Sends a message of the specified type to a registered listener. This can be used
to send messages from a tag back to the client that ran the container.

**Syntax**

```javascript
const sendMessage = require('sendMessage');

sendMessage('send_pixel', {url: 'https://analytics.example.com/collect'});
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`messageType`** | *string* | The message type to send. If the value is not a string, it will be coerced to a string. |
| **`message`** | *object* | The message to send. If the message is not an object, the API will do nothing. |

**Associated permissions**

Requires [`use_message`](https://developers.google.com/tag-platform/tag-manager/server-side/permissions.md.txt#use_message) permission. The permission must be configured to permit
at least:

- A message type with `Usage` of `listen_and_send` or `send`.

*** ** * ** ***

## `Object`

Returns an object that provides `Object` methods.

The `keys()` method provides the Standard Library [Object.keys()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/keys)
behavior. It returns an array of a given object's own enumerable property
names in the same order that a `for...in...` loop would. If the input value is
not an object, it will be coerced to an object.

The `values()` method provides the Standard Library [Object.values()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/values)
behavior. It returns an array of a given object's own enumerable property values
in the same order that a `for...in...` loop would. If the input value is not an
object, it will be coerced to an object.

The `entries()` method provides the Standard Library [Object.entries()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/entries)
behavior. It returns an array of a given object's own enumerable property
`[key, value]` pairs in the same order that a `for...in...` loop would. If the
input value is an not an object, it will be coerced to an object.

The `freeze()` method provides the Standard Library [Object.freeze()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
behavior. A frozen object can no longer be changed; freezing an object prevents
new properties from being added to it, existing properties from being removed,
and the values of existing properties from being changed. `freeze()` returns the
same object that was passed in. A primitive or null argument will be treated as
if it were a frozen object, and will be returned.

The `delete()` method provides the Standard Library [delete operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/delete)
behavior. It removes the given key from the object unless the object is frozen.
Like the Standard Library delete operator, it returns `true` if the first input
value (`objectInput`) is an object that is not frozen even if the second input
value (`keyToDelete`) specifies a key that does not exist. It returns `false` in
all other cases. However, it differs from the Standard Library delete operator
in the following ways:

- `keyToDelete` cannot be a dot-delimited string that specifies a nested key.
- `delete()` cannot be used to remove elements from an array.
- `delete()` cannot be used to remove any properties from the global scope.

**Syntax**

```javascript
Object.keys(objectInput)
Object.values(objectInput)
Object.entries(objectInput)
Object.freeze(objectInput)
Object.delete(objectInput, keyToDelete)
```

**Parameters**

***Object.keys***

| Parameter | Type | Description |
|---|---|---|
| objectInput | *any* | The object whose keys to enumerate. If the input is not an object, it will be coerced to an object. |

***Object.values***

| Parameter | Type | Description |
|---|---|---|
| objectInput | *any* | The object whose values to enumerate. If the input is not an object, it will be coerced to an object. |

***Object.entries***

| Parameter | Type | Description |
|---|---|---|
| objectInput | *any* | The object whose key/value pairs to enumerate. If the input is not an object, it will be coerced to an object. |

***Object.freeze***

| Parameter | Type | Description |
|---|---|---|
| objectInput | *any* | The object to freeze. If the input is not an object, it will be treated as a frozen object. |

***Object.delete***

| Parameter | Type | Description |
|---|---|---|
| objectInput | *any* | The object whose key to delete. |
| keyToDelete | *string* | The top-level key to delete. |

**Example**

```javascript
const Object = require('Object');

// The keys of an object are enumerated in an array.
const keys = Object.keys({foo: 'bar'});

// The values of an object are enumerated in an array.
const values = Object.values({foo: 'bar'});

// The key/value pairs of an object are enumerated in an array.
const entries = Object.entries({foo: 'bar'});

// The input object is frozen.
const frozen = Object.freeze({foo: 'bar'});

// The key is removed from the input object.
const obj1 = {deleteme: 'value'};
Object.delete(obj1, 'deleteme');
// Only a top-level key can be specified as the key to delete.
const obj2 = {nested: {key: 'value'}};
Object.delete(obj2, 'nested.key'); // This has no effect.
Object.delete(obj2.nested, 'key'); // This deletes the nested key.
```

*** ** * ** ***

## `Promise`

Returns an object that provides methods for interacting with promises.

Promises are functionally equivalent to JavaScript promises. Each instance has
three methods that return a Promise which allows further action when a promise
settles:

- `.then()` - Handles both the resolved and rejected cases. It takes two callbacks as parameters: one for the success case and one for the failure case.
- `.catch()` - Handles the rejected cases only. Takes one callback as a parameter.
- `.finally()` - Provides a way for code to be run whether the promise was resolved or rejected. Takes one callback as a parameter that is invoked with no argument.

A variable that returns a promise equals the resolved value of the promise, or
`false` if the promise rejects.

> [!NOTE]
> **Note:** A Sandboxed JS promise times out (rejects) after five seconds if it has not resolved.

**Example**

```javascript
promise.then((resolvedValue) => {
    // Handles when promise resolves.
  }, (rejectedValue) => {
    // Handles when promise rejects.
  });
promise.catch((rejectedValue) => {
    // Handles when promise rejects.
  });
promise.finally(() => {
    // Runs regardless of whether or not the previous promise resolves or
    // rejects.
  });
```

### `Promise.all`

Returns a promise that either:

- resolves when all the inputs have resolved, or
- rejects when any of the inputs reject

**Syntax**

```javascript
Promise.all(inputs);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`inputs`** | *Array* | An array of values or promises. If an input is not a promise, the input is passed through as if it's the resolved value of a promise. Throws an error if the input is not an array. |

**Example**

```javascript
const Promise = require('Promise');
const sendHttpGet = require('sendHttpGet');

return Promise.all(['a', sendHttpGet('https://example.com')])
  .then((results) => {
    // results will equal: ['a', {statusCode: 200, headers: {}, body: ''}]
  });
```

**Associated permissions**

None.

### `Promise.create`

Creates a promise that is functionally equivalent to a JavaScript promise.

**Syntax**

```javascript
Promise.create(resolver);
```

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`resolver`** | *function* | A function that is invoked with two functions -- resolve and reject. The returned promise will resolve or reject when the corresponding parameter is invoked. Throws an error if resolver is not a function. |

**Example**

```javascript
const Promise = require('Promise');

return Promise.create((resolve, reject) => {
  // Do asynchronous work that eventually calls resolve() or reject()
});
```

**Associated permissions**

None.

## Test APIs

These APIs work with sandboxed JavaScript tests to build tests for custom
templates in Google Tag Manager. These test APIs do not need a `require()`
statement. \[Learn more about custom template tests\].

*** ** * ** ***

### `assertApi`

Returns a matcher object that can be used to fluently make assertions about the
given API.

**Syntax**

`assertApi(apiName)`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`apiName`** | *string* | The name of the api to check; same string as passed to [`require()`](https://developers.google.com/tag-platform/tag-manager/templates/api.md.txt#require). |

**Matchers**

- `Subject.wasCalled()`
- `Subject.wasNotCalled()`
- `Subject.wasCalledWith(...expected)`
- `Subject.wasNotCalledWith(...expected)`

**Examples**

```javascript
assertApi('sendPixel').wasCalled();
assertApi('getUrl').wasNotCalled();
assertApi('makeNumber').wasCalledWith('8');
assertApi('setInWindow').wasNotCalledWith('myVar', 'theWrongValue');
```

*** ** * ** ***

### `assertThat`

The `assertThat` API is modeled after Google's \[Truth\] library. It returns an
object that can be used to fluently make assertions about a subject's value. An
assertion failure will immediately stop the test and mark it as failed. However,
a failure in one test will not affect other test cases.

**Syntax**

`assertThat(actual, opt_message)`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`actual`** | *any* | The value to use in the fluent checks. |
| **`opt_message`** | *string* | Optional message to print if the assertion fails. |

**Matchers**

| Matcher | Description |
|---|---|
| **`isUndefined()`** | Asserts that the subject is `undefined`. |
| **`isDefined()`** | Asserts that the subject is not `undefined`. |
| **`isNull()`** | Asserts that the subject is `null`. |
| **`isNotNull()`** | Asserts that the subject is not `null`. |
| **`isFalse()`** | Asserts that the subject is `false`. |
| **`isTrue()`** | Asserts that the subject is `true`. |
| **`isFalsy()`** | Asserts that the subject is falsy. Falsy values are `undefined`, `null`, `false`, `NaN`, 0, and '' (empty string). |
| **`isTruthy()`** | Asserts that the subject is truthy. Falsy values are `undefined`, `null`, `false`, `NaN`, 0, and '' (empty string). |
| **`isNaN()`** | Asserts that the subject is the value NaN. |
| **`isNotNaN()`** | Asserts that the subject is any value besides NaN. |
| **`isInfinity()`** | Asserts that the subject is positive or negative Infinity. |
| **`isNotInfinity()`** | Asserts that the subject is any value besides positive or negative Infinity. |
| **`isEqualTo(expected)`** | Asserts that the subject is equal to the given value. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`isNotEqualTo(expected)`** | Asserts that the subject is not equal to the given value. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`isAnyOf(...expected)`** | Asserts that the subject is equal to one of the given value. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`isNoneOf(...expected)`** | Asserts that the subject is not equal to any of the given values. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`isStrictlyEqualTo(expected)`** | Asserts that the subject is strictly equal (`===`) to the given value. |
| **`isNotStrictlyEqualTo(expected)`** | Asserts that the subject is not strictly equal (`!==`) to the given value. |
| **`isGreaterThan(expected)`** | Asserts that the subject is greater than (`>`) the given value in an ordered comparison. |
| **`isGreaterThanOrEqualTo(expected)`** | Asserts that the subject is greater than or equal to (`>=`) the given value in an ordered comparison. |
| **`isLessThan(expected)`** | Asserts that the subject is less than (`<`) the given value in an ordered comparison. |
| **`isLessThanOrEqualTo(expected)`** | Asserts that the subject is less than or equal to (`<=`) the given value in an ordered comparison. |
| **`contains(...expected)`** | Asserts that the subject is an array or string that contains all of the given values in any order. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`doesNotContain(...expected)`** | Asserts that the subject is an array or string that contains none of the given values. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`containsExactly(...expected)`** | Asserts that the subject is an array that contains all of the given values in any order and no other values. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`doesNotContainExactly(...expected)`** | Asserts that the subject is an array that has contains a different set of values from the given values in any order. This is a value comparison, not a reference comparison. The contents of objects and arrays are compared recursively. |
| **`hasLength(expected)`** | Asserts that the subject is an array or string with the given length. The assertion always fails if the value is not an array or string. |
| **`isEmpty()`** | Asserts that the subject is an array or string that is empty (length = 0). The assertion always fails if the value is not an array or string. |
| **`isNotEmpty()`** | Asserts that the subject is an array or string that is not empty (length \> 0). The assertion always fails if the value is not an array or string. |
| **`isArray()`** | Asserts that the type of the subject is an array. |
| **`isBoolean()`** | Asserts that the type of the subject is a boolean. |
| **`isFunction()`** | Asserts that the type of the subject is a function. |
| **`isNumber()`** | Asserts that the type of the subject is a number. |
| **`isObject()`** | Asserts that the type of the subject is an object. |
| **`isString()`** | Asserts that the type of the subject is a string. |

**Examples**

```javascript
assertThat(undefined).isUndefined();
assertThat(id, 'ID must be defined').isDefined();
assertThat(null).isNull();
assertThat(undefined).isNotNull();
assertThat(true).isTrue();
assertThat(false).isFalse();
assertThat(1).isTruthy();
assertThat('').isFalsy();
assertThat(1/0).isInfinity();
assertThat(0).isNotInfinity();
assertThat(-'foo').isNaN();
assertThat(100).isNotNaN();
assertThat(sentUrl).isEqualTo('https://endpoint.example.com/?account=12345');
assertThat(category).isNotEqualTo('premium');
assertThat(5).isAnyOf(1, 2, 3, 4, 5);
assertThat(42).isNoneOf('the question', undefined, 41.9);
assertThat('value').isStrictlyEqualTo('value');
assertThat('4').isNotStrictlyEqualTo(4);
assertThat(['a', 'b', 'c']).contains('a', 'c');
assertThat(['x', 'y', 'z']).doesNotContain('f');
assertThat(['1', '2', '3']).containsExactly('3', '2', '1');
assertThat(['4', '5']).doesNotContainExactly('4');
assertThat('a string').hasLength(8);
assertThat([]).isEmpty();
assertThat('another string').isNotEmpty();
```

*** ** * ** ***

### `fail`

Immediately fails the current test and prints the given message, if supplied.

**Syntax**

`fail(opt_message);`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`opt_message`** | *string* | Optional error message text. |

**Example**

```javascript
fail('This test has failed.');
```

*** ** * ** ***

### `mock`

The `mock` API allows you to override the behavior of Sandboxed APIs. The mock
API is safe to use in template code, but it is operational only in test mode.
Mocks are reset before each test is run.

**Syntax**

`mock(apiName, returnValue);`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`apiName`** | *string* | The name of the API to mock; same string as passed to `require()` |
| **`returnValue`** | *any* | The value to return for the API or a function called in place of the API. If `returnValue` is a function, that function is called in place of the Sandboxed API; if `returnValue` is anything other than a function, that value is returned in place of the Sandboxed API. |

**Examples**

```javascript
mock('encodeUri', "https://endpoint.example.com/?account=12345");
mock('sendPixel', function(url, onSuccess, onFailure) {
    onSuccess();
});
```

*** ** * ** ***

### `mockObject`

The `mockObject` API lets you override the behavior of Sandboxed APIs that
return an object. The API is safe to use in template code, but it is operational
only in test mode. Mocks are reset before each test is run.

**Syntax**

`mockObject(apiName, objectMock);`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`apiName`** | *string* | The name of the API to mock; same string as passed to `require()` |
| **`objectMock`** | *object* | The value to return for the API or a function called in place of the API. Must be an object. |

**Examples**

```javascript
const storage = {};
let firestoreId = 1;

function asTestPromise(result) {
  return {
    then: (callback) => callback(result)
  };
}

mockObject('Firestore', {
  write: (collection, input) => {
    storage[collection + '/' + (++firestoreId)] = input;
    return asTestPromise(firestoreId);
  },
  read: (document) => asTestPromise({data: storage[document]})
});
```

*** ** * ** ***

### `runCode`

Runs the code for the template, i.e. the content of the **Code** tab, in the
current test environment with a given input data object.

**Syntax**

`runCode(data)`

**Parameters**

| Parameter | Type | Description |
|---|---|---|
| **`data`** | *object* | Data object to be used in the test. |

**Return Value**

Returns the value of a variable for variable templates; returns `undefined` for
all other template types.

**Example**

```javascript
runCode({field1: 123, field2: 'value'});
```

*** ** * ** ***