Search documentation...

K
ChangelogBook a demoSign up

Field mapping

Overview

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.

Mapping diagram

"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:

  • mapping with static or constant values
  • mapping with variables
  • mapping with Liquid templates
  • inline mapping, which lets you create nested objects and arrays from model columns

Usage

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.

Mapping in the Hightouch UI

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.

Suggest Mappings in the Hightouch UI

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.

Model column changes and field mapping

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.

Basic mapper

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:

Column in your sourceField in your destination
email_addressEmail
first_nameFirstName
last_nameLastName
account_idAccountId

Advanced mapper

For destinations with the advanced mapper, you can create mappings that include:

  • a column value
  • a static value
  • a sync-based variable value
  • values using the Liquid templating language
  • nested objects and arrays using the inline mapper

The advanced mapper in the Hightouch UI

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.

Column values

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.

Column Mapping

Don't sync null values

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.

Column Mapping with ignore null option enabled

Static 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:

Static Mapping

  1. Open the advanced mapper by clicking on a model column.
  2. Select Static value and the value's data type: String, Number, Boolean, or Null.
  3. Enter the desired value in the field provided.
  4. Click Apply.
  5. 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.

Static Mapping

Variable values

With variable mapping, you can send sync metadata to a destination field. The available metadata variables are:

  • model-id (string)
  • model-name (string)
  • current-timestamp (date/time)
  • sync-id (string)
  • sync-run-id (string)

For example, you may want to send a sync's timestamp to an updated_at field in a destination.

Variable Mapping

  1. Open the advanced mapper by clicking on a model column.
  2. Select Variable value and the desired metadata, for example, current-timestamp.
  3. Click Apply.
  4. In the field input to the right of the variable value, select the destination field name to which you want to map the variable value.

With this example mapping, Hightouch sends ISO time/date value (YYYY-MM-DD) into every record's updated_at field:

Variable Mapping

Template mapping

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.

The template mapper uses the Liquid templating language to create complex mappings.

  1. Open the advanced mapper by clicking on a model column.
  2. Select Template, then select a Variable and Function. The function's code automatically appears in the editor window.
  3. Click Apply.
  4. 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.

Template Mapping

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.

Inline mapping

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.

Create an object

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.

Object inline mapper example

  1. In the destination field input on the right, select the field name to which you want to map an object, for example, Shipping Address.
  2. 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.

Autopopulated object type in the Hightouch UI

  1. Select the relevant destination fields you want to map values to and map the nested fields as needed.

Object inline mapper example

Given the previous example row and the mappings shown in the screenshot above, Hightouch would sync the following payload:

{
  "email": "doe@test.com",
  "shipping": {
    "address": {
      "city": "San Francisco",
      "state": "California",
      "postal_code": "94105"
    },
    "name": "John Doe",
    "phone": "123-456-7890"
  }
}

Create an array

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.

Array inline mapper example

Required data format

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.

[
  {
    "item_id": "542",
    "quantity": 50,
  },
    {
    "item_id": "631",
    "quantity": 20,
  },
]

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_idcustomer_idamountdescription
in_1cust_abcd55Waffle Maker
in_1cust_abcd7Dog Chew Toy
in_2cust_efgh12HDMI Cable
in_3cust_abcd45Humidifier Filters
in_3cust_abcd109Electric Kettle
in_3cust_abcd15Wall Calendar
in_4cust_ijkl25Mediterranean Cookbook
in_4cust_ijkl10AAA 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:

[
  {
    "invoice_id": "in_1"
    "customer_id": "cust_abcd",
    "items": [
      {
        "description": "Waffle Maker",
        "amount": 55,
      },
      {
        "description": "Dog Chew Toy",
        "amount": 7,
      }
    ]
  },
  {
    "invoice_id": "in_3"
    "customer_id": "cust_abcd",
    "items": [
      {
        "description": "Humidifier Filters",
        "amount": 45,
      },
      {
        "description": "Electric Kettle",
        "amount": 109,
      },
      {
        "description": "Wall Calendar",
        "amount": 15,
      }
    ]
  }
]

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
group by
  1,
  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.

Map fields

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.

  1. 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.
  2. 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.
  3. 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 your array of objects column from the advanced mapper.

  1. Select the relevant destination fields you want to map values to and map the nested fields as needed.

Mapping our example properties to the quotes object in Stripe.

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.

Mapping our example properties to the quotes object in Stripe

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:

