Follow me on LinkedIn - AI, GA4, BigQuery

Learn how to set up GA4 cookieless tracking and track user activity without cookies. Follow our easy guide to ensure privacy-friendly analytics in GA4.

What is cookieless tracking?

Cookieless tracking refers to the process of tracking user behaviour and interactions on websites or apps without relying on browser cookies, particularly third-party cookies used for tracking across multiple websites.

A cookie is a text file that is used to:

  • Store information about user preferences, user location, and other details
  • Protect users’ data from unauthorized access
  • Maintain certain websites’ functionality
  • Serve personalize ads to users and make advertising more effective via re-marketing
  • Collect Google Analytics data and other tracking data.

Cookies are stored on a user’s hard disk and can be enabled or disabled via web browser settings. 

For more information on cookies: Understanding Google Analytics 4 cookies – _ga cookie.

Classification of cookies.

In terms of privacy compliance, Cookies can be broadly classified into two categories:

#1 Essential cookies—These are the cookies required for maintaining website functionality and security. They can be first-party and/or third-party cookies.

#2 Non-essential cookies – These cookies are not required to maintain website functionality and security. They can be first-party and/or third-party cookies. Non-essential cookies are often used to enhance user experience, gather analytics, or serve personalised ads.

First-party cookies are issued by the website being visited, and only the website that issued them can read them. Whereas, third-party cookies are issued by the website(s) other than the website being visited.

Not all first-party cookies are essential cookies. 

It is a common misconception that first-party cookies are inherently essential, but this is not true.

First-party cookies can be either essential or non-essential, depending on their purpose.

For example, a Google Analytics cookie is a first-party cookie but a non-essential cookie since the website can function perfectly well without gathering analytic data.

Not all third-party cookies are non-essential cookies.

Some third-party cookies are crucial for the core functionality and security of websites.

For example, if a website uses a third-party SSO provider (like Google or Facebook login), third-party cookies are essential to authenticate users and manage the login session across different websites. 

These cookies enable users to sign in across different services without repeatedly entering credentials.

Cookies from payment processors like Stripe or PayPal can be essential for secure transactions on e-commerce sites.

Services like Cloudflare may use cookies that are essential for load balancing, DDoS protection, and optimising content delivery.

How GA4 provide Cookiless Tracking

GA4 (Google Analytics 4) primarily relies on first-party cookies (like the ‘_ga’ cookie) for tracking users and sessions under normal circumstances.

Still,

GA4 has mechanisms to provide cookieless tracking when cookies are not available or when users do not consent to cookie-based tracking.

GA4 uses the following techniques to track users even when cookies are not available or consent is not granted for cookie-based tracking:

#1 Behavioural modeling – Estimates user behaviour when they don’t consent to cookies.

#2 Conversion modeling – Estimates the impact of marketing when conversions can not be directly attributed to a traffic source.

#3 User-ID tracking – Allows users to be tracked across devices and browsers when they are logged in. If a user is logged in, the User ID can be used as the primary identifier across devices and sessions without needing cookies. In this case, it acts as a cookieless tracking method because the User-ID replaces the Client ID (stored in a cookie) as the key identifier.

#4 First-Party Data Collection – GA4 encourages businesses to use first-party data, such as email addresses or other login information, to identify users. This helps create a more comprehensive understanding of user behaviour across devices and sessions without relying entirely on cookies.

#5 Google Advanced Consent Mode – Allows for cookieless tracking through several mechanisms like Cookieless Pings, Default Consent States, Behavioral and Conversion Modeling, Anonymous Data Collection, etc.

How to set up Cookiless tracking in GA4?

You can set up cookieless tracking in GA4 by using the following storage mechanism (instead of cookies) to achieve as much functionality as possible without compromising user experience, functionality, or data privacy.

  1. Data Layers.
  2. Session Storage.
  3. Local Storage.
  4. URL Parameters.
  5. Server-side storage.
  6. Server-side tracking.

If you want to temporarily store data (like the data from UTM parameters) before consent is granted, use the data layer instead of the first-party cookie.

That way, you don’t need to place any analytics cookie before the consent is granted.

When a user lands on your page, you can capture the UTM parameters from the URL and temporarily store them in the data layer.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

