Shopify product sync
You can sync all products from your Shopify store to a Braze catalog for deeper messaging personalization.
Shopify catalogs will update in near real-time as you make edits and changes to the products in your Shopify store. You can enrich your abandoned cart, order confirmation, and more with the most up-to-date product details and information.
In addition to supporting core Shopify product data, you can sync Shopify collections, product tags, and product metafields to your Braze catalog. These additional fields unlock richer personalization, more precise catalog selections, and more powerful segmentation through Segment Extensions.
Set up your Shopify product sync
If you have already installed your Shopify store, you can still sync your products by following the instructions below.
Step 1: Turn on the sync
You can sync your products to a Braze catalog through the Shopify install flow or on the Shopify partner page.

Step 2: Select your product identifier
Select what product identifier to use as the catalog ID:
- Shopify Variant ID
- SKU
The ID and header values for the product identifier you choose can only include letters, numbers, hyphens, and underscores. If the product identifier doesn’t follow this format, Braze will filter it out of your catalog sync.
This will be the primary identifier you use to reference Braze catalog information.
If you are selecting SKU as your catalog ID, make sure that all your products and variants in your store have a SKU set and they are unique.
- If an item has a missing SKU, Braze cannot sync that product into the catalog.
- If you have more than one product with the same SKU, this can cause unexpected behavior or result in product information being overridden unintentionally by the duplicate SKU.
Step 3: Configure additional product data (optional)
You can optionally enable syncing for product tags, Shopify Collections, and metafields. Enable or modify these settings after the initial sync from the Shopify partner page.
Add product tags, Shopify Collections, and metafields in Shopify first. If they do not exist in Shopify, they will not appear in Braze.

- On the Sync product data to Braze page, select the Sync product tags checkbox to open the Select product tags modal.
- Select up to 20 product tags to sync to your Braze catalog. Only the tags you select will be synced.

- Select Sync Shopify collections to open the collection setup modal.
- Select up to 20 collections to sync.
- The modal provides a searchable list of up to 5,000 of the most recently created or updated collections from your Shopify store.
- Previously selected collections that are no longer in the top 5,000 will still appear in your selection.
Braze uses the Shopify Collection ID to identify synced collections, which are then used when building Catalog selections and segment filters.

Step 4: Track your sync progress
After saving your configuration, Braze will begin syncing your products and update the status to In Progress on your Shopify partner page. The sync time depends on the number of products and variants in your store.
You can leave the page once the sync is in progress; Braze sends you a dashboard notification when the sync completes. After the completion, the status updates to Active and you can view your products by selecting the catalog name on your Shopify partner page.

You can also view synced product tags, metafields, and collections within your Shopify catalog as new columns.

If your sync exceeds your catalog storage limit, Braze stops syncing and new product updates are no longer reflected. Contact your customer success manager to upgrade your tier if needed.
Step 5: Manage your configuration
Each sync type has a summary card on the Shopify partner page showing the total count synced, current status, and a link to your catalog. Select the view icon to view your active configuration and edit it.
You can modify your Shopify product sync, including managing your product tags, collections, and product metafields at any time from the Shopify partner page.

