A flexible Server GTM variable template for building structured JSON objects from flat key/value pairs and grouped JSON rows. Returns a JSON string that can be used in any GTM tag or variable.
→ Designed for creating structured payloads for BigQuery, API tags, and other JSON-based integrations.
JSON Object Builder lets you construct JSON objects in Server GTM using two complementary configuration layers:
- Flat JSON Fields
Define top-level key/value pairs directly - Grouped JSON Objects
Build nested one-level JSON objects by grouping related key/value pairs
Built for setups where:
- You need to create JSON payloads from GTM variables
- Structured data is required for BigQuery, APIs, or other integrations
- You want to combine flat fields with nested JSON structures
- Predictable, sorted JSON output is needed
- Pure Server GTM variable template (no client-side code)
- Two-layer JSON builder:
✔ Flat fields
✔ Grouped JSON objects - Optional empty value filtering
- Alphabetical key sorting (top-level and nested)
- Debug logging (toggle via checkbox)
- Returns JSON string usable in any GTM tag or variable
- Automatic string conversion for consistent output
- Grouped objects override flat keys with the same name
- Fully compatible with BigQuery JSON columns and API payloads
| 🔍 Problem | ✅ JSON Object Builder Solution |
|---|---|
| Need to build JSON objects from multiple GTM variables | Flat JSON Fields configuration lets you map variables to JSON keys |
Want to group related key/value pairs into nested objects (e.g. user, device, geo) |
Grouped JSON Objects automatically groups rows by Group Key and creates nested structures |
| Complex custom JavaScript for simple JSON building | Lightweight template focused on explicit field mapping and JSON grouping |
| Hard to debug what JSON is being generated | Built-in debug logging shows the final object structure |
| Need predictable, sorted JSON output | Optional alphabetical key sorting for stable output |
| Want to ignore empty values automatically | Optional empty value filtering skips undefined, null, or empty string values |
| Need JSON strings for BigQuery or API tags | Returns JSON string directly usable in any GTM tag or variable |
Templates → Variable Templates → Import → select .tpl file
Select JSON Object Builder from the variable type dropdown
Add top-level key/value pairs that will appear directly in the JSON object.
Example:
- Key:
event_name, Value:{{Event Name}} - Key:
event_date, Value:{{Date}} - Key:
session_id, Value:{{Session ID}}
Add grouped key/value pairs that will be nested under a Group Key.
Example:
- Group Key:
user, JSON Key:id, JSON Value:{{User ID}} - Group Key:
user, JSON Key:email, JSON Value:{{User Email}} - Group Key:
device, JSON Key:os, JSON Value:{{Operating System}} - Group Key:
device, JSON Key:browser, JSON Value:{{Browser}}
- Ignore empty values
If enabled, rows with empty, undefined, or null values will be skipped - Sort keys alphabetically
If enabled, all top-level and nested JSON keys will be sorted alphabetically - Enable Debug Logging
Check this during development to see the final JSON object in the console
Reference the variable in any GTM tag or other variable that needs a JSON string.
Common Use Cases:
- BigQuery tag payloads
- API request bodies
- Custom HTML tags
- Other variable templates that accept JSON strings
Purpose:
Define top-level key/value pairs that appear directly in the JSON object.
Structure:
- Key: The JSON key name (e.g.
event_name,session_id) - Value: The value to use (can use GTM variables like
{{Event Name}}) - Type (optional): Type hint (currently reserved for future use)
Example:
| Key | Value | Type |
|---|---|---|
event_name |
{{Event Name}} |
String |
event_date |
{{Date}} |
String |
session_id |
{{Session ID}} |
String |
user_id |
{{User ID}} |
String |
Result:
{
"event_name": "page_view",
"event_date": "2025-01-15",
"session_id": "abc123",
"user_id": "user456"
}Behavior:
- Empty values are ignored if "Ignore empty values" is enabled
- Values are converted to strings
- Keys appear at the top level of the JSON object
Purpose:
Build nested one-level JSON objects by grouping related key/value pairs.
Structure:
- Group Key: The name of the nested object (e.g.
user,device,geo) - JSON Key: The key within the nested object
- JSON Value: The value for that key
Example:
| Group Key | JSON Key | JSON Value |
|---|---|---|
user |
id |
{{User ID}} |
user |
email |
{{User Email}} |
user |
role |
{{User Role}} |
device |
os |
{{Operating System}} |
device |
browser |
{{Browser}} |
geo |
country |
{{Country}} |
geo |
city |
{{City}} |
Result:
{
"user": {
"id": "user123",
"email": "user@example.com",
"role": "premium"
},
"device": {
"os": "iOS",
"browser": "Safari"
},
"geo": {
"country": "DE",
"city": "Berlin"
}
}Behavior:
- All rows with the same Group Key are combined into one nested object
- Values are converted to strings inside the nested object
- Grouped objects override flat keys with the same name (if both exist)
- Empty values are ignored if "Ignore empty values" is enabled
You can combine both configuration types in a single variable:
Flat Fields:
event_name→page_viewevent_date→2025-01-15
Grouped Fields:
user→{ "id": "123", "email": "user@example.com" }device→{ "os": "iOS", "browser": "Safari" }
Result:
{
"event_name": "page_view",
"event_date": "2025-01-15",
"user": {
"id": "123",
"email": "user@example.com"
},
"device": {
"os": "iOS",
"browser": "Safari"
}
}Important: If a flat field and a grouped object have the same key name, the grouped object will override the flat field.
| Setting | Description | Default |
|---|---|---|
| Ignore empty values | If enabled, rows with empty, undefined, or null values will be skipped | false |
| Sort keys alphabetically | If enabled, all top-level and nested JSON keys will be sorted alphabetically | false |
| Enable Debug Logging | Logs the final JSON object to the Server GTM console in Preview/Debug mode | false |
Flat Fields:
event_id→{{Event ID}}event_ts→{{Timestamp}}event_name→{{Event Name}}event_date→{{Date}}
Grouped Fields:
cd_id_values→{ "email_sha256": "{{Email SHA256}}", "phone_sha256": "{{Phone SHA256}}" }device_context→{ "os": "{{OS}}", "browser": "{{Browser}}" }geo→{ "country": "{{Country}}", "city": "{{City}}" }
Result:
{
"event_id": "evt_123",
"event_ts": "1705324800000",
"event_name": "page_view",
"event_date": "2025-01-15",
"cd_id_values": {
"email_sha256": "abc123...",
"phone_sha256": "def456..."
},
"device_context": {
"os": "iOS",
"browser": "Safari"
},
"geo": {
"country": "DE",
"city": "Berlin"
}
}Flat Fields:
action→tracktimestamp→{{Timestamp}}
Grouped Fields:
properties→{ "page_url": "{{Page URL}}", "page_title": "{{Page Title}}" }user→{ "id": "{{User ID}}", "email": "{{User Email}}" }
Result:
{
"action": "track",
"timestamp": "1705324800000",
"properties": {
"page_url": "https://example.com/page",
"page_title": "Example Page"
},
"user": {
"id": "user123",
"email": "user@example.com"
}
}Flat Fields Only:
event_name→{{Event Name}}session_id→{{Session ID}}user_id→{{User ID}}
Result:
{
"event_name": "page_view",
"session_id": "sess_123",
"user_id": "user_456"
}When Enable Debug Logging is checked, the template logs the final JSON object to the Server GTM console.
Example Console Output:
JSON Object Builder - result object: {"event_name":"page_view","event_date":"2025-01-15","user":{"id":"123","email":"user@example.com"}}
Use Cases:
- Verify JSON structure during development
- Inspect nested object grouping
- Troubleshoot empty value filtering
- Validate key sorting behavior
When Sort keys alphabetically is enabled:
- Top-level keys are sorted alphabetically
- Nested object keys (within grouped objects) are also sorted alphabetically
- Sorting happens after all fields are merged
- Useful for stable, predictable JSON output
Example without sorting:
{
"zebra": "value1",
"apple": "value2",
"banana": {
"zebra": "inner1",
"apple": "inner2"
}
}Example with sorting:
{
"apple": "value2",
"banana": {
"apple": "inner2",
"zebra": "inner1"
},
"zebra": "value1"
}When Ignore empty values is enabled:
- Rows with
undefinedvalues are skipped - Rows with
nullvalues are skipped - Rows with empty string (
"") values are skipped - Applies to both flat fields and grouped fields
Example:
Input:
event_name→page_view(kept)user_id→ `` (empty, skipped)session_id→{{Undefined Variable}}(undefined, skipped)
Result:
{
"event_name": "page_view"
}All values are automatically converted to strings:
- Numbers → String (e.g.
123→"123") - Booleans → String (e.g.
true→"true") - Objects → String (e.g.
{a:1}→"[object Object]") - Arrays → String (e.g.
[1,2,3]→"1,2,3")
Note: If you need to preserve types (numbers, booleans), parse the JSON string after receiving it, or handle type conversion in your downstream system (e.g. BigQuery schema).
The template handles edge cases gracefully:
- Missing rows: Empty arrays are handled correctly
- Invalid row structure: Rows without required fields are skipped
- Empty values: Handled based on "Ignore empty values" setting
- Type conversion: All values are safely converted to strings
Behavior:
- Missing
builderKeyin flat rows → Row is skipped - Missing
builderGroupNameorbuilderGroupKeyin grouped rows → Row is skipped - Empty arrays → Returns empty object
{} - All values → Converted to strings for consistent output
- Server GTM Container: This template runs in Server GTM only
- Logging Permission: Required for debug logging (automatically configured)
- GTM Variables: Any GTM variables can be used as field values
Use JSON Object Builder to create structured payloads for BigQuery:
- Create a JSON Object Builder variable with your event structure
- Use the variable in a BigQuery Data Dispatcher tag
- The JSON string will be parsed and sent to BigQuery
Use the JSON string directly in Custom HTML tags:
<script>
var eventData = {{JSON Object Builder Variable}};
// Use eventData as a JavaScript object
</script>Use the JSON string as the request body in HTTP Request tags:
- Request Body:
{{JSON Object Builder Variable}} - Content-Type:
application/json
MIT – see LICENSE
/ MEDIAFAKTUR – Marketing Performance Precision, https://mediafaktur.marketing
Florian Pankarter, fp@mediafaktur.marketing