Overview
Act-On’s Custom Data API lets you add related data to supplement your contact data. This could be behavior data such as purchases, interactions, registrations, or service claims. It could be extended profile data, such as a custom owner table, account data, or distributor information. Use the Custom Data API to make this data available in Act-On for segmentation, scoring, & personalization.
Custom Data is available for clients using Audience Center to manage their contact data in Act-On. It replaces the previous features, Custom Touch Points and Extension Lists.
API details are found here. See the Audience Center Custom Objects Service section.
Definitions
Custom Data: Any set of data you define that relates to your contact data in Act-On.
Custom Data Schema: The schema defines the nature of your data, including the fields and data types, required fields, unique fields, and how the data joins to your contacts.
Custom Data Dataset: Every schema will have at least one Dataset that you can populate with data. You can continue to update the same dataset, or you can create a new dataset if you have additional data to upload.
Before You Begin
Here are some things to consider before you get started.
Profile vs. Behavior Data
Profile data is typically a 1-to-1 relationship with the contact, or may be a many-to-1 relationship with contacts. For example, if you have a table of distributors, and each is linked to multiple contacts by a distributorID, this could be considered profile data.
Behavior data often has a 1-to-many relationship with contacts, in that each contact could have multiple purchases or similar behaviors in the table. Behavior data must have a date field that defines when the behavior occurred.
Choosing profile vs. behavior has implications for how the data will be used in segmentation and scoring. Behavior data can be evaluated based on the total # of behaviors the contact has had in a time period.
Relationship to Contact Data
You’ll be asked to define how the data you are uploading relates to the contact data in your All Contacts list. Is it one-to-one, many-to-one (each contact may have multiple entries in your data), or one-to-many (each entry in your data may be related to multiple contacts)?
How will this data join to the contact?
Option 1: Email join. When you upload the data, it will link to a contact with the same email. If you have duplicate contacts with the same email in your data (rare, but can occur if you have duplicates in an integrated CRM system), the data may connect to all the related contacts.
Option 2: ExternalID and ObjectType join. Act-On has 2 system fields that can be used to identify unique contacts. These are commonly used for integrated CRM systems, but you can also use them when uploading contacts via API. ExternalId contains an ID number that identifies your contact in any external system you are integrating with. ObjectType can be consistent for all contacts or can designate groups of contacts, such as “Customer” or “Lead”. The 2 fields both must match for data to connect to that contact. You can define a “default” ObjectType per schema, so you don’t need to include the ObjectType field in all your custom object data.
API Credentials
You will need API credentials on your account. Here's how to get these.
Define Your Data Schema(s)
Your first step will be to define a data schema to hold your data. Use the Create Schema API.
You'll need to specify the following:
- name - The name of the schema
- description - Describe what the schema is for
- dataType - Options are "profile" or "behavior" (see explanation above)
- fields - see below for details
- requiredFields - specify which fields are required. Any fields used in joins should typically be required. Rows without data in the required field will be rejected.
-
uniqueFieldSet - identify which field(s) make a row unique. Any updates to your dataset will match these fields to update or replace the row, vs. entering a new row.
- One-to-one relationship tables will default to the join field (i.e., Email or other) as the unique field if none is specified. Because it is a 1-to-1 relationship, additional data uploaded with the same join field value will replace the original row
- One-to-Many relationships will get a default “record ID” to use as the unique row identifier if no other field(s) are specified. New rows will be added unless the upserted data has the same unique field value.
- eventTimestampField - Required for behavior type schemas only. It will be used for segmentation and timeline sorting.
- primaryEmailField -default email field to use to link to Contacts if the “relationship” is not defined. Optional if you are using the relationships property to define the relationship
- externalIdField - define which field contains an externalID to map to Contacts' external ID, if you are using this for join purposes. Optional if the relationship is defined or if email is used to join.
- objectTypeField - define which field contains the objectType to map to Contacts' ObjectType, which is required if you are using an ExternalId join. Optional here if the relationship is defined or if email is used to join.
-
relationships: Lets you explicitly define at least one relationship to the contact data. Not required if you want to use the default email join & define the primaryEmailField.
- Type: one-to-one, one-to-many, many-to-one, many-to-many
- fieldName: identify a field in your data that matches to the contact
- otherObject: this is typically ActOnContacts
- otherFieldName: What field on the contacts data matches to your field. (i.e., “email”)
Field Properties
Each field in the schema contains:
- name: Unique identifier for the field. Case insensitive, does not allow spaces. Supports alphanumeric characters, dashes, underscores, and dots
- type: Data type of the field (see below for options)
- description: Detailed description of the field's purpose
- displayName: Human-readable name for display purposes
- properties: Additional configuration specific to the field type (optional)
Supported Field Types
Type Identifier | Description | Use Cases | Properties |
string |
Basic text type | Names, descriptions, & general text | |
|
Email address with format validation | Email address | |
url |
website address URL field with URL data validation | Links, website addresses, social media profiles | |
zipcode |
US Postal code | Address information | |
number |
Integer values | Counts, quantities, whole numbers | |
duration |
Time durations | Time spent on activity, in a webinar, etc. |
format: compound: Examples: "1s", "1 second", "1h 30m" iso8601: Standard ISO duration format mm:ss: Minutes and seconds HH:mm:ss: Hours, minutes, seconds maxDuration: Maximum allowed duration in milliseconds |
float |
Decimal, floating-point values | Precise measurements, calculations | |
currency |
Decimal, currency-specific | Currency amounts |
currencyCode*: Specifies the currency (e.g., "USD") |
boolean |
true/false values | flags, toggles, yes/no fields | |
date |
date value without time | birthdays, expiration dates | format: Specifies date format (e.g., "dd-mm-yyyy") |
datetime |
date and time values | Event timestamps, action logging | format: Specifies datetime format (e.g., "dd-mm-yyyy hh:mm:ss") |
object |
Complex JSON objects | Nested data structures | format: defaults to "json" |
stringarray |
Array of string values | Tags, categories, multiple selections |
CSVSeparator: Defines the separator for CSV format (e.g., ",") |
enum |
Predefined set of values | status values, predefined categories, & grades |
enumName: Name of the enumeration enumDescription: Description of the enumeration enumValues: Semicolon-separated list of allowed values enumValuesCaseSensitive: Boolean for case sensitivity |
* Currently supported currency codes: USD, GBP, EUR, INR, RUB, KRW, IDR, TRY, ZAR, NGN, PKR, PLN, PHP, MXN, MYR, JPY, ILS, HUF, HKD, DKK, CZK, CNY, CHF, CAD, BRL, AUD, ARS, THB
Relationships
All data schemas should have a relationship to the contact table. Typically, this is done via email. and will default if you define the primaryEmailField. However, you can also use an externalId field to join on. This requires a join on the objectType field as well. You can include objectType in your data or use a default. If you have CRM contact data, the standard externalId and objectType fields are used by the CRM. You can specify a different field as a secondary externalId to join on. Here are some examples of how to set up the relationships.
- Join on email:
relationships : [
{
"name" : "Email_Join",
"description" : "Join contact to product on Email",
"type" : "many-to-one",
"fieldName" : "Email",
"otherObject" : "ActOnContacts",
"otherFieldName" : "email"
}]
- Join on externalId and ObjectType when ObjectType is present (and varied) in your data:
relationships : [
{
"name" : "MemberId_Join",
"description" : "Join contact to product on MemberId",
"type" : "many-to-one",
"fieldName" : "MemberId",
"otherObject" : "ActOnContacts",
"otherFieldName" : "externalId"
},
{
"name" : "Object_Type_Join",
"description" : "Join contact to product on ObjectType",
"type" : "many-to-one",
“fieldName”: “objectType”,
"otherObject" : "ActOnContacts",
"otherFieldName" : "objectType",
}
]
- Join on external ID when objectType is not present in your custom data - use a default ObjectType called “member”:
relationships : [
{
"name" : "MemberId_Join",
"description" : "Join contact to product on MemberId",
"type" : "many-to-one",
"fieldName" : "MemberId",
"otherObject" : "ActOnContacts",
"otherFieldName" : "externalId"
},
{
"name" : "ObjectType_ConstantJoin",
"description" : "Join contact to product on constant ObjectType",
"type" : "simple-filter",
"otherObject" : "ActOnContacts",
"otherFieldName" : "objectType",
"otherFieldValue": "MEMBER"
}
]
Schema Limits
Data Type | Total # of fields per schema |
String | 100 |
Float | 50 |
Number | 50 |
Boolean | 50 |
DateTime | 50 |
JSON | 25 |
Uploading Data Into Your Schema
Once you’ve defined a data schema, you can upload data using this API. When you create or view your data schema, the response will include the “id” (the schemaId), which you will need to post data to this schema. At the bottom of the response, you’ll see the “defaultDatasetId”, which can alternatively be used to identify where to post the data to.
Generally, you can upload subsequent data to the same Dataset. This will give you the most flexibility when it comes to segmentation and scoring. However, if you wish, you can create a different dataset on the same schema for a different set of data.
When you upload data, the response will give you a jobId. You can use this jobId to get the status of the upload and a failure report.
Parameters for File Upload APIs:
- fileType: can be CSV or JSON
- objectId &/or datasetId: Include the data schema ID and/or the dataset ID or name.
-
abortOnInvalidRow:
- True - Will halt the import if invalid data is found.
- False - (default) will continue the import if invalid data is found
-
ingestMode:
- UPSERT - will add new rows and/or update existing rows.
- REPLACE - will replace existing data where a unique key match is found
- DELETE - will delete existing data where a unique key match is found
- createNewDataset: False (default) or True
- description: Can add a note about this data schema if creating new
Retrieving Data
You can retrieve your custom data with joined contact data using this API.
Here are the body parameters, explained
selectFields: Use to select fields to be returned.
- Prefix the target Custom Object fields with co. and the UCL/AOC fields with aoc..
- Use aoc.* or co.* or sys.* to select all AOC or Custom Object, or System fields (order is determined by the server). The order of the array matters as the fields will be returned in the same order in the result. The default if not specified is ["aoc.*", "co.*"]
page, size: pagination parameters. Use -1 in both params to indicate unpaginated results. The default is page=0, size=100 if not specified.
sortBy: sort by field. The same prefixing rules apply
sortByDirection: asc or desc - indicates the sort direction when "sortBy" is specified. By default, if not specified is set to asc
joinStrategy: Mandates how to join with All Contacts and how to treat possible duplicate data. Both Custom Objects and All Contacts might allow duplicates in a join column or columns. For example, if a custom object is related to All Contacts by email in a one-to-one relationship by email, how do we display the data in the cases where multiple emails match the join?
- joinEnabled: Use to disable join with AOC to request the data from a custom object without a join. If not specified, it defaults to true.
-
Duplicates: options include:
- allow (default)
- noOtherJoinFieldsDuplicates
- noBaseJoinFieldsDuplicates
- noJoinFieldsDuplicates
- baseOrderByField: The name of the Custom Object field to order the duplicates by to prepare for selecting. If not specified, it defaults to sys.updatedAt, which is a system Custom Object field with the last time the custom object record was updated.
- baseSelector: either first or last. Determines which duplicate record to pick after sorting. If not specified, it defaults to last.
- otherOrderByField - The name of the All Contacts field to order the duplicates by to prepare for selecting. If not specified, it defaults to updateDate, which is a system field with the last time the record was updated.
- otherSelector: either first or last. Determines which duplicate record to pick after sorting. Default, if not specified, is last.