APP + WEB: Google Analytics Measurement Protocol version 2

The Google Analytics Measurement Protocol allows users and developers to make HTTP requests directly to Google Analytics endpoint in order to measure how users interact from any enviroment/platform.

Since Google announced the new APP+WEB Properties back in summer, we noticed that the &v parameter that used to hold a fixed 1 value turned to be a =2 value in our hit requests. Which implicitily means that at some point a new version of the Measurement Protocol is going to be released.

I tried to reverse-engineer all the details I could about the parameters used on this new upcoming protocol.

Please have in mind that the , and I’m publishing all the info I was able to gather.


The new Measurement Protocol cames with some great new improvements over the version 1 that we’re used to see in our Universal Analytics hits.

I’d try to think about this new protocol as an enhanced version of the previous one. They even share some parameters.

What’s new on the version 2 protocol

This new measurement protocol seems to had been designed having some performance optimizations in mind.

First thing we need to have in mind is that APP+WEB doesn’t longer have “hit types“, everything we may end sending to APP+WEB is an “event” that may (or may not) be accompanied with parameters.

There 2 groups of parameters in the APP+WEB Measurement Protocol .
Let’s think about them as the event parameters “scope“.

  • Event Related Parameters ( ep.* , epn.* )
  • User Related Parameters ( up.* , upn.* )

Also the parameters accepts 2 diferente values types:

Batched Events

Now by default APP+WEB Protocol allows to send batched events, meaning that with a single hit request we’ll be able to send multiple events. I know this is not new at all, and we ever needed to debug an APP implemention we’d have noticed that version 1 protocol allowed us to send batched hits ( via /batch endpoint ).

In any case v2, comes with some extra enhanced comparted with the legacy version,

  • Events within a single hit request share parameters. So the hits payload will the smaller. for example won’t make much sense sending the &dl document.location for all the events if that’s a shared value across all event within the current hit.
  • POST is now the only accept Method. This will bypass the old GET 1082 bytes limit.


Debugging the new measurument protocol v2 has became even easier, since the new properties offer a Debug View.

In order to have our hits showing up here, we’ll need to add a _dbg=1 parameter to our hits.


Then our hits will show up in the DebugView report in real time, making our debugging efforts much easier that they actual are.

Turning on the debug on the web based library

If you’re working on a website based implementation you can turn on the “oficial” debugging logs just loading the GTAG container with the &dbg={{randomNumber}} parameter:

This will turn on the debug output into our browser, giving us a log of detailed info about what’s happening.

Building a request

APP+WEB hits need to go to a new endpoint that is located on the following URL:

As we mentioned in our technical overview for the new APP+WEB Properties now the hits al built in 2 separate parts:

  • URL QueryString will hold the common parameters
  • Request Payload ( POST ), this will hold the events related data.

The Request Payload will only be available when there’re more than 1 event on the current hit request. If the hit only contains one event, the parameter will be attached to the QueryString as the rest of the common shared parameters

The following code will help us to understand how should be build a hit, and also how to send it to APP+WEB Endpoint using the navigator.sendBeacon function.

// APP+WEB Endpoint
var endPoint = '';