// Initialize the data layer if it doesn't already exist

window.dataLayer = window.dataLayer || [];

 

// Function to get URL parameters (UTM values in this case)

function getURLParameter(name) {

  let regex = new RegExp('[?&]' + name + '=([^&#]*)', 'i');

  let result = regex.exec(window.location.href);

  return result ? decodeURIComponent(result[1]) : null;

}

 

// Capture UTM parameters from the URL

let utmSource = getURLParameter('utm_source');

let utmMedium = getURLParameter('utm_medium');

let utmCampaign = getURLParameter('utm_campaign');

 

// Temporarily store UTM data in the data layer

window.dataLayer.push({

  'event': 'UTMParametersCaptured',

  'utm_source': utmSource,

  'utm_medium': utmMedium,

  'utm_campaign': utmCampaign

});

 

// Log the data layer for demonstration purposes

console.log(window.dataLayer);

Once the user consents to tracking (through a cookie consent banner), you can then move the data from the data layer to an analytics tool like GA4.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// Simulate user consent (In a real scenario, this would be triggered by a consent banner)

function userConsentGranted() {

  // Find the UTM parameters event in the data layer

  let utmData = window.dataLayer.find(event => event.event === 'UTMParametersCaptured');

   

  if (utmData) {

    // Send the UTM parameters to GA4 using gtag()

    gtag('event', 'utm_capture', {

      'utm_source': utmData.utm_source,

      'utm_medium': utmData.utm_medium,

      'utm_campaign': utmData.utm_campaign

    });

 

    console.log("UTM parameters sent to GA4:", utmData);

  }

}

 

// Example: Call the consent function once consent is granted (e.g., after the user clicks "Accept")

userConsentGranted();

Note: Only pass necessary and lightweight data through the data layer. For larger datasets, rely on server-side storage. Server-side storage replaces cookies for handling large or sensitive datasets that can’t be handled efficiently in the data layer.

#2 Use Session Storage for storing session specific data.

Use ‘Session Storage’ for data that only needs to persist for the duration of a user’s session. The session ends when a browser tab or window is closed by a user. 

Session Storage is a part of web storage API that provides a programmatic interface for developers to interact with the browser’s session storage mechanism.

SessionStorage can replace analytics cookies for session-specific analytics, tracking user behaviour, page views, and interactions during a single session.

This approach is privacy-friendly because data is automatically cleared once the session ends (i.e. when the user closes the browser tab or window).

For example, 

You can track how many pages a user views during a session by using session storage:

1

2

3

4

5

6

7

8

9

10

// Initialize or retrieve the page view count from SessionStorage

let pageViews = parseInt(sessionStorage.getItem('pageViews')) || 0;

 

// Increment the page view count for each page visit

pageViews += 1;

 

// Store the updated page view count in SessionStorage

sessionStorage.setItem('pageViews', pageViews);

 

console.log(`Pages viewed this session: ${pageViews}`);

You can track how many times a user clicks a specific button during the session.

1

2

3

4

5

6

7

8

9

10

11

12

13

// Retrieve or initialize button click count from SessionStorage

let buttonClicks = parseInt(sessionStorage.getItem('buttonClicks')) || 0;

 

// Add an event listener to the button

document.getElementById('subscribeButton').addEventListener('click', function() {

  // Increment the click count each time the button is clicked

  buttonClicks += 1;

 

  // Store the updated click count in SessionStorage

  sessionStorage.setItem('buttonClicks', buttonClicks);

 

  console.log(`Button clicked ${buttonClicks} times this session.`);

});

Tracking items added to a cart using SessionStorage

You can track items added to a shopping cart using SessionStorage by storing the cart data in an array or object, updating it as the user adds items, and retrieving it when needed during the session.

For example, each time a user adds an item to the cart, you update the cart stored in SessionStorage.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

// Function to add an item to the cart

