Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:45 +08:00
commit c02dafae1d
41 changed files with 17283 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,357 @@
# Sandboxed JavaScript API Reference
This is the complete Sandboxed JavaScript API reference for Google Tag Manager custom templates. These APIs enable you to build powerful custom templates while maintaining security and performance standards.
Source: https://developers.google.com/tag-platform/tag-manager/templates/api
## API Categories
### Core APIs
These APIs work with sandboxed JavaScript to build custom templates in Google Tag Manager.
#### Consent Management
- **addConsentListener(consentType, listener)** → void
- Registers a listener function to execute when the state of the specified consent type changes.
- **isConsentGranted(consentType)** → boolean
- Returns true if the specified consent type is granted.
- **setDefaultConsentState(consentSettings)** → void
- Pushes a default consent update to the data layer.
- **updateConsentState(consentSettings)** → void
- Pushes a consent update to the data layer.
#### Event Handling
- **addEventCallback(callback)** → void
- Allows you to register a callback function that will be invoked at the end of an event.
- **callLater(function)** → void
- Schedules a call to a function to occur asynchronously.
#### Window and Global Object Access
- **aliasInWindow(toPath, fromPath)** → boolean
- Lets you create an alias (e.g. window.foo = window.bar).
- **callInWindow(pathToFunction, args)** → *
- Allows you to call functions from a path off the window object, in a policy-controlled way.
- **copyFromWindow(key)** → *
- Copies a variable from window object.
- **setInWindow(key, value, overrideExisting)** → boolean
- Sets the given value in window at the given key.
#### Queue and Array Creation
- **createArgumentsQueue(fnKey, arrayKey)** → function
- Creates a queue that is populated with argument objects, in support of tag solutions that require it.
- **createQueue(arrayKey)** → function
- Creates an array in window and returns a function that will push values onto that array.
#### URI and Encoding
- **decodeUri(encoded_uri)** → string
- Decodes any encoded characters in the provided URI.
- **decodeUriComponent(encoded_uri_component)** → string
- Decodes any encoded characters in the provided URI component.
- **encodeUri(uri)** → string
- Returns an encoded Uniform Resource Identifier (URI) by escaping special characters.
- **encodeUriComponent(str)** → string
- Returns an encoded Uniform Resource Identifier (URI) by escaping special characters.
- **fromBase64(base64EncodedString)** → string
- Lets you decode strings from their base64 representation.
- **toBase64(input)** → string
- Lets you encode a string into a base64 representation.
#### Utility Functions
- **generateRandom(min, max)** → number
- Returns a random number (integer) within the given range.
- **getContainerVersion()** → object
- Returns an object containing data about the current container.
- **getType(value)** → string
- Returns a string describing the given value's type.
- **logToConsole(obj1, obj2, ...)** → void
- Logs arguments to the browser console.
- **makeInteger(value)** → number
- Converts the given value to a number (integer).
- **makeNumber(value)** → number
- Converts the given value to a number.
- **makeString(value)** → string
- Returns the given value as a string.
- **makeTableMap(tableObj, keyColumnName, valueColumnName)** → object
- Converts a simple table object with two columns to a Map.
- **queryPermission(permission, functionArgs)** → boolean
- Query the allowed and narrowed permissions.
- **require(name)** → function
- Imports a built-in function by name.
#### Data Layer Access
- **copyFromDataLayer(key, dataLayerVersion)** → *
- Returns the value currently assigned to the given key in the data layer.
- **gtagSet(object)** → void
- Pushes a gtag set command to the data layer.
#### Cookie Management
- **getCookieValues(name, decode)** → array
- Returns the values of all cookies with the given name.
- **setCookie(name, value, options, encode)** → void
- Sets or deletes the cookie with the specified name, value, and options.
#### URL and Query Parameters
- **getQueryParameters(queryKey, retrieveAll)** → *
- Returns the first or all of the parameters for the current URL's queryKey.
- **getUrl(component)** → string
- Returns a string that represents all or a portion of the current URL.
- **parseUrl(url)** → object
- Returns an object that contains all of a given URL's component parts.
- **getReferrerUrl(component)** → string
- Reads the document object for the referrer and returns a string that represents a portion of the referrer.
- **getReferrerQueryParameters(queryKey, retrieveAll)** → *
- Acts the same way as getQueryParameters, except it acts on the referrer instead of the current URL.
#### Time Management
- **getTimestamp()** → number
- Returns a number that represents the current time in milliseconds since Unix epoch.
- **getTimestampMillis()** → number
- Returns a number that represents the current time in milliseconds since Unix epoch.
#### Network and Injection
- **injectHiddenIframe(url, onSuccess)** → void
- Adds an invisible iframe to the page.
- **injectScript(url, onSuccess, onFailure, cacheToken)** → void
- Adds a script tag to the page to load the given URL asynchronously.
- **sendPixel(url, onSuccess, onFailure)** → void
- Makes a GET request to a specified URL endpoint.
- **sha256(input, onSuccess, onFailure, options)** → void
- Calculates the SHA-256 digest of the input.
#### Document Reading
- **readCharacterSet()** → string
- Returns the value of document.characterSet.
- **readTitle()** → string
- Returns the value of document.title.
- **readAnalyticsStorage(cookieOptions)** → object
- Retrieves the data stored for analytics and returns an object with client_id and sessions.
#### Built-in Objects
- **JSON** → object
- Returns an object that provides JSON functions.
- **Math** → object
- An object providing Math functions.
- **Object** → object
- Returns an object that provides Object methods.
- **localStorage** → object
- Returns an object with methods for accessing local storage.
- **templateStorage** → object
- Returns an object with methods for accessing template storage.
---
### Test APIs
These APIs work with sandboxed JavaScript tests to build tests for custom templates in Google Tag Manager.
#### Assertions and Validation
- **assertApi(apiName)** → object
- Returns a matcher object that can be used to fluently make assertions about the given API.
- **assertThat(actual, opt_message)** → object
- Returns an object that can be used to fluently make assertions about a subject's value.
- **fail(opt_message)** → void
- Immediately fails the current test and prints the given message, if supplied.
#### Mocking
- **mock(apiName, returnValue)** → void
- Allows you to override the behavior of Sandboxed APIs.
- **mockObject(apiName, objectMock)** → void
- Lets you override the behavior of Sandboxed APIs that return an object.
#### Test Execution
- **runCode(data)** → *
- Runs the code for the template in the current test environment.
---
## API Summary
**Total Core APIs**: 49 functions across 13 categories
**Total Test APIs**: 6 functions across 3 categories
**Total APIs**: 55 functions
### Core API Categories
1. Consent Management (4 functions)
2. Event Handling (2 functions)
3. Window and Global Object Access (4 functions)
4. Queue and Array Creation (2 functions)
5. URI and Encoding (6 functions)
6. Utility Functions (8 functions)
7. Data Layer Access (2 functions)
8. Cookie Management (2 functions)
9. URL and Query Parameters (5 functions)
10. Time Management (2 functions)
11. Network and Injection (4 functions)
12. Document Reading (3 functions)
13. Built-in Objects (5 functions)
### Test API Categories
1. Assertions and Validation (3 functions)
2. Mocking (2 functions)
3. Test Execution (1 function)
---
## Usage Examples
### Working with the Data Layer
```javascript
// Get a value from the data layer
var userId = copyFromDataLayer('userId');
// Push a gtag set command
gtagSet({
'event': 'page_view',
'page_title': readTitle()
});
```
### Managing Cookies
```javascript
// Get cookie values
var cookieValues = getCookieValues('tracking_id', true);
// Set a cookie
setCookie('my_cookie', 'value123', {
'domain': 'example.com',
'path': '/',
'max-age': 86400
});
```
### Working with URLs
```javascript
// Get URL components
var hostname = getUrl('hostname');
var pathname = getUrl('pathname');
var queryString = getUrl('query');
// Parse a URL
var urlParts = parseUrl('https://example.com/page?param=value');
// Get query parameters
var userParam = getQueryParameters('user_id', false);
```
### Async Operations
```javascript
// Inject a script
injectScript('https://example.com/tracker.js', function() {
logToConsole('Script loaded successfully');
}, function() {
logToConsole('Script failed to load');
});
// Send a pixel
sendPixel('https://example.com/track?event=purchase', function() {
logToConsole('Pixel sent');
}, function() {
logToConsole('Pixel failed');
});
// Calculate SHA-256
sha256('input_string', function(result) {
logToConsole('SHA-256: ' + result);
}, function() {
logToConsole('Hash calculation failed');
});
```
### Consent Management
```javascript
// Check if consent is granted
if (isConsentGranted('analytics_storage')) {
// Proceed with analytics
}
// Add a consent listener
addConsentListener('analytics_storage', function() {
logToConsole('Consent state changed');
});
// Update consent
updateConsentState({
'analytics_storage': 'granted',
'ad_storage': 'denied'
});
```
### Testing Custom Templates
```javascript
// Mock an API
mock('sendPixel', undefined);
// Assert API behavior
assertApi('sendPixel').wasCalled();
// Run template code with test data
var result = runCode({
'event': 'test_event',
'user_id': '12345'
});
```
---
## Reference
- **Official Documentation**: https://developers.google.com/tag-platform/tag-manager/templates/api
- **Google Tag Manager**: https://tagmanager.google.com
- **GTM Custom Templates Guide**: https://developers.google.com/tag-platform/tag-manager/templates/guide

