Skip to content

Instantly share code, notes, and snippets.

@sahava
Created October 6, 2021 10:32
Show Gist options
  • Save sahava/4f9662a57ea812c5ddbd811d5c965a33 to your computer and use it in GitHub Desktop.
Save sahava/4f9662a57ea812c5ddbd811d5c965a33 to your computer and use it in GitHub Desktop.
Server-side GTM tag template for Amplitude Analytics
___INFO___
{
"type": "TAG",
"id": "cvt_temp_public_id",
"version": 1,
"securityGroups": [],
"displayName": "Amplitude Analytics",
"brand": {
"id": "brand_dummy",
"displayName": "",
"thumbnail": "data:image/png;base64,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\u003d"
},
"description": "",
"containerContexts": [
"SERVER"
]
}
___TEMPLATE_PARAMETERS___
[
{
"type": "TEXT",
"name": "apiKey",
"displayName": "API Key",
"simpleValueType": true,
"valueValidators": [
{
"type": "NON_EMPTY"
}
]
},
{
"type": "CHECKBOX",
"name": "hideIp",
"checkboxText": "Hide User IP Address",
"simpleValueType": true,
"defaultValue": false
},
{
"type": "SIMPLE_TABLE",
"name": "eventProps",
"displayName": "Event Properties",
"simpleTableColumns": [
{
"defaultValue": "",
"displayName": "Event Data Key",
"name": "key",
"type": "TEXT",
"isUnique": true
},
{
"defaultValue": "",
"displayName": "Parameter Name (optional)",
"name": "mapKey",
"type": "TEXT"
}
],
"newRowButtonText": "Add Event Property"
},
{
"type": "SIMPLE_TABLE",
"name": "userProps",
"displayName": "User Properties",
"simpleTableColumns": [
{
"defaultValue": "",
"displayName": "Event Data Key",
"name": "key",
"type": "TEXT",
"isUnique": true
},
{
"defaultValue": "",
"displayName": "Parameter Name (optional)",
"name": "mapKey",
"type": "TEXT"
}
],
"newRowButtonText": "Add User Property"
}
]
___SANDBOXED_JS_FOR_SERVER___
// Enter your template code here.
const getEventData = require('getEventData');
const getRemoteAddress = require('getRemoteAddress');
const getTimestampMillis = require('getTimestampMillis');
const JSON = require('JSON');
const log = require('logToConsole');
const makeInteger = require('makeInteger');
const sendHttpRequest = require('sendHttpRequest');
const httpEndpoint = 'https://api2.amplitude.com/2/httpapi';
const ga4UserPropPrefix = 'x-ga-mp2-user_properties.';
const apiKey = data.apiKey;
const userIp = data.hideIp ? '$remote' : getRemoteAddress();
const userId = getEventData('user_id') || getEventData(ga4UserPropPrefix + 'user_id') || undefined;
const deviceId = getEventData('client_id');
const sessionId = makeInteger(getEventData('ga_session_id') + '000');
const timestamp = getTimestampMillis();
const eventType = getEventData('event_name');
const getEventProps = () => {
const props = {};
data.eventProps.forEach(p => {
if (getEventData(p.key)) props[(p.mapKey || p.key)] = getEventData(p.key);
});
return props;
};
const getUserProps = () => {
const props = {};
data.userProps.forEach(p => {
if (getEventData(p.key)) props[(p.mapKey || p.key)] = getEventData(p.key);
});
return props;
};
const event = {
device_id: deviceId,
event_type: eventType,
time: timestamp,
event_properties: getEventProps(),
user_properties: getUserProps(),
ip: userIp,
session_id: sessionId,
insert_id: deviceId + eventType + timestamp
};
if (userId) event.user_id = userId;
const postBody = {
api_key: apiKey,
events: [event]
};
sendHttpRequest(httpEndpoint, (statusCode, headers, body) => {
if (statusCode >= 400) {
data.gtmOnFailure();
} else {
data.gtmOnSuccess();
}
}, {headers: {'content-type': 'application/json'}, method: 'POST', timeout: 1000}, JSON.stringify(postBody));
___SERVER_PERMISSIONS___
[
{
"instance": {
"key": {
"publicId": "read_request",
"versionId": "1"
},
"param": [
{
"key": "requestAccess",
"value": {
"type": 1,
"string": "any"
}
},
{
"key": "headerAccess",
"value": {
"type": 1,
"string": "any"
}
},
{
"key": "queryParameterAccess",
"value": {
"type": 1,
"string": "any"
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
},
{
"instance": {
"key": {
"publicId": "logging",
"versionId": "1"
},
"param": [
{
"key": "environments",
"value": {
"type": 1,
"string": "debug"
}
}
]
},
"isRequired": true
},
{
"instance": {
"key": {
"publicId": "read_event_data",
"versionId": "1"
},
"param": [
{
"key": "eventDataAccess",
"value": {
"type": 1,
"string": "any"
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
},
{
"instance": {
"key": {
"publicId": "send_http",
"versionId": "1"
},
"param": [
{
"key": "allowedUrls",
"value": {
"type": 1,
"string": "specific"
}
},
{
"key": "urls",
"value": {
"type": 2,
"listItem": [
{
"type": 1,
"string": "https://api2.amplitude.com/2/httpapi"
}
]
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
}
]
___TESTS___
scenarios: []
___NOTES___
Created on 06/10/2021, 13:31:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment