🔏
Azure Serverless Quickstart
  • Introduction
  • Initial Setup
    • Workstation Installs
    • Codebase
      • Directory Structure
      • User Interface Project
        • Configuring StoryBook
        • Configure Tailwind
        • Configure Craco
        • -Architectural Decision Log
      • Data Access Project
        • DDD
      • Untitled
      • Full Stack Debugging
      • Creating GitHub Project
    • Infrastructure
      • Configure Session Behavior
      • Create AAD Tenant
      • Resource Group
      • Create AAD B2C Instance
        • Identity Experience Framework
        • Configure Session Behavior
      • Storage Account & CDN
        • CDN Rules
        • Configure Azure BLOB Storage
      • App Insights
        • Create AppInsight Account
        • Apollo GraphQL App Insights Configuration
      • CosmosDB
      • Twilio SendGrid
      • KeyVault
      • Function
      • Function App Settings
      • Front Door
      • DevOps
      • Optional Items
        • Azure Data Factory
      • Azure Event Hub
    • CICD and Source Control
      • Azure DevOps
      • SonarCloud
        • Incorporate into Yaml
      • Chromatic
      • User Interface YAML
      • CICD for Data Access
        • Create Pipeline
        • Data Access YAML
  • Application Structure
    • Connect Apollo
      • Apollo Overview
      • Create Apollo Component
    • MongoDB Integration
      • Mappings
      • Directory Structure
      • Apollo Connection
      • Models
      • Queries Mutations and Subscriptions
      • Caching Reponses
    • Integrating GraphQL Tools
      • GraphQL Code Generator
    • Feature Flags
      • Flag Structure & Storage
      • Website Integration
      • Apollo Integration
      • Tips and Techniques
      • Alternative Approaches
    • React Router
    • Adding Authentication
      • Create AAD Applications
      • Configure AAD For External Identities
      • Adding MSAL And React
      • Add MSAL to the build
      • Add MSAL to ApolloClient
      • Add MSAL to ApolloServer
    • Ant Design
    • Jest Tests
  • Azure Active Directory Business-to-Consumer (AD B2C)
    • Introduction
    • How to navigate through AD B2C documentation
    • Localization
    • Abbreviations
    • Azure AD B2C Extension
  • Cognitive Search
  • Cost Analysis
  • Technical Architecture
    • Identity and Access Control
  • Adding Functionality
    • Google Analytics
      • Create Analytics
    • DAPR
      • DAPR setup
      • DAPR Services (ignore for now)
        • Identity
  • Patterns and Practices
    • Idempotent Messages
    • Pathways
    • DDD
      • Initial Setup
        • Aggregate Root
        • Entity
        • Value Object
      • Field Types
        • Primitive Types
        • Non-Primitive Types
          • Types.DocumentArray
          • PopulatedDoc
          • Custom Types
      • Example Walkthrough
  • Open Items
    • Issue Tracking
  • Helpful Resources
  • DDD
    • Page 1
  • Experimental
    • StaticWebApp
    • Azure Maps
Powered by GitBook
On this page
  • Terminology
  • Prerequisites
  • Setup
  • Install NPM Package
  • Add Environment Variable
  • Initialize React Component
  • Configure CSP Header
  • Integrate with ReactRouter
  • Integrate With React Components
  • Adding Helmet to update Page Name
  • Integrate Helmet with your React Pages
  • Verifying with Debug Mode
  • Additional Resources

Was this helpful?

  1. Adding Functionality

Google Analytics

PreviousIdentity and Access ControlNextCreate Analytics

Last updated 12 months ago

Was this helpful?

In October 2020 Google launched GA4 - a major change to Google Analytics, one which is more event driven to reflect that there has been a fundamental shift away from traditional web sites to web applications and mobile apps.

What follows is a guide for implementing gtag.js into the codebase, this is different from Google Tag Manager.

Terminology

Tag Manager ( a tool for processing events in a website and sending to a GA account ) can have difficulty with the complexity of site described in this guide as it's more of a full on javascript application than a website.

GA4 - it's wildly different than GA3 and Universal Analytics, and is the recommended path take by Google who is committed to it (as it works better with Javascript applications (like pathways), mobile apps etc).

gtag.js - Is a developer friendly library that exposes only a few methods for logging events later in this document each of these will be explored.

Prerequisites

Setup

Install NPM Package

Install the npm package, it helps to ensure the that the google scripts are initialized correctly before calling functions.

This small but mighty package will do a few things:

  • Reference the google script file from google's CDN

  • Add a script tag to the head element to execute javascript to wire up GA

  • Expose GA4 in react in an easy to use way.

Terminal / Command Prompt ( /azure-quickstart/ui )
npm install ga-4-react

Add Environment Variable

Update .env file to include the GA4 Measurement ID.

  • Create React App

/azure-quickstart/ui/.env
...
REACT_APP_GA_MEASUREMENT_ID=<<your GA4 measurement ID>>
...
  • Vite

/azure-quickstart/ui/.env
...
VITE_GA_MEASUREMENT_ID=<<your GA4 measurement ID>>
...

Initialize React Component

Update index.tsx to:

  • Read the GA4 Measurement ID environment variable

  • Create an instance of the Ga4react class

    • Automatically enter into debug mode when running locally

  • Initialize the ga4react object prior to rendering the app to ensure GA4 is available in the app.