{
  "line_items": [
    {
      "price_data": {
        "currency": "USD",
        "product": "542"
      },
      "quantity": 50
    },
    {
      "price_data": {
        "currency": "USD",
        "product": "631"
      },
      "quantity": 20
    }
  ],
  "customer": 231,
  "description": "Two items"
}

Nesting depth

You may need to sync arrays or objects with more deeply nested objects. For example, you may need to sync a Shipping Address object with this format:

{
  "items": [
    {
      "item": {
        "id": "8"
      },
      "line": 1,
      "amount": 1,
      "price": {
        "id": "-1",
        "usd": 50
      }
    },
    "name": "Jane Doe",
    "phone_number": "4151234567"
  }
  // ...
  ]
}

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.

Mapping an array in the Hightouch UI

Liquid reference

This reference goes over the following:

For more detailed information, refer to the Liquid reference documentation.

Liquid template format

Variables follow this format:

{{ row['company'] }}

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.

Liquid variables in the advanced mapper

You can use metadata variables in your liquid templates, such as a model's name, all model column names, and the timestamp of a sync's last run.

$ <column_name>
$ Model Name
$ Timestamp

You can view all available variables in the Variables column in the template editor.

Template Mapping

Liquid-inspired functions in the advanced mapper

Hightouch provides these non-native functions for you to use out of the box:

FunctionSyntaxDescription
base64_decoderow['email']|b64_decodeBase64 decode input
base64_encoderow['email']|b64_encodeBase64 encode input
castrow['phone']|cast:'string'Cast input to specified type. Allowable types are 'string', 'number', 'boolean'
includesrow['last_name']|includes:'Stark'Check input for a substring. Row will be rejected if substring isn't found
parserow['first_name']|parseParse input to JSON
JSON_construct| json_construct: 'city', row['city'], 'state', row['state_province']Construct JSON object
regex_replacerow['last_name']|regex_replace: '<[a-zA-Z]>', '<replacement>'Search and replace substrings of input using RegEx
regex_testrow['last_name']|regex_test: '<[a-zA-Z]>'Check input for a RegEx match. Row will be rejected if no match is found using RegEx
sha256row['email']|sha256Hash input using SHA-256
sha512row['email']|sha512Hash input using SHA-512
to_daterow['dob']|to_dateParse input and return a Date object (ISO 8601 format)
to_unixrow['date_sent']|to_unixConvert input to Unix time
validate_emailrow['email']|validate_emailReject emails that aren't RFC 2822 compliant email addresses

Liquid function chaining

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 (|):

Examples:

{{ row['full_name'] | camelcase | sha256 }}
{{ row['email'] | downcase | validate_email | sha256 }}

Extended Liquid and use cases

See the Shopify's Liquid docs, Liquid Cheatsheet, or Liquid Reference for a complete list of available functions.

Conditional output

You can use Liquid conditionals to specify output based on input. For example, this Liquid snippet:

{%- if row['discount_percent'] >= 50 -%}
  Over half off!
{%- elsif row['discount_percent'] == 50 -%}
  50% off!
{%- elsif row['discount_percent'] > 0 -%}
  Discounted!
{%- else -%}
  null
{%- endif -%}

outputs the following result in a destination column:

Liquid Conditional Output

Conditionals are also helpful to guard against missing values.

For example, you could use the following Liquid snippet to send a null value for empty values.

{%- if row['column_name'] !=nil -%}
{{ row['column_name'] }}
{%- else -%}
{{ null }}
{%- endif -%}

This is helpful if you need to map a column that exists for some rows but not others.

Default value

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.

Date function

If your destination expects dates in a different format than your model returns them, you can use the Liquid date function to reformat them.

For example, this Liquid snippet:

{{ row['column_name'] | date: '%d/%m/%Y' }}

ensures that dates from the column are always in the DD-MM-YYYY format.

This snippet:

{{ row['column_name'] | date: '%m/%d/%Y' }}

always returns dates in the MM-DD-YYYY format.

Math functions

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:
{{ row['value'] | round: 2 }}

String functions

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:
{{ row['file_name'] | append: '.png' }}

Isolating parts of 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 }}

would return the gclid value, 123.

Isolating object properties

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.

Template Mapping

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.

Book a demoSign upBook a demo

Need help?

Our team is relentlessly focused on your success. Don't hesitate to reach out!

Feature requests?

We'd love to hear your suggestions for integrations and other features.

Last updated: Jun 9, 2023

On this page

OverviewUsageBasic mapperAdvanced mapperColumn valuesStatic valuesVariable valuesTemplate mappingInline mappingLiquid reference

Was this page helpful?