Blog
The user_data object is where Meta, TikTok, and others expect matching keys. Six common shapes and how to extract them.
When your client GTM forwards an event to your server container, the user data (email, phone, click IDs) is bundled into a parameter that the server-side tag templates know how to read. The shape of that parameter varies by source, and getting it wrong is the most common reason CAPI events match badly.
GA4's recommended shape:
{
"user_data": {
"email_address": "jane@example.com",
"phone_number": "+15551234567",
"address": [{"first_name": "Jane", "last_name": "Doe"}]
}
}
In sGTM, read this with getEventData('user_data.email_address'). The dot notation traverses the nested object.
Meta uses a flat object with two-character keys:
{
"user_data": {
"em": "",
"ph": "",
"fn": "",
"ln": ""
}
}
Already hashed by the Pixel before it reaches your server. Do not hash again.
TikTok uses descriptive keys but expects raw values, hashing them on the way out:
{
"context": {
"user": {
"external_id": "",
"email": "",
"phone": ""
}
}
}
If you are receiving from the TikTok Pixel and forwarding to TikTok's CAPI, hash before forwarding. The same normalisation rules apply.
If your team built a custom data layer, the shape is whatever your team decided. Common patterns: a flat object at the top level, or nested under a user key. Whatever it is, document it. The next person who touches your tags will need to know.
const email = getEventData('user_data.email_address')
|| getEventData('user_data.em')
|| getEventData('context.user.email')
|| getEventData('user.email');
A defensive read that works across the four common shapes. Useful when your container receives events from multiple sources with inconsistent conventions. Keep the order intentional: the first match wins, so list the canonical form first.