Skip to main content

Google analytics for apps in WPP Open

This guide outlines the standards for deploying Google Analytics (GA4) to applications in WPP Open. The primary goal of deploying GA4 on WPP Open is to enable tracking and reporting of the adoption of the system by users. Additional goals include understanding the utilisation, adoption, value generation and commercial benefits of WPP Open across different markets, agencies, clients and tools.

Implementation steps

Implementing GA4 on the web includes the following steps:

  1. Deploy a Google Tag Manager tag to every page on the site, or application to be tracked (App Dev Team).
  2. Configure a data layer to hold the data to be sent to GA4 (App Dev Team).
  3. Configure GTM (GA4 Team).
  4. Configure GA4 (GA4 Team).
note

This guide covers the first two steps of the process.

Types of WPP Open web applications

There are three ways in which applications are deployed in WPP Open:

  1. Integrated – these applications are built within Open OS and are integrated within the WPP Open Platform.
  2. i-Framed – these applications are hosted in their own environment and are accessed from WPP Open via an i-frame.
  3. Stand-Alone – these applications sit entirely outside of the WPP Open Platform and are accessed by users directly in their own environments.

Any application can in theory be accessed in any one of these configurations.

important

Integrated applications are tracked via the Core OS tag manager and data layer and do not require any additional work from the App Dev team.

Google Tag Manager (GTM)

Each Studio has been assigned a Google Tag Manager ID (GTM ID) as follows:

StudioGTM ID
Core OSGTM-KSKHG4RN
Creative StudioGTM-PHG7HMFL
Media StudioGTM-56M5TDZ9
Commerce StudioGTM-MCJK2K3M
Production StudioGTM-PVJH95C3
Brand StudioGTM-KBKFN66M
Experience StudioGTM-N3D6DRHM
Work Management StudioGTM-58V922NT
PR StudioGTM-MCBWFVWF
Other StudiosGTM-MH5HD5L6

The code below with the correct GTM ID must be deployed on every web page to be tracked. The code should be placed as high up in the <head> of the page as possible:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var
f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insert
Before(j,f);
})(window,document,'script','wppopen','GTM-MCJK2K3M');</script>
<!-- End Google Tag Manager -->
important

See the official Google documentation on installing the Google Tag Manager container snippet.

The below diagram illustrates the relationship between Open OS and CO environments:

Instructional image

Data layer

Data layer is an object that contains all the information that you want to pass to Google Tag Manager. Rather than referencing variables, transaction information, page categories, and other important signals scattered throughout a page, Google Tag Manager is designed to easily reference information that is put in this Data layer by applying a variable called an event. This event is used within JavaScript event listeners to initiate tag firing when a user interacts with website elements such as a button.

Data object

The data object (which is the data layer object) should be deployed consistently across all pages, instances, workspaces, and any element of an application that is to be tracked.

This data object adds a layer of dimensions to all collected events, enabling segmentation of the data based on those dimensions.

The following categories of information are tracked:

  • User Information: Identifies the user and their organizational context.
  • Contextual Information: Provides details about the specific application, workspace, and project the user was working on.
  • Action & Feature: Specifies the application, the feature used, and the task status.
  • Web Analytics: Includes standard web analytics data like page details, platform, device, and browser information.

How this data can be used for tracking and analytics

  • User Behaviour: Analyse how different user roles and departments interact with specific features.
  • Feature Adoption: Track the usage and popularity of different features within the application.
  • Performance Monitoring: Identify potential issues or bottlenecks based on task completion rates and user engagement.
  • Product Development: Gather insights to inform the development of new features and improvements.
note

To avoid data layer clashes or overwrites, it is important to name your data layer to ‘wppopen_dataLayer’. This means that your data object won't collide with any default data layer that may be in place from another GTM container.

For reference here is a link to the official google guide: https://developers.google.com/tagplatform/tag-manager/datalayer

Data layer setup

Tags set in Google Tag Manager are commonly sending information to end points at two stages of the user website visit: immediately after the user lands on a page (Page View), or immediately after the user engages with a page (User Interaction). The data layer setup will vary accordingly.

Page View

When the data layer setup is defined as Page View setup, the data layer array code is included before the Google Tag Manager Snippet.

If the data layer code is called after the container snippet, any variables declared within will not be available for Google Tag Manager to selectively fire tags on page view.

