Create a Consent Mode template

If you maintain a consent management solution for sites that use Google Tag Manager (GTM), we strongly recommend creating a template to support Google Consent Mode. A Consent Mode template enables your users to adopt Consent Mode and to integrate it with their consent solution in a codeless way, saving significant time and effort.

Consent Mode templates support the creation of tags that set default consent state and communicate visitor consent choices to Google Tag Manager. This ensures optimal functioning of Google and third-party tags that support Consent Mode.

As a template creator, you can implement Consent Mode templates for internal use or publish them in the Community Template Gallery to make them publicly available. Consent Management Platform (CMP) providers who offer Consent Mode templates have the opportunity to be listed in our Consent Mode documentation and have the Template Gallery picker feature their templates.

This page introduces consent state and consent types and shows how to use them with Consent Mode APIs. The last section provides an example of how to use the APIs to create a Tag Manager template. If you are new to Consent Mode or to Tag Manager templates, the following articles provide background information:

Google and third-party tags adjust their storage behavior based on a consent state of either granted or denied. They can have built in consent checks for any of the following consent types:

Consent Type Description
ad_storage Enables storage, such as cookies, related to advertising
analytics_storage Enables storage, such as cookies, related to analytics (for example, visit duration)
functionality_storage Enables storage that supports the functionality of the website or app such as language settings
personalization_storage Enables storage related to personalization such as video recommendations
security_storage Enables storage related to security such as authentication functionality, fraud prevention, and other user protection

The template should give your users the ability to set a default consent state for each consent type used by their website. They might also want to set default consent states for different regions.

GTM users should fire tags created with your template on all pages using the Consent Initialization trigger. This ensures that it will fire before any other tags. The template code should set the configured default consent states immediately upon firing. The CMP should then prompt the visitor as soon as possible to grant or deny consent for all applicable consent types. When a visitor indicates their choice, the CMP should pass in the updated consent state via the appropriate template API. Consent Mode keeps track of visitor consent choices and tag consent checks ensure that tag behavior adjusts accordingly.

Consent Mode implementations on sites that leverage GTM for tagging should use the GTM-specific APIs for managing consent states, setDefaultConsentState and updateConsentState. They may optionally use the gtagSet API to set the ads_data_redaction and url_passthrough settings as appropriate. These APIs are only available within the GTM template sandbox environment.

The default consent state should be set as early as possible when the page loads, using the Consent Initialization event to trigger the tag. Consent updates should be signaled to GTM as soon as possible after the user provides consent, or when the user's previous consent choice is loaded from cookies. There are a number of possible approaches for triggering updateConsentState. The examples later in this article demonstrate two possible options.

To configure the default consent settings, use the setDefaultConsentState API. The following example illustrates the use of the setDefaultConsentState call. It denies ad_storage by default and grants consent to the other storage types. It also uses wait_for_update to allow time to receive visitor choices from the CMP.

const setDefaultConsentState = require('setDefaultConsentState');

setDefaultConsentState({
  'ad_storage': 'denied',
  'analytics_storage': 'granted',
  'functionality_storage': 'granted',
  'personalization_storage': 'granted',
  'security_storage': 'granted',
  'wait_for_update': 500
});

After a website visitor has indicated their consent choices, typically through interacting with a consent banner, the template code should update consent states accordingly with the updateConsentState API.

The following example shows the updateConsentState call for a visitor that indicated they consent to all storage types. Again, this example uses hardcoded values for granted, but in practice, these should be determined at runtime using the visitor’s consent that is collected by the CMP.

const updateConsentState = require('updateConsentState');

updateConsentState({
  'ad_storage': 'granted',
  'analytics_storage': 'granted',
  'functionality_storage': 'granted',
  'personalization_storage': 'granted',
  'security_storage': 'granted'
});

Region-specific behavior

To set default consent states that apply to visitors from particular areas, specify a region (according to ISO 3166-2) in the template. Using region values enables template users to comply with regional regulations without losing information from visitors outside those regions. When a region is not specified in a setDefaultConsentState command, the value applies to all other regions.

For example, the following sets default status for analytics_storage to denied for visitors from Spain and Alaska, and sets analytics_storage to granted for all others:

const setDefaultConsentState = require('setDefaultConsentState');

setDefaultConsentState({
  'analytics_storage': 'denied',
  'region': ['ES', 'US-AK']
});
setDefaultConsentState({
  'analytics_storage': 'granted'
});

Most specific takes precedence

If two default consent commands occur on the same page with values for a region and subregion, the one with a more specific region will take effect. For example, if you have ad_storage set to 'granted' for the region US and ad_storage set to 'denied' for the region US-CA, a visitor from California will have the more specific US-CA setting take effect.

Region ad_storage Behavior
US 'granted' Applies to users in the US that are not in CA
US-CA 'denied' Applies to users US-CA
Unspecified 'granted' Uses the default value of 'granted'. In this example, that applies to users who aren't in the US or US-CA

Passing ad click, client ID, and session ID information in URLs

When a visitor lands on an advertiser’s website after clicking an ad, information about the ad might be appended to the landing page URLs as a query parameter. To improve conversion accuracy, Google tags usually store this information in first-party cookies on the advertiser’s domain.

However, if ad_storage is denied, Google tags will not save this information locally. To improve ad click measurement quality in this case, advertisers can optionally pass ad click information through URL parameters across pages using a feature called URL passthrough.

Similarly, if analytics_storage is set to denied, URL passthrough can be used to send event and session-based analytics (including conversions) without cookies across pages.

The following conditions must be met to use URL passthrough:

  • Consent-aware Google tags are present on the page.
  • The site has opted in to using the URL passthrough feature.
  • Consent Mode is implemented on the page.
  • The outgoing link refers to the same domain as the current page's domain.
  • A gclid/dclid is present in the URL (Google Ads and Floodlight tags only)

Your template should allow the template user to configure whether or not they would like to enable this setting. The following template code is used to set url_passthrough to true:

gtagSet('url_passthrough', true);

Redact ads data

When ad_storage is denied, new cookies will not be set for advertising purposes. Additionally, third-party cookies previously set on google.com and doubleclick.net will not be used. Data sent to Google will still include the full page URL, including any ad click information in the URL parameters.

To further redact your ads data when ad_storage is denied, set ads_data_redaction to true.

gtagSet('ads_data_redaction', true);

When ads_data_redaction is true and ad_storage is denied, ad click identifiers sent in network requests by Google Ads and Floodlight tags will be redacted.

Developer ID

If you are a CMP vendor with a Google-issued developer ID, use the following method to set this as early as possible in your template.

gtagSet('developer_id.<your_developer_id>', true);

Implementation example

This example shows how to create a template that reads cookies from the consent management solution to get visitor consent choices. This makes those choices available to GTM as early as possible during the loading process when a visitor made their selections on a previous page.

To follow this example, you will create one field in the template to hold the default consent state. The implementation code will read that field to set the default consent state at runtime. For the update command, your code will attempt to read a cookie set by the consent solution to store visitor consent choices. You will also set up a callback for updateConsentState to handle the case where a visitor has yet to make their consent selections or decides to change their consent.

The main steps include:

Use the Template Editor to create the template

  1. Log into your Google Tag Manager account.
  2. In the left navigation, select Templates.
  3. In the Tag Templates pane, click New.

Add Fields

  1. Select the Fields tab, click Add Field.
  2. Choose Param table.
  3. Change the name to defaultSettings.
  4. Expand the field.
  5. Update the Display name to Default settings.
  6. Click Add column, choose Text input, change the name to region and check the Require column values to be unique box.
  7. Expand the column, and change the display name to Region (leave blank to have consent apply to all regions). The statement in parenthesis is documentation for your template users.
  8. Click Add column, choose Text input, change the name to granted.
  9. Expand the column and change the display name to Granted Consent Types(comma separated).
  10. Click Add column, choose Text input, change the name to denied.
  11. Expand the column and change the display name to Denied Consent Types (comma separated).
  12. Click Add Field, choose Checkbox, and change the field name to ads_data_redaction.
  13. Update the Display name to Redact Ads Data.

Add Code

Copy the code below and replace parameters in brackets (the cookie name and check for updated consent state) with those appropriate for your implementation. Once updated, use your code to replace the boilerplate code in the GTM Code tab. Save the template after pasting.

// The first two lines are optional, use if you want to enable logging
const log = require('logToConsole');
log('data =', data);
const setDefaultConsentState = require('setDefaultConsentState');
const updateConsentState = require('updateConsentState');
const getCookieValues = require('getCookieValues');
const callInWindow = require('callInWindow');
const gtagSet = require('gtagSet');
const COOKIE_NAME = '<replace_with_your_cookie_name>';
/**
 * Splits the input string using comma as a delimiter, returning an array of
 * strings
 */
