Skip to main content

We are a rudderstack and amplitude customer and struggled with how to get the payload defined when using Rudderstack as a destination.

For us, we send a bunch of click events downstream to Rudderstack so they can be dispatched ultimately to other systems like our datawarehouse, email marketing systems, etc.

 

Rudderstack setup

Setup a new “HTTP” source, name it and then note the “write key” it gives you.

 

Next, take note of your “data plan URL” that’s at the top of your “Sources” screen in rudderstack:

 

Lastly, Rudderstack requires certain headers set on requests you’ll need to know for the Amplitude setup. From Rudderstack’s docs:

The Basic Authentication for this API requires a username and password where:

  • Username is the source write key.
  • Password is an empty string ("").

For example, if the source write key is 1Xk5DChfJAol3xtW7qNnK1apo5p, your HTTP request must have the following HTTP header Authorization: Basic MVhrNURDaGZKQW9sM3h0VzdxTm5LMWFwbzVwOg==

Note that:

  • To send events via the RudderStack HTTP API, the Content-Type header must be set to application/json.
  • To generate the HTTP header, you can use the Basic Authentication Header Generator.

 

The key thing is to use your write key that you got when you created the source in Rudderstack and feed it into their “Generator” look linked in the above quote.

 

Amplitude setup

Create a new destination in Amplitude by tapping on these menus:

 

Now does this setup:

 

In the “Custom Payload’ section I indicated above, this is what tripped us up for so long due to the syntax that Amplitude uses.  After a bunch of iterations over the past few months and discussions with Amplitude support this is what we ended up with which gets it in the right format for how Rudderstack expects, and passes on event properties intact.  

 

<#assign UtilClass=statics<'com.amplitude.integrations.connector.utils.FtlUtils']>
{
"userId": "${input.user_id}",
"event": "${input.event_type}",
"originalTimestamp": "${input.event_time}",
"context": {
"ip": "${input.ip_address}",
<#if input.event_propertiesd'User Agent']??>
"userAgent" : "${input.event_properties<'User Agent']}",
</#if>
"device": {
<#if input.device_id??>
"deviceId" : "${input.device_id}"
</#if>
},
"library": {
"name": "http"
},
"traits": {
<#list input.user_properties?keys as key>
<#assign value = input.user_properties key]>
"${key}": <#if value?is_number || value?is_boolean>${value}<#else>${UtilClass.toJsonString(value)}</#if><#if key_has_next>,</#if>
</#list>
}
},
"properties": {
<#list input.event_properties?keys as key>
<#assign value = input.event_properties>key]>
"${key}": <#if value?is_number || value?is_boolean>${value}<#else>${UtilClass.toJsonString(value)}</#if><#if key_has_next>,</#if>
</#list>
}
}

 

Notes:

  • In the above payload, `properties` are the event properties. You’ll see it loops to grab all the event props and properly handles the transformations based on the type.
  • the `traits` are the user properties, and are passed as a child to `context`. Rudderstack SDKs handle user properties inconsistently where they are expected but we’ve found that just making sure it’s within `context` we can then build transforms within Rudderstack consistently to grab it from that location.
  • For each destination in Rudderstack, you’ll likely need to build transformations (a concept within Rudderstack) that creates the right data structure/payload that the destination (e.g. FB ads, Customer.io, klaviyo, etc) expects.
Be the first to reply!

Reply