<script>
window.wppopen_dataLayer = window.wppopen_dataLayer || [];
window.wppopen_dataLayer.push({
'event': 'sitewide',
'visitorType': 'high-value'
});
</script>
<!-- Google Tag Manager -->
//GTM container snippet would go here
<!-- End Google Tag Manager -->

User Interaction

The data layer array implementation for user interactions doesn’t require any specific setup outside a simple call to the push API immediately after the user interaction that is required to track. For example, if we want to fire a conversion tracking tag in Google Tag Manager when a user clicks the Submit button on a newsletter signup form, we could have something similar to the below:

<script>
function dataLayerTracking() {
window.wppopen_dataLayer = window.wppopen_dataLayer || [];
WPP Open GA4 Implementation
9
dataLayer.push({
'event': 'signUpNewsLetter',
'crmID': '12345'
});
}
</script>
...
<a href='#' name='newsLetter_button1'
onclick='dataLayerTracking();'>Sign Up</a>

Supported data types

Each data field in the data layer belongs to a specific type, each with its own validation rules. If any of the parameter values do not conform to the validation rules, the information sent by Google Tag Manager to the different tracking provider could be compromised.

Data TypeDefinitionExample
TextUsed to represent strings.window.wppopen_dataLayer.push({'Text': 'My Text here'});
CurrencyUsed to represent the total value of a currency. A decimal point is used as a delimiter between the whole and fractional portion. Supports up to 6 decimal places, though 2 is typical.window.wppopen_dataLayer.push({'Currency': '1000.000001'});
BooleanUsed to determine if a value is true or false. Valid values: true, false.window.wppopen_dataLayer.push({'Boolean': true});
IntegerUsed to represent whole numbers. Stored as signed int64.window.wppopen_dataLayer.push({'Integer': 25});
NumberUsed to represent an integer or a floating-point number.window.wppopen_dataLayer.push({'Number': 19.6});

Default values

Each data field in the Data Layer must have a default value.

Default ValueDefinitionExample
'unknown''unknown' (type String) must be used when a value is expected to exist for a given key within a page or user interaction, but could not be retrieved.window.wppopen_dataLayer.push({'MyVar': 'unknown'});
undefinedundefined (type undefined) must be used when a value is not meant to exist for a given key within a page or user interaction.window.wppopen_dataLayer.push({'MyVar': undefined});

User profile data

To obtain user information and understand users and usage on WPP Open as well as Studios and Apps additional user profile data is required. We use data derived from the user’s Okta profile for this. The following variables need to be passed through in the data object (instructions for this below):

User dimensions

Dimension NameDescriptionExample ValueGA4 Parameter / User PropertyMandatory / Optional
User IDA unique hashed ID used to track users across sessions and platforms.d75f4df44ef437b93309d303bbdc65e79d6db36ea3320e4d974b727a272d17c4user_idMandatory
User CompanyWPP agency or OpCo the user belongs to.essencemediacomuser_companyMandatory
User DepartmentTeam or department the user belongs to.programmaticuser_departmentMandatory
User Job RoleThe user’s job title.digital_planneruser_job_roleMandatory
User Country CodeTwo-letter code for the user's country.ukuser_country_codeMandatory
User RegionRegion where the user is based.EMEAuser_regionMandatory

We need to pass through the correct values for the variables for each user i.e. update the profile to accommodate for the above variables.

User ID

This should be the hashed email address.

For normalisation:

  • Remove leading or trailing whitespaces.
  • Convert the text to lowercase. For hash: Use hex SHA256.

This site can be used to validate the output: https://emn178.github.io/online-tools/sha256.html

The table below lists more information about the customer data variables that you can define. Note that all data should be passed as ‘String’ type variables.

Apps in Open

Populate the datalayer with the data passed to the application from Open’s context object:

Context KeyData Layer Object
userDetails->email (pre hash)user_id (hashed)
userDetails->companyuser_company
userDetails->countryAlpha2Codeuser_country_code
userDetails->departmentuser_department
userDetails->jobTitleuser_job_role
userDetails->geoRegionuser_region

Standalone apps outside of Open

It is vital we accurately capture the identity of the user so we can attribute user to the correct OpCo, Country and Job Role.

