One of the key aspects of sync configuration is field mapping. Field mapping defines which columns from your model query results should appear in your destination and how. In other words, it's a way of relating model columns to destination fields or properties.
"Columns" vs. "fields" vs. "properties": Though some may use these terms
interchangably,
Hightouch uses the term "columns" to refer to a set of vertical data values in
a source or model and "fields" or "properties" to refer to them in a destination.
Depending on your destination, you can map your data with either the basic mapper or the advanced mapper. The basic mapper maps columns to fields in a one-to-one way. The advanced mapper gives the additional options of:
You can start with either the source or destination input fields when using either basic or advanced mapper.
The Hightouch UI offers this flexibility to enable you to map data the way that makes the most sense for you.
For example, you may approach mapping with an idea of all model columns you want to send to your destination.
To do so, click Add mapping and select each model column in the left-hand inputs.
Then select the appropriate destination fields to map them to in the corresponding right-hand dropdowns.
If you begin by selecting all model columns you want to sync, you can click the lightning icon next to Add mapping to Suggest mappings.
Conversely, you may know all the destination fields you need to sync to.
Select each destination field from the dropdowns on the right and map the appropriate model columns on the left.
This option proposes relevant destination fields for model columns.
For example, a model column named email_address would receive a suggested destination field like Email.
This autocompletion works by searching for matching and near-matching column and field names.
Before saving your configuration, you should confirm that the autocompleted suggestions have made the correct selections.
Sync configurations detect changes to your model columns.
Hightouch handles the changes differently depending on whether columns are removed, renamed, or added to your model definition.
If you remove a column used in field mapping from your model, Hightouch removes it from your sync configurations after you've previewed and saved the model query.
If you rename a column used in field mapping from your model, subsequent sync runs fail with an Unknown field name error.
The error message also contains the original name of the renamed column.
To resolve the error, remove or update the relevant field mappings in your sync configurations.
If you add a new column to your model, Hightouch doesn't automatically add it as a field mapping to your sync configurations.
This is because Hightouch is unaware which configurations you'd want to add it to, and which destination fields it should map to.
Follow the field mapping instructions outlined below to include new columns in your field mapping.
With the basic mapper, you tell Hightouch which columns in your source to feed into which fields in your destination. For example, you can use the basic mapper to relate model columns to destination fields like these:
You can open the advanced mapper by clicking the source field you want to map. If you click a source field and the advanced mapper doesn't appear, it isn't supported. Please if you have a use case requiring the advanced mapper on a destination that doesn't support it.
Mapping column values is similar to the basic mapper's functionality. You can search for and select the model column name you want to map to a destination field.
By default, Hightouch syncs any null values found in your model query results to your destination. You can select to sync nothing instead of null values by enabling Don't sync null values.
With static mapping, you can specify a constant value to use for each field value. For example, suppose you want to map the string value EMEA for every record's region field value in a destination. You can do this with static mapping:
Open the advanced mapper by clicking on a model column.
Select Static value and the value's data type: String, Number, Boolean, or Null.
Enter the desired value in the field provided.
Click Apply.
In the field input to the right of the static value, select the destination field name to which you want to map the static value.
The template mapper is convenient when your destination requires data in a specific format, and you want to avoid baking this specificity into your model. For example:
Webflow requires slugs not to have any special characters. You can use the template mapper's regex_replace function to remove them.
You want to validate email addresses before sending them to Mailchimp or another email service provider.
You want to enable lead routing in your destination using Liquid conditionals without touching your central dbt model.
To create nested objects or arrays, you need to use the inline
mapper.
Open the advanced mapper by clicking on a model column.
Select Template, then select a Variable and Function. The function's code automatically appears in the editor window.
Click Apply.
In the field input to the right of the templated value, select the destination field name to which you want to map the templated value.
In the example screenshot, the template uses the function {{row['last_name'] | includes: "Stark" }} to check checks if a row's last_name column includes the string "Stark". If it does, the row is processed. If it doesn't, the row is rejected.
The template mapper supports all of Liquid's native features and also includes Liquid-inspired functions. To learn more about the Liquid templating language, skip to the Liquid reference section in this doc or check out the Liquid reference documentation.
The inline mapper is only available for certain destinations and is currently in beta. Please if you'd like to be considered for early access.
When syncing data to a marketing automation or enterprise resource planning (ERP) tool, you may need to nest related entities. For example, you may have nested items in an invoice or nested entities for a user: associated devices, shipping address, pets, etc. The inline mappers allows you to create these nested objects and arrays from your model query results without altering your model definition.
Each destination has its own formatting expectations for these nested entities. For example, in Stripe, an invoice object supports an items field that expects an array of items.
The inline mapper lets you model your data once and format it during sync configuration rather creating a separate model for each destination requiring nested objects or arrays.
The object inline mapper allows you to construct objects and map them to destination fields usings columns from your model. This section walks through constructing an object for the shipping field in Stripe's customer object.
In the destination field input on the right, select the field name to which you want to map an object, for example, Shipping Address.
The model column input on the left autopopulates to Object mode if the selected field is of type object. If the type of the field is not provided, open the advanced mapper by clicking on the source input field and select Create an object.
Select the relevant destination fields you want to map values to and map the nested fields as needed.
Given the previous example row and the mappings shown in the screenshot above, Hightouch would sync the following payload:
The array inline mapper allows you to construct an array of objects and map them to destination fields using a model column that contains an array of objects. This section walks through constructing a line items array for Stripe's quote object. You would use the same steps for any other object arrays you want to create.
To use the inline mapper to create an array of objects, the query results from your model need to have a certain format. Specifically, they should appear as an array of objects, like the example items field in the entity relationship diagram (ERD) above.
If you don't already have a data field formatted like this, you can define your model using a SQL query that constructs an array of objects from other fields.
For example, imagine you have a line_items data table where each row represents an invoice item. The columns are:
invoice_id for the ID of the invoice the item belongs to
customer_id for the ID of the customer who purchased the item
amount for the cost of item
description for a short description of the item
For example:
invoice_id
customer_id
amount
description
in_1
cust_abcd
55
Waffle Maker
in_1
cust_abcd
7
Dog Chew Toy
in_2
cust_efgh
12
HDMI Cable
in_3
cust_abcd
45
Humidifier Filters
in_3
cust_abcd
109
Electric Kettle
in_3
cust_abcd
15
Wall Calendar
in_4
cust_ijkl
25
Mediterranean Cookbook
in_4
cust_ijkl
10
AAA Batteries
You want to sync an array of items for each invoice for each customer. For example, for customer_abcd from the preceding table, they would have two separate invoice objects, each with their own items array, one for the invoice with ID in_1 and one for the in_3 invoice:
To make these fields available in the inline mapper to construct an items array, you would need to include SQL like this in your model definition:
select
inv.customer_id,
inv.invoice_id,
array_agg(object_construct(it.*)) as items
from
line_items inv
join items it on it.invoice_id = invoice._id
groupby1,
2
This query selects the customer_id and invoice_id as well as all properties—in this case just description and amount—on each item and then aggregates them into an array of objects. The group by statement groups them based on the customer_id and invoice_id so that each aggregated array is for one invoice for one customer. Without the inline mapper, you would need to write more complex SQL manually constructing each item attribute as part of the item object.
Once your model query results have an array of objects to pull data from, you can use the inline mapper to configure as many syncs as you need to sync these items.
In the Field Mapping section of your sync configuration, in the destination field input on the right, select the field name to which you want to map an array, for example, Line items.
The model column input on the left autopopulates to Array mode if the selected field is of type array. If the type of the field is not provided, open the advanced mapper by clicking on the source input field and select Create an array.
You will be prompted to pick a column that contains an array of objects. Select your desired column from the list of compatible columns. If no columns appear, ensure your model query results conform to the required data format.
Select the relevant destination fields you want to map values to and map the nested fields as needed.
The columns available under the array inline mapper are properties of the previously selected column.
Hightouch uses the first 100 rows from your query to extract the available properties at each index of the array. To add additional properties that may be missing, type into the input field and select the custom option or press Enter.
Hightouch only processes properties if the mapped object property at the index of the array exists.
For example, if <Your Column>[0].price exists and <Your Column>[1].price does not exist, items[0].price will be mapped and items[1].price will not be mapped. Hightouch syncs null values if you don't choose to ignore them.
For each row in your query, the array created using the inline mapper matches the length of the array in your column.
Given the previous example row and the mappings shown in the screenshot above, Hightouch would sync the following payload:
The "address" key expects a further nested object. Hightouch supports nesting up to two levels deep. You can do this by selecting Create an object or Create an array while already using the inline mapper.
The double handlebars enclose a Liquid snippet that generates an output. The column name, company in the preceding example, should be in single quotes inside the square brackets.
Functions follow this format:
{{ row['last_name'] | includes : 'Stark' }}
A single pipe (|) comes after the variable and before the name of the function and any necessary parameters. See the Liquid Reference or Liquid Cheatsheet for a complete list of available functions.
You can use more than one Liquid function in a template by chaining them. For example, you may want to put a string variable into camel case before hashing it. To chain functions, separate them with a single pipe (|):
You can also use Liquid to set a default value, in case an input value is null, false, or empty. For example, this Liquid snippet:
{{ row['revenue'] | default: 0 }}
sets the revenue field as 0 if the value is missing or null in a model's row.
Be sure to change revenue to the column name you want to set default values for.
See Liquid Math Functions for a complete list of math functions. In Hightouch, the absolute value and rounding functions are some of the most commonly used:
Use the abs function to send an absolute value:
{{ row['value'] | abs }}
Use the round function to round a value to the nearest integer or a specified number of decimals:
See Liquid String Functions for a complete list of string functions. In Hightouch, the capitalize, strip, and append functions are some of the most commonly used:
Use the capitalize function to capitalize the first letter of a string:
{{ row['title'] | capitalize }}
Use the strip function to remove all whitespace from the left and right sides of a string:
{{ row['title'] | strip }}
Use the append function to add a file extension to a string:
You can use the Liquid split function to isolate a certain part of a string.
For example, suppose you have a model column that returns URLs, including query parameters.
An example value may look like this: www.example.com/?gclid-123.
You may want to send the base URL (www.example.com/) as one field and one of the query parameters as another field.
Query parameters often include click IDs, such as the gclid or fbclid that you should include on events you send to Google Ads or Facebook Conversions APIs respectively.
For the example value www.example.com/?gclid-123., this Liquid snippet:
{{ row['column_name'] | split: "?gclid-" | first }}
would return the base URL; and this Liquid snippet:
{{ row['column_name'] | split: "?gclid-" | last }}
If your model columns contain object type values, you may want to sync only one or some of the object's properties to your destination.
You can do this in the template mapper using the dot notation.
Specifically, you can write a Liquid expression containing the model column's name and the property's name: {{ row['model_column'].property }}
For example, suppose you had a model column named invoice that contains objects with this structure:
{"invoice_number":"INV-001","issue_date":"2023-06-08","due_date":"2023-06-30","customer":{"name":"John Doe","email":"johndoe@example.com","address":"123 Main St, City, State, ZIP"},"items":[{"description":"Product A","quantity":2,"unit_price":10.99,"total_price":21.98},{"description":"Product B","quantity":1,"unit_price":15.99,"total_price":15.99}],"subtotal":37.97,"tax":3.60,"total":41.57,"currency":"GBP"}
You may only want to map the total column to a price field in your destination.
You could do this by including the following Liquid in the template mapper:
{{ row['invoice'].total }}
You can also use this to map nested properties, for example, customer.name:
{{ row['invoice'].customer.name }}
If you want to sync multiple object properties individually, you can use these types of expressions for multiple mappings in your sync configuration.
Make sure you've set the model column's type as Object / Array in the model's Columns tab.
Otherwise, Hightouch syncs an undefined value to your destination.
Dot notation only works with field columns that contain single objects, not arrays of objects.
Ready to get started?
Jump right in or a book a demo. Your first destination is always free.