> ## Documentation Index
> Fetch the complete documentation index at: https://partner-integrations.voyado.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Map Shopify customer metafields to Voyado Engage attributes

> Sync customer metafields from Shopify into custom attributes in Voyado Engage for segmentation, personalization, and automation.

The Voyado Engage app for Shopify lets you map customer metafields from Shopify to custom attributes in Voyado Engage. This means data you already store on a customer's Shopify profile, like loyalty tier, preferred size, or a referral source, can flow straight into Voyado and power your segmentation, personalization, and automation. Some of the most common fields are mapped for you automatically, and you can add your own mappings for anything else you track in Shopify metafields.

## How it works

The attribute mapping page distinguishes between two kinds of mappings:

* **Locked mappings.** A set of default mappings that come pre-configured and can't be changed. These cover the core customer fields Voyado needs, like name, address, and email.
* **Custom mappings.** Mappings you configure yourself, between any Shopify customer metafield and any custom attribute on your Voyado contact type.

<Note>
  Voyado Engage is the source of truth for attribute definitions, including the allowed values for **Dropdown** and **Checkbox Multiple** attributes. Every time you open the mapping page, we fetch the current attributes, types, and allowed values directly from Voyado, so what you see is always up to date.
</Note>

## Locked mappings

The following Shopify fields are always mapped to their corresponding Voyado attribute. You'll see these listed under **Locked Mappings** on the mapping page, marked with a lock icon. They're not available to select when you create a custom mapping.

| Shopify field                     | Voyado attribute | Voyado type |
| --------------------------------- | ---------------- | ----------- |
| `first_name`                      | `firstName`      | string      |
| `last_name`                       | `lastName`       | string      |
| `default_address.address1`        | `street`         | string      |
| `default_address.country_code`    | `countryCode`    | string      |
| `default_address.zip`             | `zipCode`        | string      |
| `default_address.city`            | `city`           | string      |
| `phone`                           | `mobilePhone`    | string      |
| `email`                           | `email`          | string      |
| `id`                              | `externalId`     | string      |
| `voyado.gender` (metafield)       | `gender`         | string      |
| `voyado.birthDay` (metafield)     | `birthdate`      | date        |
| `email_marketing_consent.state`   | `acceptsEmail`   | checkbox    |
| `sms_marketing_consent.state`     | `acceptsSms`     | checkbox    |
| `locale`                          | `lang`           | string      |
| `voyado.discoveryKey` (metafield) | `discoveryKey`   | string      |
| `voyado.age` (metafield)          | `age`            | integer     |

All metafields the app creates for these locked mappings live under the `voyado` namespace (for example, `voyado.discoveryKey`). Note that the Shopify metafield key and the Engage attribute name are not always identical — the birthday metafield is `voyado.birthDay`, while the Engage attribute it fills is `birthdate`.

<Note>
  Shopify field names are given here in their REST form (`first_name`, `default_address.zip`). The same fields appear in their GraphQL form (`firstName`, `defaultAddress.zip`) in [Field mappings](/docs/ecom/shopify/field-mappings), which documents the full receipt and order payloads alongside contact data.
</Note>

## Supported attribute types

When you create a custom mapping, only Voyado attribute types that are compatible with the selected Shopify metafield type are shown. Here's how types line up:

| Voyado type       | Description                             | Compatible Shopify metafield type(s)      |
| ----------------- | --------------------------------------- | ----------------------------------------- |
| String            | Plain text, up to around 255 characters | `single_line_text_field`, `url`, `color`  |
| Long String       | Rich or long text                       | `multi_line_text_field`                   |
| Int               | Integer number                          | `number_integer`                          |
| Number            | Decimal number                          | `number_decimal`                          |
| Checkbox          | Boolean true/false                      | `boolean`                                 |
| Checkbox Multiple | Array of values                         | `list.choice_list.single_line_text_field` |
| Dropdown          | One value from a predefined list        | `choice_list.single_line_text_field`      |
| Date              | Date (YYYY-MM-DD)                       | `date`                                    |
| Date Time         | Date and time                           | `date_time`                               |

## Create a custom mapping

<Steps>
  <Step title="Open Attribute Mapping">
    Go to **App Settings** > **Attribute Mapping** in the Voyado Engage app in Shopify.
  </Step>

  <Step title="Add a mapping">
    In the **Custom Mappings** section, select **Add mapping**.
  </Step>

  <Step title="Select the Shopify metafield">
    Search for and select the metafield you want to sync. You can select metafields from any namespace, including ones created by other apps.
  </Step>

  <Step title="Select the Voyado attribute">
    Choose the attribute you want to map to. Only attributes compatible with your selected metafield's type are shown.
  </Step>

  <Step title="Check type compatibility">
    A green checkmark means you're good to go. If you see a warning, the types aren’t compatible — choose a different attribute or metafield.
  </Step>

  <Step title="Resolve value alignment (if applicable)">
    If you mapped a **Dropdown** or **Checkbox Multiple** attribute and the allowed values don't match between Shopify and Voyado, review the side-by-side comparison and confirm that we can update the Shopify values to match Voyado.
  </Step>

  <Step title="Create the metafield (if it doesn't exist yet)">
    Choose whether to create it under the `voyado` namespace, or skip creation and save the mapping as inactive until you create it yourself.
  </Step>

  <Step title="Save">
    Leave the **Enabled** toggle on, then select **Save**.
  </Step>
</Steps>

### Creating a new metafield manually

If the metafield you want doesn't exist in Shopify yet and you'd rather create it yourself first:

<Steps>
  <Step title="Create the definition in Shopify">
    Go to **Settings** > **Metafields and metaobjects** > **Customers** > **Add definition**.
  </Step>

  <Step title="Save it">
    Create and save the metafield.
  </Step>

  <Step title="Complete the mapping">
    Go back to **Attribute Mapping** in the Voyado Engage app and complete your mapping.
  </Step>