To allow for consistency in this regard, we use Okta and its Okta Object, which provides a common way for all applications (that use Okta) to send consistent data points for that user for use within GA4.

Okta object to Data layer mapping

Okta ObjectData Layer Object
email (pre hash)user_id (hashed)
companyuser_company
countryCodeuser_country_code
departmentuser_department
titleuser_job_role
geoRegionuser_region

Mandatory custom events

There are three events that are a required for all applications. Firstly, there is an event (user_login) to capture logins. Parameters for this event come from the OKTA Object. The second event (app_launch) is fired on the launch of an application. The third is page_view for when the page loads in the browser. If your application is a SPA then there is a 4th Mandatory Event for virtual_page_views to cope with state changes that don’t reload the page.

User login event

note

Apps launched via Open should not send the user_login event, but if they can also be launched standalone, then they should only send the user_login event when launched standalone.

Setup

The data object should be implemented following the Page View setup spec above as typically the user should gain access to the application via the Okta Verification process before seeing a home page. Note that Login still would be required if a user previously followed the Okta Verification Process and was not prompted on entry to the Application. Please see the section about WPP User Meta Data for more detail.

Code example

{
"event": "user_login",
"user_id":
"d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4"
,
"user_company": "Choreograph",
"user_country": "GB",
"user_department": "Analytics",
"user_job_role": "Lead Technology Consultant – Digital
Analytics",
"user_region": "EMEA",
}
Data Layer ObjectMandatory / Optional
user_id (hashed)Mandatory
user_companyMandatory
user_country_codeMandatory
user_departmentMandatory
user_job_roleMandatory
user_regionMandatory

Page_View

Setup

The data object should be implemented following the Page View setup. So, when a page is loaded in the browser we send the following data object when the dataLayer items are available, if items are not applicable then please do set as undefined.

Code example

{
"event": "page_view",
"user_id":
"d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4",
"workspace_market": "EMEA",
"workspace_industry": "Food and Drink",
"workspace_brand": "TCCC",
"workspace_client": "The Coca Cola Company",
"workspace_region": "APAC",
"workspace_custom": "TCCC",
"context_type": "os",
"tenant_name": "WPP Open",
}

Datalayer key explanations

DataLayer Key NameDescriptionMandatory / Optional
user_idMandatory
workspace_marketThe market name from hierarchy->mapping with type='Market', or undefined.Mandatory
workspace_industryThe industry name from hierarchy->mapping with type='Industry', or undefined.Mandatory
workspace_brandThe brand name from hierarchy->mapping with type='Brand', or undefined.Mandatory
workspace_clientThe client name from hierarchy->mapping with type='Client', or undefined.Mandatory
workspace_regionThe region name from hierarchy->mapping with type='Region', or undefined.Mandatory
workspace_customThe custom name from hierarchy->mapping with type='custom', or undefined.Mandatory
context_typeValue must be either "os" or "standalone".Mandatory
tenant_nameFrom context object (tenant->name), otherwise undefined.Mandatory

Virtual_Page_View

Setup

In a single-page application, when triggering a new page_view due to a screen change without reloading the browser page, the following approach should be used.

The pageUrl, previousUrl, and pageTitle parameters must be dynamically updated to reflect the current screen's URL and title. If the URL includes hash fragments (#) or query parameters (?), these should also be included.

Code example

{
"event": "virtual_page_view",
"user_id":
"d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4",
"pageUrl": "https://www.mywebsite.com/something/?page#contact-us",
"pageTitle": "Contact us' //some arbitrary name for the page/state",
"previousUrl": "https://www.mywebsite.com/something-else/",
"workspace_market": "EMEA",
"workspace_industry": "Food and Drink",
"workspace_brand": "TCCC",
"workspace_client": "The Coca Cola Company",
"workspace_region": "APAC",
"workspace_custom": "TCCC",
"context_type": "os",
"project": "project X",
"tenant_name": "WPP Open",
}

Datalayer key explanations

