Skip to main content

Product Mapping

Product Mapping is the core feature of Tapestry Stitch that transforms Shopify product data into the format required by Bloomreach. Through customizable field mappings, you can control exactly how your product information is synchronized between systems.

Overview

Product Mapping allows you to:

  • Define data transformations using Liquid templates
  • Map Shopify fields to Bloomreach attributes
  • Control data types to ensure proper JSON formatting
  • Preview transformations before syncing
  • Import/Export mappings for backup or replication

Basic Concepts

Entities

Product mappings operate on two entity types:

Product

Product-level attributes apply to the entire product and are the same across all variants.

Examples:

  • title - Product name
  • description - Product description
  • brand - Product vendor/brand
  • thumb_image - Featured product image
  • category_paths - Product collections

Variant

Variant-level attributes apply to individual product variants and can differ between variants of the same product.

Examples:

  • price - Variant price
  • sku - Stock keeping unit
  • inventory_quantity - Available inventory
  • color - Variant color option
  • size - Variant size option

Bloomreach Target

The Bloomreach Target is the field name in Bloomreach where the data will be stored. This should match the expected attribute names in your Bloomreach catalog schema.

Reserved Words

Bloomreach has reserved field names that cannot be used as custom attributes. Common reserved words include: score, rank, query, and others. For a complete list, refer to the Bloomreach Reserved Words Documentation.

Common targets:

  • id - Unique product or variant identifier
  • title - Display name
  • price - Product price
  • availability - Stock availability
  • custom_attribute_name - Any custom field you define

Shopify Source

The Shopify Source uses Liquid template syntax to reference and transform Shopify data. This powerful templating language allows you to access nested data, perform calculations, and apply transformations.

Simple examples:

{{ product.title }}
{{ variant.price }}
{{ product.vendor }}

Advanced examples:

{%- assign total = 0 -%}
{%- for variant in product.variants -%}
{%- assign total = total | plus: variant.inventoryQuantity -%}
{%- endfor -%}
{{ total }}

See the Liquid Filters documentation for available custom filters.

Types

Types determine how values are formatted in the final JSON output to Bloomreach:

String

Text values, properly escaped and quoted.

"title": "Example Product"

Use for: Names, descriptions, URLs, SKUs

Integer

Whole numbers without decimal points.

"quantity": 42

Use for: IDs, inventory counts, whole number values

Float

Decimal numbers with floating-point precision.

"price": 29.99

Use for: Prices, weights, ratings, percentages

Boolean

True/false values (unquoted).

"available": true

Use for: Flags, availability status, feature toggles

Object

Complex JSON objects or arrays. This type is special because it can:

  • Build nested JSON structures
  • Create arrays of any type
  • Define a JSON schema for validation during sync
"category_paths": [
{"id": "collection-1", "name": "Category 1"},
{"id": "collection-2", "name": "Category 2"}
]

Use for: Arrays, nested objects, complex data structures

JSON Schema Validation

When using the object type, you can optionally define a JSON schema to validate the rendered output during the sync job. If validation fails, the sync job will log an error and skip the invalid data.

Benefits:

  • Catch malformed data early
  • Ensure consistent data structure
  • Prevent invalid data from reaching Bloomreach

Creating & Editing Mappings

Creating a New Mapping

  1. Navigate to Product Mappings in the Tapestry Stitch admin
  2. Click "New mapping" in the top right
  3. Select the Entity (Product or Variant)
  4. Enter the Bloomreach Target (e.g., title, price, custom_field)
  5. Choose the Type (string, integer, float, boolean, or object)
  6. Write the Shopify Source using Liquid syntax
  7. Click "Create" to save

Editing an Existing Mapping

  1. Click on any mapping in the table
  2. Update the fields as needed
  3. Click "Save" to apply changes
info

The Bloomreach Target and Entity cannot be changed after creation. To change these, delete the mapping and create a new one.

Example: Product Title with Translation

Entity: Product
Bloomreach Target: title
Type: string
Shopify Source: {{ "product.title" | translate }}

This mapping uses the translate filter to automatically return the localized product title based on the current locale.

Example: Total Inventory Calculation

Entity: Product
Bloomreach Target: total_inventory
Type: integer
Shopify Source:
{%- assign total_inventory = 0 -%}
{%- for variant in product.variants -%}
{%- assign total_inventory = total_inventory | plus: variant.inventoryQuantity -%}
{%- endfor -%}
{{ total_inventory }}

This mapping calculates the total inventory across all variants of a product.