View File

@@ -0,0 +1,149 @@
# Custom Template Examples
<!-- To be populated with practical examples -->
## Tag Template Examples
### Simple Pixel Tag Template
```javascript
// Code section
const sendPixel = require('sendPixel');
const encodeUriComponent = require('encodeUriComponent');
const getUrl = require('getUrl');
const pixelUrl = 'https://example.com/pixel?'
+ 'page=' + encodeUriComponent(getUrl())
+ '&event=' + encodeUriComponent(data.eventName);
sendPixel(pixelUrl, data.gtmOnSuccess, data.gtmOnFailure);
```
### HTTP Request Tag Template
```javascript
// Code section
const sendHttpRequest = require('sendHttpRequest');
const JSON = require('JSON');
const postBody = JSON.stringify({
event: data.eventName,
userId: data.userId,
timestamp: Date.now()
});
const options = {
headers: {'Content-Type': 'application/json'},
method: 'POST',
};
sendHttpRequest(data.endpoint, options, postBody)
.then(data.gtmOnSuccess)
.catch(data.gtmOnFailure);
```
## Variable Template Examples
### Cookie Variable Template
```javascript
// Code section
const getCookieValues = require('getCookieValues');
const cookieName = data.cookieName;
const cookies = getCookieValues(cookieName);
if (cookies.length > 0) {
return cookies[0];
}
return data.defaultValue;
```
### LocalStorage Variable Template
```javascript
// Code section
const localStorage = require('localStorage');
const key = data.localStorageKey;
return localStorage.getItem(key) || data.defaultValue;
```
### Custom JavaScript Function Variable
```javascript
// Code section
const makeTableMap = require('makeTableMap');
const lookupTable = makeTableMap(data.tableInput, 'input', 'output');
const inputValue = data.inputVariable;
return lookupTable[inputValue] || data.defaultValue;
```
## Common Patterns
### Error Handling
```javascript
const sendHttpRequest = require('sendHttpRequest');
const logToConsole = require('logToConsole');
sendHttpRequest(url, options)
.then(response => {
logToConsole('Success:', response);
data.gtmOnSuccess();
})
.catch(error => {
logToConsole('Error:', error);
data.gtmOnFailure();
});
```
### Conditional Logic
```javascript
const getType = require('getType');
if (getType(data.value) === 'undefined') {
return data.defaultValue;
}
if (data.value > 0) {
return 'positive';
} else if (data.value < 0) {
return 'negative';
} else {
return 'zero';
}
```
### Data Validation
```javascript
const makeNumber = require('makeNumber');
const makeString = require('makeString');
// Validate and convert input
const numericValue = makeNumber(data.inputValue);
if (numericValue === undefined) {
logToConsole('Invalid numeric input');
data.gtmOnFailure();
return;
}
// Continue with validated value
const result = numericValue * 2;
data.gtmOnSuccess();
```
## Placeholder for Additional Examples
This file will be enhanced with:
- Server-side client template examples
- Complex permission configurations
- Field validation patterns
- Real-world use cases
- Community template patterns
**Status**: ⚠️ To be enhanced with documentation extraction