</Steps>

## How syncing works

Once a mapping is active, it's applied automatically. Here's what triggers a sync:

| Trigger                              | What happens                                                                                         |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| A customer is created in Shopify     | A contact is created (or updated, if one already exists) in Voyado with all mapped attribute values. |
| A customer is updated in Shopify     | Mapped attributes are updated in Voyado.                                                             |
| A metafield is updated on a customer | The relevant mapped attribute is updated in Voyado.                                                  |
| You run a manual full sync           | All customers are re-synced using your current mapping configuration.                                |

This applies whether the sync happens in real time through webhooks, or as part of a bulk import (for example, during onboarding or a manual re-sync). Both use whatever mapping configuration is active at the time.

## Good to know

<Tip>
  A metafield can only be mapped to one Voyado attribute, and an attribute can only be the target of one mapping. You can't map the same field twice.
</Tip>

<Note>
  If a Shopify metafield has no value for a customer, we don't overwrite the existing value in Voyado. An empty source field never blanks out existing data.
</Note>

<Warning>
  If a mapped Voyado attribute is later deleted in Engage, or a mapped Shopify metafield definition is removed, the mapping is flagged as **Broken** the next time you open the field mapping section.
</Warning>

<Note>
  For Dropdown attributes, if an incoming value during sync doesn't match any allowed value in Voyado, that update is skipped and a warning is written to the sync log rather than the sync failing outright.
</Note>

<Info>
  Any metafield the app creates on your behalf is always placed under the `voyado` namespace. This keeps app-managed fields collision-free and easy to identify, and means they can be cleanly removed if you ever uninstall the app. If you already store similar data under `custom` or another namespace, you'll need to map those fields manually; the app doesn't auto-detect or migrate existing data.
</Info>

<Warning>
  Syncing currently only goes one way: Shopify to Voyado. Changes you make to an attribute directly in Voyado Engage aren't pushed back to Shopify.
</Warning>

<Note>
  Per-mapping behavior for null or empty values isn't configurable yet. Support for that is planned for a future release.
</Note>

## Exclude orders from syncing

Merchants (or other Shopify apps) can exclude individual orders from syncing to Voyado Engage. The exclusion holds for as long as the metafield is set, and can be reversed by clearing it. This is controlled by a dedicated metafield on the Shopify order.

<Note>
  This is separate from customer attribute mapping above. It applies to the order resource, not the customer resource, and isn't part of the mapping configuration.
</Note>

When the exclusion metafield is present and set to `true` on an order, the Voyado Engage app skips that order in every sync operation, no matter how many times it's subsequently updated.

### The exclusion metafield

| Property  | Value                                                                     |
| --------- | ------------------------------------------------------------------------- |
| Namespace | `voyado`                                                                  |
| Key       | `exclude_from_sync`                                                       |
| Type      | boolean                                                                   |
| Full key  | `voyado.exclude_from_sync`                                                |
| Set by    | You, or any third-party Shopify app with write access to order metafields |

<Warning>
  The Voyado Engage app never sets this metafield itself. It's up to you, or another app, to apply it to orders that should be excluded.
</Warning>

### What gets excluded

| Operation                | API endpoint      | Behavior                                                   |
| ------------------------ | ----------------- | ---------------------------------------------------------- |
| Order communication sync | `api/v2/orders`   | The order isn't synced to Voyado.                          |
| Receipt sync             | `api/v2/receipts` | No receipt is created or updated in Voyado for this order. |

### How exclusion and correction work

The exclusion check runs on every event tied to an order, including creation, updates, fulfillment, and cancellation. The app reads the current value of `voyado.exclude_from_sync` at the time of each event and acts on it directly; it isn’t cached or treated as a permanent state.

| Scenario                                                | Behavior                                                                             |
| ------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| Metafield set to `true` at order creation               | Order is excluded from all sync operations.                                          |
| Metafield set to `true` after order creation            | Order is excluded from all subsequent sync operations.                               |
| Metafield set to `false` after exclusion                | Order is no longer excluded, and syncs normally on the next event or manual re-sync. |
| Metafield removed entirely                              | Treated the same as setting it to `false` — the order is no longer excluded.         |
| Manual re-sync triggered after correcting the metafield | Order is included and fully processed.                                               |
| Order updated multiple times while excluded             | All update events are ignored for sync purposes.                                     |
| Manual full re-sync triggered while still excluded      | Order is skipped during the re-sync.                                                 |

<Tip>
  If you set the metafield by mistake, just set it back to `false` (or remove it) and trigger a re-sync, either by updating the order in Shopify or running a manual re-sync in the app.
</Tip>

### Sync coverage

The exclusion check applies across every sync mechanism, with no exceptions.

| Sync mechanism              | Exclusion check applied | Detail                                                                                                                                      |
| --------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Incremental sync (webhooks) | Yes, on every event     | The metafield is read at the start of every order webhook event, before any processing begins. If `true`, the entire event is skipped.      |
| Bulk data import sync job   | Yes, on every order     | The metafield is checked for each order before processing. Excluded orders are skipped and logged; the job continues with remaining orders. |

<Note>
  For the bulk import job, `voyado.exclude_from_sync` isn't included in the standard order export payload. It has to be fetched explicitly alongside order data from the Shopify Admin API.
</Note>

### Logging

Every time an order event comes in and the order is excluded, we log:

* Order ID
* Event type that triggered the check (for example, `order/updated` or `order/paid`)
* Reason: excluded via `voyado.exclude_from_sync`
* Timestamp

<Info>
  Excluded orders aren't surfaced as errors anywhere in the app. They're silent from your perspective and logged only for internal debugging.
</Info>