Working with Object Types

The object type is the most powerful mapping type, allowing you to build complex JSON structures including arrays and nested objects.

Building Arrays

Arrays can contain strings, integers, floats, booleans, or nested objects:

String array:

[
{%- for option in product.options -%}
{{ "option.name" | translate | json }}
{%- unless forloop.last -%}, {% endunless -%}
{%- endfor -%}
]

Object array:

[
{%- for collection in product.collections -%}
{
"id": {{ "collection.handle" | translate | json }},
"name": {{ "collection.title" | translate | json }}
}{% unless forloop.last %},{% endunless %}
{%- endfor -%}
]

Schema Validation

When creating an object-type mapping, you can define a JSON schema to validate the rendered output:

{
"type": "array",
"items": {
"type": "object",
"required": ["id", "name"],
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
}
}
}

If the rendered Liquid template doesn't match this schema during sync, an error will be logged and the invalid data will be skipped.

Example: Category Paths

This is one of the default mappings that demonstrates the power of the object type:

Entity: Product
Bloomreach Target: category_paths
Type: object
Shopify Source:
[
{%- for collection in product.collections -%}
{
"id": {{ "collection.handle" | translate | string }},
"name": {{ "collection.title" | translate | string }}
}{% unless forloop.last %},{% endunless %}
{%- endfor -%}
]

This creates an array of category objects, each with an id and name property, translated to the current locale.

Preview Feature

The Preview feature is one of the most powerful tools for developing and debugging your product mappings. It allows you to see exactly how your Shopify data will be transformed before running a sync.

Opening the Preview

Click the "Preview" button in the top right of the Product Mappings page to open the preview modal.

Selecting a Product

  1. Click "Select Product" in the preview modal
  2. Use the Shopify resource picker to choose any product from your store
  3. The preview will automatically load and display the transformation

Understanding the Tabs

The preview modal has two tabs:

Shopify Tab

Shows the raw Shopify product data along with catalog context (locale, URL, etc.) that's available to your Liquid templates.

What you see:

  • Complete product object with all fields
  • Catalog configuration (locale, URL)
  • All data available for reference in Liquid templates

Use this to:

  • Understand the structure of Shopify data
  • Find the correct field paths for your mappings
  • See what data is available for a specific product

Bloomreach Tab

Shows the final transformed payload that will be sent to Bloomreach, exactly as it will appear after your mappings are applied.

What you see:

  • Product-level attributes
  • Array of variant objects
  • Final JSON structure sent to Bloomreach

Use this to:

  • Verify your mappings are working correctly
  • Debug transformation issues
  • Confirm data types are correct

Copy JSON Feature

Both tabs include a "Copy JSON" button that copies the current tab's JSON to your clipboard.

ChatGPT Prompt Example

After copying the Shopify JSON, you can use ChatGPT to help write Liquid templates. Here's an effective prompt pattern:

I have a Shopify product with this JSON structure:
[paste the Shopify JSON here]

I need to write a Liquid template that extracts [describe what you need].

The template should:
- [specific requirement 1]
- [specific requirement 2]
- Return [expected output format]

Please provide the Liquid template code.

Example:

I have a Shopify product with this JSON structure:
[paste JSON]

I need to write a Liquid template that creates an array of all image URLs
from the product, excluding the featured image.

The template should:
- Loop through product.media
- Filter for images only (not videos)
- Skip the featuredMedia
- Return a JSON array of URL strings

Please provide the Liquid template code.

Locale Selection

If your store has multiple locales configured, you can use the locale dropdown to preview how translations will appear in different markets.

Refresh Button

Click "Refresh" to re-fetch the product data and re-run all transformations. This is useful after editing mappings to see the changes immediately.

Import/Export

The Import/Export feature allows you to backup your mappings, replicate configurations across stores, or share mapping configurations with team members.

Exporting Mappings

  1. Click "Export mappings" in the Product Mappings page
  2. All mappings are copied to your clipboard as JSON
  3. Paste into a file for backup or sharing

Export format:

{
"shop": "example-store.myshopify.com",
"exportedAt": "2025-01-15T10:30:00.000Z",
"mappings": [
{
"resource": "product",
"targetAttribute": "title",
"sourceValue": "{{ product.title }}",
"type": "string"
}
// ... more mappings
]
}

Importing Mappings

  1. Click "Import mappings"
  2. Paste the exported JSON
  3. Click "Import"

Upsert Behavior