View File

@@ -0,0 +1,96 @@
# Tests
**Source**: https://developers.google.com/tag-platform/tag-manager/templates/tests
**Extracted**: 2025-01-09
## Overview
Unit tests for Google Tag Manager custom templates help you validate the functionality of your templates. You can create a set of tests for each template that can be run without needing to deploy your tag, which allows you to continuously test your template's behavior during development. Each test can provide sample input values, mock function calls, and assert code behavior.
## Limitations
- Unit tests do not check validation rules but you can manually check validation using the **Run Code** button.
- Permission checks do not happen on mocked APIs in unit tests.
## Step-by-Step Guide: Creating a Variable Template with Tests
This guide creates a variable template that takes an input string and returns the uppercase version of that string.
### Steps 1-3: Create Template and Add Field
1. Create a new variable template. Click **Templates** in the left navigation and click **New** under the **Variable Templates** section.
2. Click **Fields**.
3. Click **Add Field** and select **Text input**. Name the field \`text1\` and set the display name to _"Text 1"_.
### Step 4: Add Template Code
In the **Code** tab, replace the default code with this sandboxed JavaScript:
\`\`\`javascript
let input = data.text1;
return input.toUpperCase();
\`\`\`
### Steps 5-7: Create First Test
5. Click **Tests** to open the testing tab.
6. Click **Add Test** and change the test's name from _"Untitled test 1"_ to _"Handles strings"_.
7. Click on the expand icon to reveal the test's sandboxed JavaScript editor. Replace the code with:
\`\`\`javascript
// Call runCode to run the template's code with a lowercase string
let variableResult = runCode({text1: 'this is a test'});
// Validate that the result of runCode is an uppercase string.
assertThat(variableResult).isEqualTo('THIS IS A TEST');
\`\`\`
This test passes the string \`'this is a test'\` to the variable and verifies that the variable returns the expected value of \`'THIS IS A TEST'\`. The \`runCode\` API is used to run the template code in the **Code** tab. The argument to \`runCode\` is an object that is used as the data global. The \`assertThat\` API returns an object that can be used to fluently make assertions about a subject's value.
### Step 8: Run Tests
Click **▶ Run Tests** to run the test. The output of the test will appear in the Console.
The **▶ Run Tests** button runs all of the enabled tests in the template, in the order shown. To change the order, use the drag icon. A test can be temporarily enabled or disabled by clicking on the circle to the left of the test name. To run a single test, click the ▶ button that appears when you move the mouse over the test.
The console should print the total number of tests run and the number of tests that failed, if any. In this case, only one test was run and it should pass.
### Steps 9-11: Create Second Test for Edge Cases
9. Click **Add Test** again to add a second test. Change the test's name from _"Untitled test 2"_ to _"Handles undefined"_.
10. Click on the test to expand it and reveal the sandboxed JavaScript editor. Enter:
\`\`\`javascript
let variableResult = runCode({});
assertThat(variableResult).isEqualTo(undefined);
\`\`\`
11. Click **▶ Run Tests** to run all of the tests at once. The output of the test will appear in the console.
The _Handles undefined_ test should fail. Congratulations, you found a bug!
### Steps 12-14: Fix Code and Re-test
12. Click **Code** to go back and edit the template's sandboxed JavaScript code. Update the code as follows:
\`\`\`javascript
const getType = require('getType');
let input = data.text1;
if (getType(input) !== 'string') {
return input;
}
return input.toUpperCase();
\`\`\`
The updated code follows the best practice of validating the \`input\` variable before using it.
13. Click **Tests** to go back to the list of test cases.
14. Click **▶ Run Tests** to run all of the test cases again. This time the _Handles undefined_ test should pass.
15. Click **Save**, and close the Template Editor.
## Core APIs
### runCode
Executes the template's code with provided sample data object. Arguments are merged into the data global variable used in the template code.
### assertThat
Returns an object that can be used to fluently make assertions about a subject's value. Used for validation in tests.