function addItemToCart(item) {

  // Retrieve the current cart from SessionStorage, or initialize an empty array if it doesn't exist

  let cart = JSON.parse(sessionStorage.getItem('shoppingCart')) || [];

 

  // Check if the item already exists in the cart

  let existingItem = cart.find(cartItem => cartItem.id === item.id);

 

  if (existingItem) {

    // If the item already exists, update the quantity

    existingItem.quantity += item.quantity;

  } else {

    // If the item doesn't exist, add it to the cart

    cart.push(item);

  }

 

  // Store the updated cart back in SessionStorage

  sessionStorage.setItem('shoppingCart', JSON.stringify(cart));

 

  console.log('Cart Updated:', cart);

}

 

// Example of adding an item to the cart

addItemToCart({ id: 1, name: 'Laptop', quantity: 1, price: 999.99 });

addItemToCart({ id: 2, name: 'Mouse', quantity: 2, price: 49.99 });

You can retrieve the cart from SessionStorage and display the items on the cart page.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// Function to display cart items

function displayCartItems() {

  // Retrieve the shopping cart from SessionStorage

  let cart = JSON.parse(sessionStorage.getItem('shoppingCart')) || [];

 

  // If the cart is empty, display a message

  if (cart.length === 0) {

    console.log('Your cart is empty.');

    return;

  }

 

  // Display each item in the cart

  cart.forEach(item => {

    console.log(`Item: ${item.name}, Quantity: ${item.quantity}, Price: $${item.price}`);

  });

}

 

// Example of displaying the cart items

displayCartItems();

You can also remove an item from the cart and update SessionStorage.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// Function to remove an item from the cart

function removeItemFromCart(itemId) {

  // Retrieve the cart from SessionStorage

  let cart = JSON.parse(sessionStorage.getItem('shoppingCart')) || [];

 

  // Filter out the item with the given ID

  cart = cart.filter(item => item.id !== itemId);

 

  // Update the cart in SessionStorage

  sessionStorage.setItem('shoppingCart', JSON.stringify(cart));

 

  console.log('Item removed. Updated Cart:', cart);

}

 

// Example of removing an item from the cart

removeItemFromCart(1);  // Removes the item with ID 1

Note: Session Storage is not designed for long-term tracking. If you need to achieve long-term tracking without relying on cookies, consider alternative approaches, such as LocalStorage, server-side storage, or user authentication.

#3 Use Local Storage for storing persistent, non-sensitive data across sessions.

Use ‘Local Storage’ for storing persistent, non-sensitive data across multiple sessions.

Local Storage is a part of web storage API that provides a programmatic interface for developers to interact with the browser’s session storage mechanism.

LocalStorage can replace analytics persistent cookies for storing non-sensitive, persistent data that needs to remain across sessions and page reloads.

This approach is privacy-friendly because, unlike cookies, LocalStorage does not automatically transmit data to the server with each HTTP request, reducing the risk of unwanted data sharing or tracking across different websites.

For example,

You can use LocalStorage to store a unique identifier for each user.

This identifier helps in recognising returning users across multiple sessions:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// Check if the client ID already exists in LocalStorage

let clientId = localStorage.getItem('clientId');

 

if (!clientId) {

  // Generate a new client ID and store it in LocalStorage

  clientId = 'client_' + Date.now() + Math.random().toString(36).substring(2);

  localStorage.setItem('clientId', clientId);

   

  console.log('New client ID generated:', clientId);

} else {

  console.log('Returning user with client ID:', clientId);

}

 

// Send the client ID to GA4

gtag('event', 'identify_user', {

  'client_id': clientId

});

You can store user preferences (such as theme, language, or layout settings) in LocalStorage so that they persist across sessions.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

// Store a user preference in LocalStorage

function setUserPreference(theme, language) {

  localStorage.setItem('theme', theme);

  localStorage.setItem('language', language);

 

  console.log(`User preferences set: Theme = ${theme}, Language = ${language}`);

   

  // Send the user preferences to GA4

  gtag('event', 'set_user_preferences', {

    'theme': theme,

    'language': language

  });

}

 

// Retrieve user preferences from LocalStorage

function getUserPreferences() {

  const theme = localStorage.getItem('theme');

  const language = localStorage.getItem('language');

 

  console.log('Retrieved user preferences:', { theme, language });

   

  return { theme, language };

}

 

// Example usage

setUserPreference('dark', 'en');

const preferences = getUserPreferences();

