Actions
UpdatedHere’s a quick demonstration showing how actions work and how easy it is to change data structures to fit your needs.
How it works
You might send an identify
call or a track
event from a source to Customer.io, but we have to reshape that data to fit the kinds of requests and data your destination expects.
That’s what an action does: it determines when we send data to your destination and how we map data to your destination.
The when is what we call a trigger. You’ll see the trigger on the Actions page for any destination. It’s the formula that tells us what kinds of source events result in a destination event.
The how are the Actions that we use. Because your destination expects data in a specific shape, we map source data to the shape your destination to the calls and payload-shapes your destination expects.
In most cases, our default actions are all you’ll need
We’ve set up actions to support the majority of use cases and expected data structures. You’ll only want to change these if you aren’t using the out-of-the-box functionality with your destination.
destination trigger} b-->|yes|c(Map data to
destination) b-.->|no|d(Event is not
forwarded to destination)
How many actions should I have?
The Type determines the kinds of things your source data can do in your destination. In general, you won’t have more actions than you have types!
By default, when you set up a new destination, you’ll see an action for every available Type.
Action types
An action Type is the thing that you want to do in your destination.
For example, you’ll notice that the top type in our Customer.io destination is the Create or Update Person action. This is a fundamental action in Customer.io Journeys and maps nicely to an Identify call.
You can add/update and delete devices to, but these don’t map neatly to a source method, so we look for events called Application Installed and Uninstalled!
Because different destinations serve different purposes, action types differ by destination.
Triggers and Filters
A Trigger determines when we send an action of the specified Type. It’s governed by conditions in the Filter field when you edit an action.
There are two typical filter fields:
type
represents the kinds of methods sent from our source libraries:identify
,track
,page
,screen
,group
, andalias
.event
represents thename
field fromtrack
calls. Unlike other calls, track calls simply represent custom events, and the eventname
tells us what kind of event a person performed.
You can also filter based on other fields, but we’d recommend that you not get too granular with filters or you could inadvertently prevent data from reaching your destination!
Triggers on the Actions Tab | Filters within an Action |
---|---|
Data Structure
The Data Structure for each action determines the source data that we set for the fields that your destination expects. Data structures use JSON notation for variables—but you don’t necessarily need to know JSON notation to change values. When you opt to change a mapping on the left, we’ll give you a drop-down of available Variables that you can select from incoming source payloads.
In most cases, if you want to manipulate values, you’ll want to do it at your source—in your code. But we offer a couple of functions that can make things a little easier on you. Read more about the case and coalesce functions below.
Pick variables that match your source filter
The list of available variables covers all possible source events. It isn’t limited to the type
or event
in your source filter. If the action is based on an incoming identify
event, and you try to map a field to $.event
, that field will always be null
, because identify calls don’t include an event
!
Mapping to traits and event properties
While we know that incoming identify calls contain traits
and incoming track calls likely contain properties
, we don’t know what those properties are or might be. If you want to map to a specific trait or event property, you’ll need to provide it yourself—under traits.<trait-name>
or properties.<property-name>
respectively.
Make sure that your requests reliably provide the trait or event property in your source events or the property will be empty when we send data to your destination!
The case function
The case function is simple: it converts a value’s case to lower
or upper
. You might use this function to enforce uniform cases in a destination. For example, you might want to store your users’ names in lowercase for uniformity.
The case function uses the format case(sourcekey, "lower/upper")
.
case(traits.first_name, "lower")
The coalesce function
The coalesce
function picks the first non-null value in a list of possible values. That’s a fancy way of saying that it uses the first non-empty value that it finds in the incoming source payload.
The coalesce function uses the format coalesce(firstkey, secondkey)
. Only two arguments are supported at the moment.
For example, Customer.io lets you identify people by id
or email
address. So, when you use Customer.io as a destination, we set the Person ID to coalesce($.userId, $.traits.email)
. This simply means that if the request has a userId
, we’ll map that to the person’s ID. If it doesn’t, we’ll map the email
trait to the person’s ID.
If you use coalesce
, and none of the keys are populated, the trait and the corresponding mapping will be null
(empty).
coalesce(userId, traits.email)
")-->b{Does the callhave a
userId
}
b-->|yes|c(Person ID = userId
)
b-.->|no|d{"Does the call havean
email
trait?"}
d-->|yes|e(Person ID = traits.email
)
d-.->|no|f(Person ID = null
)Hash function
The hash
function lets you hash a value using the SHA-256 algorithm. This is useful if you want to hash an email address or other personally identifiable information (PII) before sending it to a destination.
hash(traits.email)
Slugify function
The slugify
function converts a value to a slug—a value that consists only of letters, numbers, and hyphens. Slugifying a value removes all special characters, converts spaces to hyphens, and removes multiple hyphens. For example, slugify("Hello, World!")
returns hello-world
.
This might be useful when you want to convert a value to a URL-friendly identifier. For example, if you want to convert an email address to a slug that you use to identify a person in destination.
slugify(traits.email)
toJSON and fromJSON functions
These two functions help you handle stringified JSON data, but the naming convention can be a little confusing!
fromJSON
converts stringified JSON to a JSON object.toJSON
converts a JSON object to a string, similar toJSON.stringify
in JavaScript.
You may want to convert to or from stringified JSON if you’re working with a destination that expects JSON data in a specific format.
var jsonTraits = {
"email": "cool.person@example.com",
"name": "Cool Person"
}
var stringifiedJSON = toJSON(jsonTraits)
// returns '{"email":"cool.person@example.com","name":"Cool Person"}'
fromJSON(stringifiedJSON)
// returns the original JSONTraits object
Empty source and destination values
You can map values to destinations, but that doesn’t guarantee that those values are populated in your source events.
Most source calls only require an ID of some sort or an event name, so you won’t necessarily receive errors if you send source data that doesn’t fully populate all the data you want to capture at your destination. You’ll need to make sure sure that your sources send the right data—traits, event properties, etc—that you want to map to your destinations.