// Base Event Model for Web Hit
var eventModel = {
    v: 2,
    tid: 'G-XXXXXXXX-0',
    _p: Math.round(2147483647 * Math.random()),
    sr: screen.width + 'x' + screen.height,
    _dbg: 1,
    ul: (navigator.language || "").toLowerCase(),
    cid: '1908161148.1586721292',
    dl: '',
    dr: '',
    dt: 'APP + WEB Measurement Protocol version2 DEMO',
    sid: new Date() * 1,
    _s: 1

// A queue to batch our events
var events = [];

var requestQueryString;
var requestBody;

// Let's push some events 
    'en': 'pageview'
// Second Event
    'en': 'scroll',
    '_et': '5000',
    'epn.percent_scrolled': '90'
// Another more event
    'en': 'useless_no_bounce_event',
    '_et': '5000',
    'ep.no_bounce_time': '5sec'

// Is there any event in our queue?
if (events.length > 0) {
    // If there's only one event, we'll not pushing a body within our request
    if (events.length === 1) {
        Object.assign(eventModel, events[0]);
    } else {
        requestBody = {
            return (Object.keys(e).map(key=>key + '=' + e[key]).join('&'));
    requestQueryString = Object.keys(eventModel).map(key=>key + '=' + encodeURIComponent(eventModel[key])).join('&');
    navigator.sendBeacon(endPoint + '?' + requestQueryString, requestBody);
APP + Web Measurement Protocol v2 Hit Example . Just 1 Event

Parameters Reference

Request Parameters

These parameters are available across all hits. There are related to the current hit.

ParameterValue TypeValue
vintProtocol Version
tidstringStream ID ( G-XXXXXXXXX )
cidstringClient ID Value
sidstringSession ID . ( current session start TimeStamp )
srstringScreen Resolution
_dbgboolDebug Switch
ulstringUser Language
gtmstringContainer Hash
_sintegerSession Hits Count

Shared Parameters

ParameterValue TypeValue
dlstring (url)Document Location
drstring (url)Document Referer
dtstringDocument Title
sidstringSession ID
sctintegerSession Count
segbooleanSession Engagement
_fvboolFirst Visit
_nsiboolNew Session Id
_ssboolSession Start
custringCurrency Code

Event Parameters

ParameterValue TypeValue
enstringEvent Name
_etintegerEvent Time
up.*stringUser Parameter String
upn.*numberUser Parameter Number
ep.*stringEvent Parameter String
epn.*numberEvent Parameter Number


NOTE: I want to add that this was live on the latest gtag version one week ago, and that it seems it has been removed. In any case I wouldn’t expect to have changes on the final release.

We’re splitting the parameters related to the Ecommerce on 3 categories. We need to have in mind that APP+WEB have 2 main groups of models for the Enhanced Ecommerce, the Products Model and the Promotions Model.

Products Model, is used in every single ecommerce event that is sent to Google Analytics . Which includes product listings, products clicks, product details views, products adds to cart, products remove from cart, product checkout, products purchases and products refunds.

Promotions Model, this is the second model, this is for the promotions tracking in the Enhanced Ecommerce, since they’re not directly related to a product this is a total aside model used on APP+WEB

  • Product Items ( Shared Product Related data )
  • Product List Details ( Product Lists Related data , this goes along with Product Items )
  • Promotions

Product Items

Products Items are send under it’s own incremental key, &pr1, &pr2&prN . Then each of these parameters will hold all the product model info.


&pr1': 'idP12345~nmAndroid Warhol T-Shirt~lnSearch Results~brGoogle~caApparel/T-Shirts~vaBlack~lp1~qt2~pr2.0',

As you can see we can split the data within this parameter key by the tilde character ( ~ ) to be able to see a proper Product Model

id: P12345
nm: Android Warhol T-Shirt
ln: Search Results
br: Google
ca: Apparel/T-Shirts
va: Black
qt: 2
pr: 2.0
ParameterValue TypeValue
pr[0-9]idstringProduct ID/Sku
nmstringProduct Name
brstringProduct Brand
castringProduct Category Hierarchy Level 1
ca2stringProduct Category Hierarchy Level 2
ca3stringProduct Category Hierarchy Level 3
ca4stringProduct Category Hierarchy Level 4
ca5stringProduct Category Hierarchy Level 5
vastringProduct Variant
prnumberProduct Unit Price
qtintegerProduct Quantity
cpstringProduct Coupon
dsnumberProduct Discount

Product Impressions

These are the Measurement Protocol related parameters to the products Impressions. They are complimentary to the product items. Expect these on the product impressions and product clicks events

ParameterValue TypeValue
lnstringList Name
listringList ID
lpstringList Position

Transaction Related Data

The next table shows the parameters related to the transacion info.

ParameterValue TypeValue
ep.transaction_idstringTransaction ID
ep.affiliationstringTransactionm Affiliation
epn.valuenumberTransaction Revenue
epn.taxnumberTransaction Tax
epn.shippingnumberTransaction Shipping
ep.couponstringTransaction Coupon


And finally the next table shows the parameters related to the promotions tracking. We should expect these parematers to be showing up into the promotion views and promotion clicks events

ParameterValue TypeValue
pistringPromotion ID
pnstringPromotion Name
cnstringCreative Name
csstringCreative Slot (Position )
lostringLocationo ID


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.