You can track the number of sessions a user has completed by incrementing a session counter in LocalStorage.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// Retrieve the session count from LocalStorage or initialize it

let sessionCount = parseInt(localStorage.getItem('sessionCount')) || 0;

 

// Increment the session count each time a new session starts

sessionCount += 1;

 

// Store the updated session count in LocalStorage

localStorage.setItem('sessionCount', sessionCount);

 

console.log(`User has completed ${sessionCount} sessions.`);

 

// Send the session count to GA4

gtag('event', 'session_count', {

  'session_count': sessionCount

});

You can store and update the total number of purchases made by a user in LocalStorage.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

// Retrieve the purchase count from LocalStorage or initialize it

let purchaseCount = parseInt(localStorage.getItem('purchaseCount')) || 0;

 

// Function to update purchase count

function recordPurchase() {

  // Increment the purchase count when a purchase is made

  purchaseCount += 1;

 

  // Store the updated purchase count in LocalStorage

  localStorage.setItem('purchaseCount', purchaseCount);

 

  console.log(`User has made ${purchaseCount} purchases.`);

 

  // Send the updated purchase count to GA4

  gtag('event', 'purchase_made', {

    'purchase_count': purchaseCount

  });

}

 

// Example usage: Call recordPurchase() when a purchase is completed

recordPurchase();

#4 Use URL Parameters for cross-page tracking.

You can use URL parameters to pass tracking data from one page to another without relying on cookies or local storage. 

This method is particularly useful when tracking data needs to be persisted across multiple pages but in a privacy-friendly way.

URL parameters are visible in the browser’s address bar and can be easily shared, logged, or cached. 

If sensitive information (like personally identifiable information) is included in URL parameters, it may be exposed to third parties or leaked unintentionally.

Avoid storing sensitive data in URL parameters. If you have to store sensitive data, use anonymised or hashed values. 

Use URL parameters in combination with sessionStorage or localStorage to avoid having to pass the data across every page via URLs.

For example, if you capture the UTM parameters on the landing page, store them in sessionStorage, and use them throughout the session without exposing them in subsequent URLs.

URL parameters offer a privacy-friendly alternative to cookies for passing session data between pages.

Unlike cookies, which are stored on the user’s device, URL parameters are transmitted with each page request. This means that sensitive data is not stored locally.

#5 Use server-side storage for sensitive or long-term tracking.

Server-side storage is a more secure and privacy-friendly approach for handling sensitive or long-term tracking compared to client-side mechanisms like cookies, LocalStorage, or SessionStorage. 

Server-side storage refers to data stored on a web server or in a database that the server manages. 

This data typically relates to user sessions, application state, or preferences.

Server-side storage data is more secure and reliable because it’s not affected by browser settings or user actions (like clearing cookies or switching devices).

Note: Cookies and server storage often work together. But server-side storage can function without cookies.

Key differences between DataLayers, SessionStorage, LocalStorage and ServerStorage

Following are the key differences between DataLayers, SessionStorage, LocalStorage, and ServerStorage in terms of their scope, persistence, and functionality:

Feature

Data Layers

SessionStorage

LocalStorage

Server-Side Storage

Location

Temporary storage in the data layer (client-side).

Stored in the user’s browser (client-side).

Stored in the user’s browser (client-side).

Stored on the server (server-side).

Persistence

Exists for as long as the page/session exists; cleared after use.

Data is cleared when the browser tab or window is closed.

Data persists indefinitely until manually cleared.

Data persists as long as needed, based on server configuration.

Scope

Available during the page lifecycle, shared across scripts and tags.

Specific to a single tab or window (session-specific). Not shared between tabs or windows.

Shared across all tabs and windows for the same origin.

Accessible from any client-side request (via API, session, etc.), independent of the user’s browser or device.

Data Access

Can be accessed by scripts and tags running on the page.

Only available while the browser tab is open.

Available across all sessions until explicitly cleared.

Accessed through HTTP requests (such as REST APIs) or via a session identifier sent from the client.

Size Limit

No fixed size, but used for small data sets.

Typically around 5MB per origin.

Typically around 5MB per origin.

No fixed size limit, determined by server storage capacity.

Visibility