/azure-quickstart/ui/index.tsx
...
import GA4React from 'ga-4-react';

const gaMeasurementId = process.env.REACT_APP_GA_MEASUREMENT_ID as string;
const ga4react = new GA4React(gaMeasurementId,{ debug_mode: process.env.NODE_ENV !== 'production'});

(async() =>  {
  
  try{
    await ga4react.initialize();
  }catch(error){
    console.error(error);
  }

  ReactDOM.render(
    ...
  );
  
})()

...

Configure CSP Header

Once deployed, the website will not work as the webpage is referencing a script from a different domain and also using some inline code, thanks to CSP.

To get things working the HTTP headers will need to be updated:

  • Allow script and images to be loaded from a different domain

  • Allow a very specific inline script to be run (adding a hash of the script)

    • As the inline script includes your GA Measurement ID, you have to generate the hash yourself for each environment (assuming you use a different measurement ID for QA/UAT/Prod)

This will not work with proper security headersUpdate CSP

To generate the CSP hash use the following as an example:

The script block is what gets injected on your page from the react component, to get the specific specific block for your code, pause your app in chrome debugger and get your exact string. ( /src/lib/ga4tagmanager.tsx ~line 130) (be sure to change the debug_mode to false if you are debugging locally, as it wont be false when you deploy to your production environment)

window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);};
        gtag('js', new Date());
        gtag('config', 'G-XXXXXXXXXX', {"debug_mode":false});

Read more on CSP with these resources

Example CSP from a Static-Web-App config section for reference.

/azure-quickstart/ui/staticwebapp.config.json
{
  ...
  "globalHeaders": {
    "content-security-policy": "default-src https: 'unsafe-eval' 'unsafe-inline' https://www.googletagmanager.com; object-src 'none'; script-src 'self' https://cdn.jsdelivr.net https://www.googletagmanager.com 'sha256-IBkv3CC/Fwz7jbHfcCIlP19U0yv+7XjdPbTS4DBRBeg='; img-src 'self' www.googletagmanager.com data:;"
  },
  ...
}

Integrate with ReactRouter

Update App.tsx to register every page change by subscribing to react routers' location changes

/azure-quickstart/ui/src/App.tsx
...
import React, { useEffect } from 'react';
import { Switch, Route, useLocation } from "react-router-dom";
import  { useGA4React } from "ga-4-react";

..
 
function App() {
  const ga = useGA4React();
  const location = useLocation();
  
  useEffect(()=> {
    if(ga){
      ga.pageview(location.pathname)
    }
  }, [location, ga])

  return (
    <>
      ...
    </>
  );
}

export default App;

Integrate With React Components

Note that "select_content" and "click" are Google defined events each with their own valid parameters. Google has relatively low limits on the number non-standard event types and parameters therefore it is recommended to stick to the standard types and parameters.

/azure-quickstart/ui/src/components/<<some component>>.tsx
import{ useGA4React } from "ga-4-react";


const MyComponent: FC< RouteComponentProps| any> = (props) => {
  const ga = useGA4React();

  var someAction = (eventDetail:string) => {
    if(ga && eventDetail ){
      ga.gtag(
        'event',
        'select_content',
        {
          'content_type':'user-took-some-action',
          'item_id': eventDetail
        }
      );
    }
  }
  
  const trackOutboundLink = (event:any) => {
    var targetUrl = event.target.href;
    if(ga && targetUrl ){
      ga.gtag(
        'event',
        'click',
        {
          'page_location': targetUrl,
          'page_referrer': document.location.pathname + document.location.search
        });
    }
  }
  
  ...
  
  return(
    <>
        ...
          <a href='https://www.google.com' target='_blank' rel='noreferrer'  onClick={trackOutboundLink}>Google</a>
        ...
    </>
  )
}

export default withRouter(MyComponent);

Adding Helmet to update Page Name

It is always good to update the page title for usability, it also benefits in GA

Terminal / Command Prompt ( /azure-quickstart/ui )
npm install react-helmet

Integrate Helmet with your React Pages

/azure-quickstart/ui/src/components/<<some component>>.tsx
import React, { FC } from "react";
import { Helmet } from 'react-helmet';
...


const MyComponent: FC<any> = (props) => {
  ...

  return(
    <>
        <Helmet>
          <title>A PAGE TITLE FOR THIS COMPONENT</title>
        </Helmet>
        ... YOUR NORMAL REACT CODE ...
    </>
  )
}

Verifying with Debug Mode

Testing everything out:

Debug the codebase and navigate to the webpage, a new floating box will be shown the lower right of the screen, click "connect" to connect to the Tag Assistant, a new browser window will open and from there it is easy to see google is receiving from the website.

Additional Resources

(change out the code with your GA Measurement ID and use an to get the proper hash value, in the example above, the hash would be: sha256-IBkv3CC/Fwz7jbHfcCIlP19U0yv+7XjdPbTS4DBRBeg=)

Google Analytics -

Google Analytics -

Google Tag Assistant -

GA4 Measurement ID
ga-4-react
online hash generator
GA And CSP
CSP Details
Events Reference
Advice on using Events
Introduction and Help