const splitInput = (input) => {
  return input.split(',')
      .map(entry => entry.trim())
      .filter(entry => entry.length !== 0);
};
/**
 * Processes a row of input from the default settings table, returning an object
 * which can be passed as an argument to setDefaultConsentState
 */
const parseCommandData = (settings) => {
  const regions = splitInput(settings['region']);
  const granted = splitInput(settings['granted']);
  const denied = splitInput(settings['denied']);
  const commandData = {};
  if (regions.length > 0) {
    commandData.region = regions;
  }
  granted.forEach(entry => {
    commandData[entry] = 'granted';
  });
  denied.forEach(entry => {
    commandData[entry] = 'denied';
  });
  return commandData;
};
/**
 * Called when consent changes. Assumes that consent object contains keys which
 * directly correspond to Google consent types.
 */
const onUserConsent = (consent) => {
  const consentModeStates = {
    ad_storage: consent['adConsentGranted'] ? 'granted' : 'denied',
    analytics_storage: consent['analyticsConsentGranted'] ? 'granted' :
                                                            'denied',
    functionality_storage: consent['functionalityConsentGranted'] ? 'granted' :
                                                                    'denied',
    personalization_storage:
        consent['personalizationConsentGranted'] ? 'granted' : 'denied',
    security_storage: consent['securityConsentGranted'] ? 'granted' : 'denied',
  };
  updateConsentState(consentModeStates);
};
/**
 * Executes the default command, sets the developer ID, and sets up the consent
 * update callback
 * 
 * Note: Developer IDs are only required when you're building an implementation
 * that will be used across multiple websites by unrelated companies or
 * entities. If the implementation will be used by one site or entity,
 * please do not apply for a developer ID.
 */
const main = (data) => {
  // Set developer ID
  gtagSet('developer_id.<replace_with_your_developer_id>', true);
  // Set default consent state(s)
  data.defaultSettings.forEach(settings => {
    const defaultData = parseCommandData(settings);
    defaultData.wait_for_update = 500;
    setDefaultConsentState(defaultData);
  });
  gtagSet('ads_data_redaction', data.ads_data_redaction);
  // Check if cookie is set and has values that corresopnd to Google consent
  // types. If it does, run onUserConsent().
  const settings = getCookieValues(COOKIE_NAME);
  if (typeof settings !== 'undefined') {
    onUserConsent(settings);
  }
  /**
   * Add event listener to trigger update when consent changes
   *
   * References an external method on the window object which accepts a
   * function as an argument. If you do not have such a method, you will need
   * to create one before continuing. This method should add the function
   * that is passed as an argument as a callback for an event emitted when
   * the user updates their consent. The callback should be called with an
   * object containing fields that correspond to the five built-in Google
   * consent types.
   */
  callInWindow('addConsentListenerExample', onUserConsent);
};
main(data);
data.gtmOnSuccess();

Add Permissions

Next, configure permissions for accessing consent state and for accessing cookies.

For managing consent states:

  1. Select the Permissions tab and click Accesses consent state.
  2. Click Add consent type.
  3. Click the box and select ad_storage from the drop-down menu.
  4. Check Write.
  5. Click Add

Repeat steps 2-5, substituting analytics_storage for ad_storage.

Finish by clicking Save.

For accessing cookies:

  1. Select the Permissions tab and click Reads cookie value(s).
  2. Under Specific, enter the names of each of the cookies your code needs to read to determine the user’s consent choices, one name per line.
  3. Click Save.

Tests

See Tests for information on creating tests for your template.

The following code shows one example of how this template could be integrated with the code for your consent management solution by adding a listener:

// Array of callbacks to be executed when consent changes
const consentListeners = [];

/**
 * Called from GTM template to set callback to be executed when user consent is provided.
 * @param {function} Callback to execute on user consent
 */
window.addConsentListenerExample = (callback) => {
  consentListeners.push(callback);
};

/**
 * Called when user grants/denies consent.
 * @param {Object} Object containing user consent settings.
 */
const onConsentChange = (consent) => {
  consentListeners.forEach((callback) => {
    callback(consent);
  });
};

Template user setup

You should provide documentation for template users. They will use this template to set up a tag that uses the Consent Initialization - All Pages trigger. In the Settings table, they should enter a list of the consent types and whether they want to grant or deny each by default. If default settings should differ based on where the user is located, they should create one row for each set of regions that share the same default consent state.