DataLayer Key NameDescriptionMandatory / Optional
user_idMandatory
pageUrlCurrent URLMandatory
pageTitleCurrent Page TitleMandatory
previousUrlPrevious URLMandatory
workspace_marketThe market name from hierarchy->mapping with type='Market', or undefined.Mandatory
workspace_industryThe industry name from hierarchy->mapping with type='Industry', or undefined.Mandatory
workspace_brandThe brand name from hierarchy->mapping with type='Brand', or undefined.Mandatory
workspace_clientThe client name from hierarchy->mapping with type='Client', or undefined.Mandatory
workspace_regionThe region name from hierarchy->mapping with type='Region', or undefined.Mandatory
workspace_customThe custom name from hierarchy->mapping with type='custom', or undefined.Mandatory
context_typeValue must be either "os" or "standalone".Mandatory
projectFrom context object (project->name), otherwise undefined.Mandatory
tenant_nameFrom context object (tenant->name), otherwise undefined.Mandatory

Application launch event

Setup

The data object should be implemented following the Page View setup. Typically, a user will launch an application from a click.

Code example

{
"event": "app_launch",
"user_id":
"d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4",
"application_id": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"application_instance_id": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"product_type": "NO_CODE_APPLICATION",
"nocode_apptype": "EMBEDDED_LINK",
"workspace_market": "EMEA",
"workspace_industry": "Food and Drink",
"workspace_brand": "TCCC",
"workspace_client": "The Coca Cola Company",
"workspace_region": "APAC",
"workspace_custom": "TCCC",
"context_type": "os",
"product_name": "creative-studio",
"product_category": "Media",
"product_subcategory": "Planning",
"tenant_name": "WPP Open",
}

DataLayer key explanations

DataLayer Key NameDescriptionMandatory / Optional
user_idMandatory
application_idTaken from context object: appInstance->devhubAppIdMandatory
application_instance_idTaken from context object: appInstance->idMandatory
product_typeTaken from context object: appInstance->devhubMetadata->productTypeMandatory
nocode_apptypeTaken from context object: appInstance->devhubMetadata->noCodeAppType, or undefinedMandatory
workspace_marketThe market name from hierarchy->mapping with type='Market', or undefinedMandatory
workspace_industryThe industry name from hierarchy->mapping with type='Industry', or undefinedMandatory
workspace_brandThe brand name from hierarchy->mapping with type='Brand', or undefinedMandatory
workspace_clientThe client name from hierarchy->mapping with type='Client', or undefinedMandatory
workspace_regionThe region name from hierarchy->mapping with type='Region', or undefinedMandatory
workspace_customThe custom name from hierarchy->mapping with type='custom', or undefinedMandatory
context_typeValue must be either "os" or "standalone"Mandatory
product_nameThe name of the product. Ensure the same name is used whether the app is registered multiple times in Open or also runs standaloneMandatory
product_categoryA meaningful one-word value that reflects the general product area of the application, e.g. Media, PRMandatory
product_subcategoryA meaningful one/two-word value that reflects the activity or sub-area the application supports, e.g. planning, production, strategy, etc.Mandatory
projectIf context object contains project key then populate with project->name, otherwise undefinedMandatory
tenant_nameFrom context object (tenant->name), otherwise undefinedMandatory
important

Work with the Open OS team to see how your application can receive data from Open OS for context around Workspaces, Projects, etc. For more details, see the Open OS Context guide.

Optional custom events

The following custom events have been defined and are available for more granular tracking of user activity. Parameters that are not required may be omitted from the data layer or set to ‘undefined’. If additional events or parameters are required, they will first have to be requested and enabled in GA4 by the GA4 team.

Action interaction events

Complete DataLayer key reference

DataLayer Key NameDescriptionMandatory / Optional
user_idMandatory
application_idTaken from context object: appInstance->devhubAppIdMandatory
application_instance_idTaken from context object: appInstance->IdMandatory
product_typeTaken from context object: appInstance->devhubMetadata->productTypeMandatory
nocode_apptypeTaken from context object: appInstance->devhubMetadata->noCodeAppType, or undefinedMandatory
workspace_marketThe market name from hierarchy->mapping with type='Market', or undefinedMandatory
workspace_industryThe industry name from hierarchy->mapping with type='Industry', or undefinedMandatory
workspace_brandThe brand name from hierarchy->mapping with type='Brand', or undefinedMandatory
workspace_clientThe client name from hierarchy->mapping with type='Client', or undefinedMandatory
workspace_regionThe region name from hierarchy->mapping with type='Region', or undefinedMandatory
workspace_customThe custom name from hierarchy->mapping with type='custom', or undefinedMandatory
context_typeValue must be either "os" or "standalone"Mandatory
product_nameThe name of the product; should remain consistent even if app is registered multiple times or used standaloneMandatory
product_categoryA one-word value reflecting the general product area, e.g., Media, PRMandatory
product_subcategoryA one- or two-word value reflecting the sub-area or activity the app supports, e.g., planning, strategy, productionMandatory
projectIf context object contains project, populate with project->name, otherwise undefinedMandatory
tenant_nameFrom context object tenant->name, otherwise undefinedMandatory
click_objectCan be: 'Image', 'Button', 'Link', 'Icon'Mandatory
click_page_pathExample: {{page_path}}Mandatory
click_textExample: {{image_text}}, {{alt_text}}, {{button_text}}, {{link_text}}Mandatory
click_target_pathExample: {{url_target_path}}Optional