Changing your synced selections may affect active campaigns, Canvases, or catalog selections that reference them. Update active content so they work properly when you apply the changes.
Supported Shopify catalog data
| Field | Data type | Examples |
|---|---|---|
id |
string | 45264808411274 when the catalog product identifier is Shopify Variant ID12345 when the catalog product identifier is SKU (matches the value you selected in Step 2) |
store_name |
string | “your-store” (Shopify store subdomain, without .myshopify.com) |
shopify_product_id |
number | 7939032613002 (stored as a number in your Braze catalog; Shopify APIs may return this ID as a string) |
shopify_variant_id |
number | 45264808411274 (stored as a number in your Braze catalog; Shopify APIs may return this ID as a string) |
product_title |
string | “Classic leather jacket” |
variant_title |
string | “Large / Red”, “Medium”, or “Default Title” for single-variant products |
status |
string | “active”, “draft”, “archived” |
product_image_url |
string | “https://cdn.shopify.com/s/files/1/0641/0970/7402/files/t_shir.jpg?v=1736538760” |
variant_image_url |
string | Same CDN-style URL as the product image when no variant image exists; otherwise a variant-specific image URL |
vendor |
string | “Flash and Thread”, “PantsLabyrinth” |
product_type |
string | “Outerwear”, “T-Shirts” (from the product’s Product type in Shopify) |
product_url |
string | “https://your-store.myshopify.com/products/classic-leather-jacket” |
product_handle |
string | “classic-leather-jacket” |
published_scope |
string | “web”, “global” |
price |
number | 10.00, 24.99Shopify often returns prices as strings (for example "199.00" in the REST Admin API). Braze converts them to numbers for this catalog field. |
compare_at_price |
number | 15.00 when Compare at price is set in Shopify0 when Shopify has no compare-at price. Shopify APIs typically return null for an unset compare-at price; Braze stores 0 in the catalog so the field is always numeric (this is a Braze default, not a value Shopify sends as 0). |
inventory_quantity |
number | 20, 0, or a negative value when overselling is allowed (for example -18) |
options |
string | “Size,Color” Shopify allows up to three option types per product (for example Size, Color, Material). The options value is a comma-separated list of those names. |
option_values |
string | “Medium,Red”, “Large,Red” Each value maps to the same order as options (up to three values). |
sku |
string | “12345”, “SKU-001-RED-L” |
product_tags |
array | ["Summer", "Sale", "New"]Requires product tag syncing. |
collection_ids |
array | [123456789012, 987654321098] (Shopify collection IDs)Requires Shopify collection syncing. |
Metafield columns |
Varies by type | Each synced metafield appears as a separate column named by its key. See Supported metafields in the “Product metafields” tab of step 3 for information. |
Your Shopify catalog is managed by Shopify. To update your catalog, make changes directly in your Shopify store, and they will automatically sync to Braze. To delete your Shopify catalog, go to the Shopify partner page in Braze and deactivate the sync.
Shopify catalog use cases
These use cases show how you can use your synced Shopify catalog data to personalize messages.
Braze syncs up to 250 variants of each Shopify product into your catalog. Variants beyond that limit are not synced. If you need more than 250 variants per product, contact your Braze customer success manager.
Use product tags to personalize messages based on how your products are categorized in Shopify. For example, you can send a promotion featuring all products tagged “Summer Sale” through a catalog selection, or build a segment of users who purchased products tagged “Premium.”
Product tags are stored as an array field on each catalog item. To configure product tag syncing, see Shopify product tags.
Catalog selection
- In Shopify, give relevant products in Shopify the product tag of “Women’s”.

- In Braze, enable tag syncing and select the “Women’s” product tag.

Personalization
- Create a catalog selection that filters for products that have the respective product tag, such as “Women’s”. You can only use one unique array field within a single catalog selection, and up to 50 products in your catalog selection.