Not visible to the user; only accessible by scripts running on the page.

Data is visible only to client-side scripts running on the same page.

Data is visible to client-side scripts running on the same origin.

Not visible to the client unless requested explicitly via HTTP.

Security

Susceptible to client-side vulnerabilities like XSS but limited scope.

Vulnerable to client-side attacks like XSS (Cross-Site Scripting).

Vulnerable to client-side attacks like XSS.

More secure as it is stored on the server, but requires secure access mechanisms (e.g., SSL, authentication).

Data Lifespan

Temporary; lasts only during the session or page lifecycle.

Exists only for the current session (until the tab is closed).

Persists until manually cleared by the user or programmatically removed.

Can persist for any duration, based on server policies or database configuration.

Use Cases

Triggering real-time events, temporary tracking for analytics or marketing.

Temporary data (e.g., session-specific user interactions, form data).

Persistent data (e.g., user preferences, theme settings, login tokens).

Long-term data storage (e.g., user profiles, transaction data, session management).

Data Sharing

Data can be shared across scripts and tags on the same page.

Data is not shared between tabs, even if they are from the same domain.

Data is shared across all tabs and windows for the same domain.

Data can be shared across devices and sessions, based on user authentication or session tokens.

Availability Across Devices

Not accessible across devices or sessions; only valid during page view.

Not accessible across devices or browsers.

Not accessible across devices or browsers.

Accessible from any device, as long as the user has the appropriate credentials or session information.

Data Management

Managed by the website or tag management system.

Managed by the browser. Can be cleared when the tab or window is closed.

Managed by the browser. Can be cleared manually by the user or programmatically.

Managed by the server. Data management policies (backup, deletion) are controlled by the server or database.

For best results, use server-side storage along with data layers, sessionStorage, localStorage and URL parameters.

Each method complements the others by handling different types of data with various levels of security and persistence, ensuring both user privacy and website functionality.

Scenario: A user visits an e-commerce website, adds a product to their cart, and proceeds to checkout.

Landing Page:

  • The user lands on the website with UTM parameters in the URL.
  • The UTM parameters are captured and added to the data layer.
  • The UTM parameters are stored in local storage for future reference.

Product Page:

  • When a user views a product, the product information (e.g., productId, productName, productPrice) is added to the data layer.
  • The viewed product is added to a session-based “recently viewed” list in session storage.

Cart Page:

  • When a user adds a product to their cart, an ‘addToCart’ event is triggered, and the product information is added to the data layer.
  • The user’s cart items are stored in local storage to persist across sessions.
  • The cart data is sent to the server and stored in a database.

Checkout Page:

  • Checkout events (e.g., ‘checkoutStarted’, ‘checkoutCompleted’) are triggered with relevant data.
  • The checkout data is stored on the server, including customer information, shipping address, and payment details.
  • Any temporary session data, such as shipping methods or coupon codes, is cleared.

By relying on data layers, SessionStorage, LocalStorage, URL parameters, and server-side storage, you can achieve the same functionality traditionally handled by first-party analytics cookies without compromising user experience, functionality, or data privacy. 

#6 Server Side Tracking

GA4 Server Side Tracking is another cookiless tracking method in GA4.

Srver-side tracking allows you to send tracking data directly from your server to GA4, bypassing the need to rely on client-side cookies for user identification and behaviour tracking.

Server-side tracking allows you to overcome ad blockers, cookie consent issues and browser restrictions (such as ITP in Safari or ETP in Firefox), which can block or limit traditional cookie-based tracking.

Since data is processed server-side, you have more control over what data is collected, how it is anonymized, and when it is sent to GA4.

Following is an example of how you might send a page view event from your server to GA4 with the measurement protocol.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

const axios = require('axios');

 

// Function to send a page view event to GA4

function trackPageView(userId, pageTitle, pageLocation) {

  const data = {

    client_id: userId,  // User identifier (can be a custom ID generated server-side)

    events: [

      {

        name: "page_view",

        params: {

          page_title: pageTitle,

          page_location: pageLocation,

        }

      }

    ]

  };

 

  // Send data to GA4 Measurement Protocol

  axios.post('https://www.google-analytics.com/mp/collect?measurement_id=YOUR_GA4_MEASUREMENT_ID&api_secret=YOUR_GA4_API_SECRET', data)

    .then(response => {

      console.log('Page view tracked', response.data);

    })

    .catch(error => {

      console.error('Error tracking page view', error);

    });

}

 