The import process uses upsert logic:

  • Matching mappings (same entity + target) are updated with the new source value and type
  • New mappings (no match) are created
  • Existing mappings not in the import are left unchanged

This allows you to:

  • Safely import partial mapping sets
  • Update specific mappings without affecting others
  • Merge configurations from multiple sources

Import results:

Import complete! 5 created, 12 updated, 8 unchanged

Use Cases

Backup before major changes:

1. Export current mappings
2. Save to file with date
3. Make changes
4. Restore if needed by importing the backup

Replicate across stores:

1. Export from production store
2. Import to staging/development store
3. Adjust as needed for environment differences

Share configurations:

1. Export your working mappings
2. Share JSON with team members
3. They import to their development stores

Default Mappings

Tapestry Stitch comes with a set of default mappings that cover common use cases. You can reset to defaults at any time using the "Reset to Defaults" button.

Default Product Mappings

  • id - Product ID
  • title - Translated product title
  • description - Product description (body)
  • brand - Product vendor
  • total_inventory - Sum of all variant inventory
  • availability - Product is active and in stock
  • thumb_image - Featured image URL
  • url - Product URL on storefront
  • option_names - Translated option names
  • category_paths - Collection hierarchy as objects

Default Variant Mappings

  • id - Variant ID
  • price - Variant price
  • sku - Variant SKU
  • inventory_quantity - Available inventory
  • default_variant - True for first variant
  • color - Color option value
  • size - Size option value
warning

Resetting to defaults will delete all custom mappings and restore only the default set. This action cannot be undone. Export your mappings first if you want to preserve them.

Best Practices

1. Use Type Filters for JSON Output

Always use the appropriate type filter when building JSON to ensure proper formatting:

{
"id": {{ product.id | integer }},
"title": {{ product.title | json }},
"price": {{ variant.price | float }},
"available": {{ product.available | boolean }}
}

See Liquid Filters for detailed documentation on all available filters.

2. Handle Null Values

Use the custom json filter to properly handle null/undefined values:

{{ potentially_null_var | json }}

This outputs null instead of an empty string, keeping JSON valid.

3. Test with Preview

Always use the Preview feature to verify your mappings before syncing:

  1. Select a representative product
  2. Check both Shopify and Bloomreach tabs
  3. Verify data types are correct
  4. Test edge cases (missing data, null values)

4. Use Translation Filters

For multi-locale stores, use the translate filter to ensure proper localization:

{{ "product.title" | translate }}
{{ "product.metafields.namespace.key" | translate }}

5. Export Regularly

Export your mappings periodically as backups:

  • Before major changes
  • After completing a new configuration
  • When you have a stable working setup

6. Document Complex Mappings

For complex Liquid templates, consider adding comments to explain the logic (these won't appear in the output):

{%- comment -%}
Calculate total inventory across all variants
excluding discontinued variants (inventory_policy = continue)
{%- endcomment -%}
{%- assign total = 0 -%}
{%- for variant in product.variants -%}
{%- if variant.inventoryPolicy != 'continue' -%}
{%- assign total = total | plus: variant.inventoryQuantity -%}
{%- endif -%}
{%- endfor -%}
{{ total }}

7. Use Object Type for Arrays

When you need to send arrays to Bloomreach, always use the object type and build valid JSON arrays:

[
{% for item in collection %}
{{ item | json }}{% unless forloop.last %},{% endunless %}
{% endfor %}
]

8. Consider Performance

Complex Liquid templates run for every product during sync. Keep performance in mind:

  • Avoid deeply nested loops when possible
  • Cache values in variables if used multiple times
  • Use efficient Liquid patterns

Troubleshooting

Mapping Not Syncing

  1. Check that the mapping is saved correctly
  2. Verify the Liquid syntax is valid using Preview
  3. Check sync logs for errors
  4. Ensure the Bloomreach target is not a reserved word

Invalid JSON in Bloomreach

  1. Use Preview to inspect the Bloomreach tab
  2. Verify all type filters are applied correctly
  3. Check for missing commas or brackets in object types
  4. Validate JSON schema if using object type with schema

Translation Not Working

  1. Ensure locale is configured in shop settings
  2. Verify translation data exists for the locale
  3. Check that field path is correct (e.g., "product.title" not product.title)
  4. Test with different locales in Preview

Missing Data

  1. Verify the Shopify field exists using the Shopify tab in Preview
  2. Check for null/undefined values
  3. Ensure filters are handling missing data gracefully
  4. Review conditional logic in Liquid templates

Additional Resources

Need help? Contact support@tapestry-stitch.com