Code example

window.wppopen_dataLayer.push({
"event": "click",
"user_id": "d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4",
"application_id": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"application_instance_id": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"product_type": "NO_CODE_APPLICATION",
"nocode_apptype": "EMBEDDED_LINK",
"workspace_market": "EMEA",
"workspace_industry": "Food and Drink",
"workspace_brand": "TCCC",
"workspace_client": "The Coca Cola Company",
"workspace_region": "APAC",
"workspace_custom": "TCCC",
"context_type": "os",
"product_name": "creative-studio",
"product_category": "Media",
"product_subcategory": "Planning",
"project": "Project Xmas",
"tenant_name": "WPP Open",
"click_object": "button",
"click_page_path": "/hubs/",
"click_text": "Request Growth Support",
"click_target_path": undefined
});

Feature function events

Use the feature function event to capture the principal features of your product that a user is interacting with. For example, a user may launch the app and navigate to an asset management page and proceed to upload a new asset. In this scenario, a feature_activate event should be sent to track the usage of the asset management feature (i.e. the feature_category) to upload assets (feature_context). The name of each asset can be included using the feature_freeform_[n] keys. Up to 10 feature_freeform_ keys can be added as needed.

Carefully consider which features to send feature_activate events for. These should not be so granular that it becomes unclear what user’s purpose is.

The feature_complete event may be used to indicate something as completed, e.g. the upload of assets is finished, AI image or text generation has completed, etc. It is not necessary to send a feature_complete for each feature_activate. Consider using this if it may be useful to understand data about the outcome of using a particular feature, e.g. the size of an audience for a particular audience definition.

The feature_settings event may be used to capture information about how a user may have adjusted a particular feature, e.g. applying filtering, particularly if it has a strong bearing on how the feature may be feature_settings if the adjustment would result in a feature_activate event being sent.

Feature event parameters

Event nameParameterExample valueMandatory / Optional
feature_activatefeature_categoryAI ImageMandatory
feature_contextGenerate ImageMandatory
feature_freeform_1{{model_used}}Optional
feature_freeform_2{{images_generated}}Optional
feature_completefeature_categoryAI ImageMandatory
feature_contextRemove ElementMandatory
feature_freeform_1{{model_used}}Optional
feature_freeform_2{{images_generated}}Optional
feature_settingsfeature_categoryAI ImageMandatory
feature_contextChange ModelMandatory
feature_freeform_1Optional
feature_freeform_2{{images_generated}}Optional

Code example

window.wppopen_dataLayer.push ({
"event": "feature_activate",
"user_id":
"d75f4df44ef437b93309d303bbbdc65e79d6db36ea3320e4d974b727a272d17c4",
"applicationwide": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"application_instance_id": "0a1c0520-8c67-1590-818c-68fa74bb004b",
"product_type": "NATIVE_APPLICATION",
"nocode_apptype": "",
"workspace_market": "EMEA", //context object
"workspace_industry": "Food and Drink", //context object
"workspace_brand": "TCCC", //context object
"workspace_client": "The Coca Cola Company", //context object
"workspace_region": "APAC", //context object
"workspace_custom": "TCCC", //context object
"context_type": "os",
"product_name": "creative-studio",
"product_category": "Media",
"product_subcategory": "Planning",
"project": "Project Xmas", //context object
"tenant_name": "WPP Open", //context object
"feature_category': 'AI Image",
WPP Open GA4 Implementation
29
"feature_context': 'generate image",
"feature_freeform_1': 'Gemini",
"feature_freeform_2': 20
});