// Example usage: track a page view

trackPageView('user_12345', 'Home Page', 'https://example.com/home');

How to make GA4 Cookiless tracking Privacy Compliant.

Cookieless tracking often leads businesses to rely more on first-party data collection, but it is crucial to understand that first-party data collection does not automatically make you GDPR compliant.

Moving to first-party data collection (via cookiless tracking) is nonsense in terms of privacy compliance because you are still collecting third-party non-essential data but now in a first-party context.

The nature of the data collection often remains the same, even if it is done in a ‘first-party’ context.

When companies shift from third-party to first-party data collection, the data collected often includes the same type of non-essential, tracking-based information that third-party cookies would have previously collected.

In this context, the main privacy concern is not eliminated; it is simply reframed as ‘first-party data collection.’

Whether the data is collected by a first party or a third party, the real privacy issue lies in how the data is used, how much control users have over it, and whether they are aware of its collection.

Many websites that claim to use “first-party” data are still sharing that data with third-party vendors or services (e.g., Google Analytics, Facebook Pixel), even if the data is collected in a first-party context.

In other words, user data is still being funnelled to third-party service providers, but now it’s happening through the first party as an intermediary.

There are only two categories of data collection in terms of privacy compliance: Essential and Non-essential.

Essential data collection is necessary for a website or service’s basic functionality or security (e.g., session management, fraud prevention).

Non-essential data collection refers to data used for purposes like marketing, analytics, personalisation, and tracking, which aren’t required for the core operation of a website but are often used for business or optimisation purposes.

Which means,

Not all first-party cookies (like Google Analytics cookies) are essential cookies. 

Not all third-party cookies are non-essential cookies. 

Not all first-party data collection is privacy-compliant.

Not all third-party data collection is bad for privacy.

The data collection method (first-party vs. third-party) is not the most important factor in privacy compliance. 

What truly matters is the purpose and necessity of the data being collected.

Instead of moving to first-party data collection, focus on privacy-driven data collection. 

It emphasises that privacy is the priority, regardless of whether the data comes from first-party or third-party sources.

Stop being obsessed with first-party and third-party distinctions. Focus on privacy-driven data collection.

The majority of businesses that use GA4 server-side tagging are not GDPR compliant because they don’t display consent banners.

When did you last see a consent banner on a website using server-side tagging?

I am not referring to the cookie banner here.

Just because you use server-side tagging does not mean you no longer need to ask for consent. The cookie banner is replaced by the consent banner.

Server-side tagging doesn’t eliminate the need for consent under GDPR.Users should be informed about how their data is collected and used, even with server-side implementations.You are not GDPR compliant if you don’t display a consent banner.

  1. Web Analytics Career Path – How to Become a Web Analyst.
  2. GA4 Form Interactions Tracking – Enhanced measurement.
  3. How to track form submissions in Google Analytics 4.
  4. How to send data from Google Search Console to BigQuery.
  5. How to fix duplicate events in Google Analytics 4 (GA4).
  6. How to use two Google Analytics codes on one page.
  7. How to import GA4 Conversions into Google Ads.
  8. What are predictive metrics in Google Analytics 4 (GA4).
  9. Google Tag Manager Event Tracking Tutorial.
  10. How to use Google Analytics 4 with iframe.
  11. Why GA4 Audiences not showing in Google Ads.
  12. Google Analytics 4 Scroll Tracking Tutorial.
  13. Why Google Ads and Google Analytics data don’t match & how to fix it.
  14. Google Analytics 4 Calculated Metrics with Examples.
  15. How to view subdomain traffic in Google Analytics 4.
  16. Google Analytics 4 Cookieless Tracking Setup.
  17. Using Funnel Exploration Report in Google Analytics 4.
  18. Google Advanced Consent Mode and GA4 BigQuery Export.
  19. Which Conversion Window to use in Google Analytics 4.
  20. Tracking single page apps in Google Analytics 4.