- In the message composer, add the selection where you want to template in the products from the catalog selection that are tagged with “Women’s”. For example, you could use an HTML product block like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{% catalog_selection_items se-team-ecommerce_shopify_catalog womens_clothing %}
{% if items[0] == blank %}
{% abort_message('Catalog selection returned no items') %}
{% endif %}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">
{% for item in items %}
{% if forloop.index0 < 3 %}
{% assign title = item.product_title | default: '' %}
{% assign image_url = item.variant_image_url | default: '' %}
{% assign price = item.price | default: '' %}
{% assign url = item.product_url | default: '' %}
<tr>
<td width="200" valign="top" style="padding:12px 12px 12px 0;">
{% if image_url == blank %}
<div style="width:200px;height:200px;background:#f2f2f2;line-height:200px;text-align:center;font-family:Arial,sans-serif;font-size:12px;color:#666;">
No image
</div>
{% else %}
{% if url == blank %}
<img src="{{ image_url }}" width="200" height="200" alt="{{ title | escape }}" style="display:block;border:0;outline:none;text-decoration:none;" />
{% else %}
<a href="{{ url }}" style="text-decoration:none;">
<img src="{{ image_url }}" width="200" height="200" alt="{{ title | escape }}" style="display:block;border:0;outline:none;text-decoration:none;" />
</a>
{% endif %}
{% endif %}
</td>
<td valign="top" style="padding:12px 0;font-family:Arial,sans-serif;font-size:14px;line-height:20px;color:#111;">
{% if title != blank %}<div style="font-weight:600;">{{ title | escape }}</div>{% endif %}
{% if price != blank %}<div>Price: ${{ price }}</div>{% endif %}
{% if url != blank %}<div><a href="{{ url }}" style="color:#F84B09;">View product</a></div>{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</table>
Or, if you want to mention specific products tagged with “Women’s” in a push notification, you can use the Add Personalization tool and specify your catalog items.
1
2
3
4
5
Checkout the latest women's clothing:
{% catalog_selection_items se-team-ecommerce_shopify_catalog womens_clothing %}
{{ items[0].product_title}}{{items[0].price}}
{{ items[1].product_title}}{{items[1].price}}
{{ items[2].product_title}}{{items[2].price}}

Catalog segmentation (SQL)
Use Segment Extensions to build segments based on users who interacted with a product tag. For example, to find users who have engaged with catalog items that contain a specific product tag, use this query:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- Description:
-- This query fetches users who have engaged with catalog items that contain a specific product tag. It joins the catalog
-- to custom events by matching any element in an array within events.properties.products (e.g. any product
-- with variant_id equal to a catalog item), using Snowflake LATERAL FLATTEN to explode the array.
SELECT
DISTINCT(events.user_id)
FROM
USERS_BEHAVIORS_CUSTOMEVENT_SHARED AS events,
LATERAL FLATTEN(input => GET_PATH(TRY_PARSE_JSON(events.properties), 'products'), outer => false) AS event_item
JOIN CATALOGS_ITEMS_SHARED AS items ON (
(
items.field_name = 'id'
AND
items.field_value = GET_PATH(event_item.value, 'variant_id')::STRING
)
OR
items.item_id = GET_PATH(event_item.value, 'variant_id')::STRING
)
WHERE
events.name = 'ecommerce.order_placed'
and events.app_group_id = '<app_group_id>'
AND items.catalog_id = '<catalog_id>'
AND (items.field_name = 'product_tags' AND ARRAY_CONTAINS('<product_tag_value>'::VARIANT, TRY_PARSE_JSON(items.field_value)));
Use Shopify collections to pull curated product groupings into your messages that are also used on your Shopify site and app experiences. For example, feature “New Arrivals” in a promotional email, cross-sell “Best Sellers” in an abandoned cart Canvas, or target users who browsed a seasonal collection.
Catalog selection
- In Shopify, create a “New Women’s Products - In Stock” collection with your top-performing products.

- In Braze, enable collection syncing and select “Women’s Products - In Stock”.

For Shopify collections, you must use the Collection ID, which is found in the URL when you view the collection. For example, a URL of https://admin.shopify.com/store/se-team-ecommerce/collections/470645342446 has the Collection ID of 470645342446.
Personalization
- Create a catalog selection named “New Women’s Products - In Stock” that is filtered with products that have that collection’s ID. You can only use one unique array field within a single catalog selection, and up to 50 products in your collection.
- You can also create your own custom selections by filtering with the Collections field.

- In your message, template in your collection by using your created selection or directly referencing the collection. For example, you could use an HTML product block like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{% catalog_selection_items se-team-ecommerce_shopify_catalog shopify_collection_womens_instock %}
{% if items[0] == blank %}
{% abort_message('Catalog selection returned no items') %}
{% endif %}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">
{% for item in items %}
{% if forloop.index0 < 3 %}
{% assign title = item.product_title | default: '' %}
{% assign image_url = item.variant_image_url | default: '' %}
{% assign price = item.price | default: '' %}
{% assign url = item.product_url | default: '' %}
<tr>
<td width="200" valign="top" style="padding:12px 12px 12px 0;">
{% if image_url == blank %}
<div style="width:200px;height:200px;background:#f2f2f2;line-height:200px;text-align:center;font-family:Arial,sans-serif;font-size:12px;color:#666;">
No image
</div>
{% else %}
{% if url == blank %}
<img src="{{ image_url }}" width="200" height="200" alt="{{ title | escape }}" style="display:block;border:0;outline:none;text-decoration:none;" />
{% else %}
<a href="{{ url }}" style="text-decoration:none;">
<img src="{{ image_url }}" width="200" height="200" alt="{{ title | escape }}" style="display:block;border:0;outline:none;text-decoration:none;" />
</a>
{% endif %}
{% endif %}
</td>
<td valign="top" style="padding:12px 0;font-family:Arial,sans-serif;font-size:14px;line-height:20px;color:#111;">
{% if title != blank %}<div style="font-weight:600;">{{ title | escape }}</div>{% endif %}
{% if price != blank %}<div>Price: ${{ price }}</div>{% endif %}
{% if url != blank %}<div><a href="{{ url }}" style="color:#F84B09;">View product</a></div>{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</table>
Or, if you want to mention specific new products in a push notification, you can use the Add Personalization tool and specify your catalog items.
1
2
3
4
5
Checkout the latest women's clothing:
{% catalog_selection_items se-team-ecommerce_shopify_catalog shopify_collection_womens_instock %}
{{ items[0].product_title}}{{items[0].price}}
{{ items[1].product_title}}{{items[1].price}}
{{ items[2].product_title}}{{items[2].price}}

Catalog segmentation (SQL)
Create a segment of users who interacted with a collection. Use Segment Extensions to build segments based on collection membership. For example, to find users who purchased products from a specific collection in the last year, use this query:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- Description:
-- This query fetches users who have engaged with catalog items that contain a specific collection ID. It joins the catalog
-- to custom events by matching any element in an array within events.properties.products (e.g. any product
-- with variant_id equal to a catalog item), using Snowflake LATERAL FLATTEN to explode the array.
SELECT
DISTINCT(events.user_id)
FROM
USERS_BEHAVIORS_CUSTOMEVENT_SHARED AS events,
LATERAL FLATTEN(input => GET_PATH(TRY_PARSE_JSON(events.properties), 'products'), outer => false) AS event_item
JOIN CATALOGS_ITEMS_SHARED AS items ON (
(
items.field_name = 'id'
AND
items.field_value = GET_PATH(event_item.value, 'variant_id')::STRING
)
OR
items.item_id = GET_PATH(event_item.value, 'variant_id')::STRING
)
WHERE
events.name = 'ecommerce.order_placed'
and events.app_group_id = '<app_group_id>'
AND items.catalog_id = '<catalog_id>'
AND (items.field_name = 'collection_ids' AND ARRAY_CONTAINS('<collection_ids_value>'::VARIANT, TRY_PARSE_JSON(items.field_value)));
You can also set up price drop notifications and back-in-stock notifications!
Note that for each use case, you must create a custom event that captures a user’s subscription status in your catalog. The custom event requires an event property that maps to either the SKU or Shopify variant ID that you have selected as part of your Shopify product sync.
Deactivate your product sync
Deactivating the Shopify product sync feature will delete your entire catalog and products. This can also impact any messages that may be actively using the product data from this catalog. Confirm that you have either updated or paused these campaigns or Canvases before deactivation, as this could result in sending messages with no product details. Do not delete the Shopify catalog directly on the catalogs page.
Troubleshooting
If your Shopify product sync runs into an error, it could be a result of the following errors. Follow the instructions on how to correct the issue and resolve the sync:
| Error | Reason | Solution |
|---|---|---|
| Server Error | This occurs if there is a server error on Shopify’s side when we attempt to sync your products. | Deactivate sync and re-sync your entire inventory of products again. |
| Duplicate SKU | This occurs if you use a SKU as your catalog item ID and have products with the same SKU. Because the catalog item ID must be unique, all your products must have unique SKUs. | Audit your full list of products and variants in Shopify to make sure that there are no duplicate SKUs. If there are duplicate SKUs, update these to be unique SKUs only in your Shopify store account. After this is corrected, deactivate sync and re-sync your entire inventory of products again. |
| Catalog Limit Exceeded | This occurs if you exceed your catalog limit. Braze will be unable to finish the sync or keep the syncing active due to no more storage availability. | There are two solutions to this issue: 1. Contact your account manager to upgrade your tier to increase your catalog limit. 2. Free up storage space by deleting any of the following: - Catalog items from other catalogs - Other catalogs - Selections created After using either of the solutions, the sync must be deactivated and then re-synced. |





