Similar to using gtag , it is possible to use the Google Analytics Measurement Protocol to send user-provided data along with User-ID, which can be used to improve behavior and conversion measurement.
To send user-provided data along with a Measurement Protocol request, add the user_data
parameter in the JSON payload. The user_id
parameter must be
present whenever user_data
is provided.
The Measurement Protocol is using the same normalization and hashing algorithm
as the Google Ads API Enhanced Measurement
feature.
For privacy concerns, email addresses, phone numbers, first names, last names,
and street addresses must be hashed using the SHA-256
algorithm before
being uploaded. The hashed value should be encoded in hex string format (string
object containing only hexadecimal digits), such as 88d7ecb5c5b21d7b1
.
In order to standardize the hash results, prior to hashing one of these values you must:
- Remove leading and trailing whitespaces.
- Convert the text to lowercase.
- Format phone numbers according to the E164 standard .
- Remove all periods (.) that precede the domain name in
gmail.com
andgooglemail.com
email addresses.
JSON post body
- lowercase
- remove periods before
@
for gmail.com/googlemail.com addresses - remove all spaces
- hash using SHA256 algorithm
- encode with hex string format.
- remove all non digit characters
- add
+
prefix - hash using SHA256 algorithm
- encode with hex string format.
- remove digits and symbol characters
- lowercase
- remove leading and trailing spaces
- hash using SHA256 algorithm
- encode with hex string format.
- remove digits and symbol characters
- lowercase
- remove leading and trailing spaces
- hash using SHA256 algorithm
- encode with hex string format.
- remove symbol characters
- lowercase
- remove leading and trailing spaces
- hash using SHA256 algorithm
- encode with hex string format.
- remove digits and symbol characters
- lowercase
- remove leading and trailing spaces.
- remove digits and symbol characters
- lowercase
- remove leading and trailing spaces.
- remove
.
and~
characters - remove leading and trailing spaces.
See the Measurement Protocol reference documentation for more information about how the transport and payload are formatted.
Send User-provided Data
Unlike gtag , which automatically hashes sensitive user-provided data, the Measurement Protocol requires a developer to hash sensitive user-provided data using a secure one-way hashing algorithm called SHA256 and encode it using hex string format prior to calling the API.
All user data fields starting with the sha256
prefix in their name should be
only populated with hashed and hex-encoded values.
The following example code performs the necessary encryption and encoding steps:
Node.js
const
{
subtle
}
=
require
(
'crypto'
).
webcrypto
;
async
function
populateSensitiveUserData
(
value
)
{
const
encoder
=
new
TextEncoder
();
// Convert a string value to UTF-8 encoded text.
const
valueUtf8
=
encoder
.
encode
(
value
);
// Compute the hash (digest) using the SHA-256 algorithm.
const
hashSha256
=
await
subtle
.
digest
(
'SHA-256'
,
valueUtf8
);
// Convert buffer to byte array.
const
hashArray
=
Array
.
from
(
new
Uint8Array
(
hashSha256
));
// Return a hex-encoded string.
return
hashArray
.
map
(
b
=
>
b
.
toString
(
16
).
padStart
(
2
,
"0"
)).
join
(
''
);
};
// Test the encryption function by calling it.
async
function
main
()
{
return
await
populateSensitiveUserData
(
'<value>'
);
}
main
()
.
then
(
v
=
>
console
.
log
(
v
))
.
catch
(
err
=
>
console
.
error
(
err
));
As a convenience shortcut, all repeated fields inside the user_data
object
(such as address
, sha256_email_address
, sha256_phone_number
) can be
passed a singular value instead of an array.
The following sample code calls the Measurement Protocol and passes user data along with User-ID.
Node.js
const
measurementId
=
" MEASUREMENT_ID
"
;
const
apiSecret
=
" API_SECRET
"
;
// Populate mock User Data using the `populateSensitiveUserData` function defined
// above.
const
yourEmailSha256Variable
=
await
populateSensitiveUserData
(
'test@yourdomain.com'
);
const
yourPhoneSha256Variable
=
await
populateSensitiveUserData
(
'+15555555555'
);
const
yourFirstNameSha256Variable
=
await
populateSensitiveUserData
(
'john'
);
const
yourLastNameSha256Variable
=
await
populateSensitiveUserData
(
'doe'
);
const
yourStreetAddressSha256Variable
=
await
populateSensitiveUserData
(
'123 main street'
);
// Populate mock unencrypted user data.
const
yourCityVariable
=
'san francisco'
;
const
yourRegionVariable
=
'california'
;
const
yourPostalCodeVariable
=
'94000'
;
const
yourCountryVariable
=
'US'
;
fetch
(
`https://www.google-analytics.com/mp/collect?measurement_id=
${
measurementId
}
& api_secret=
${
apiSecret
}
`
,
{
method
:
"POST"
,
body
:
JSON
.
stringify
({
client_id
:
" CLIENT_ID
"
,
user_id
:
" USER_ID
"
,
events
:
[{
name
:
"purchase"
}],
user_data
:
{
sha256_email_address
:
yourEmailSha256Variable
,
sha256_phone_number
:
yourPhoneSha256Variable
,
address
:
{
sha256_first_name
:
yourFirstNameSha256Variable
,
sha256_last_name
:
yourLastNameSha256Variable
,
sha256_street
:
yourStreetAddressSha256Variable
,
city
:
yourCityVariable
,
region
:
yourRegionVariable
,
postal_code
:
yourPostalCodeVariable
,
country
:
yourCountryVariable
}
}
})
});
Multiple values
Developers can optionally provide multiple values (up to 3 for phone and email and 2 for address) by using an array value rather than a string. If you capture more than one value, providing this will increase the likelihood of a match.
Node.js
const
measurementId
=
" MEASUREMENT_ID
"
;
const
apiSecret
=
" API_SECRET
"
;
fetch
(
`https://www.google-analytics.com/mp/collect?measurement_id=
${
measurementId
}
& api_secret=
${
apiSecret
}
`
,
{
method
:
"POST"
,
body
:
JSON
.
stringify
({
client_id
:
" CLIENT_ID
"
,
user_id
:
" USER_ID
"
,
events
:
[{
name
:
"purchase"
}],
user_data
:
{
sha256_email_address
:
[
yourEmailSha256Variable1
,
yourEmailSha256Variable2
],
sha256_phone_number
:
[
yourPhoneSha256Variable1
,
yourPhoneSha256Variable2
],
address
:
[{
sha256_first_name
:
yourFirstNameSha256Variable1
,
sha256_last_name
:
yourLastNameSha256Variable1
,
sha256_street
:
yourStreetAddressSha256Variable1
,
city
:
yourCityVariable1
,
region
:
yourRegionVariable1
,
postal_code
:
yourPostalCodeVariable1
,
country
:
yourCountryVariable1
},{
sha256_first_name
:
yourFirstNameSha256Variable2
,
sha256_last_name
:
yourLastNameSha256Variable2
,
sha256_street
:
yourStreetAddressSha256Variable2
,
city
:
yourCityVariable2
,
region
:
yourRegionVariable2
,
postal_code
:
yourPostalCodeVariable2
,
country
:
yourCountryVariable2
}]
}
})
});