CRM Integration
Table of Contents
Shopify Setup
To enable our Shopify synchronization, go to your funnel's "General" settings and click "Add CRM Sync" and choose "Shopify" as CRM Type.
The Shopify synchronization does not need any additional settings. It will automatically send the analysis results to Shopify when a user has completed the analysis. If the user doesn't exist yet in Shopify (identified by the email address provided in the analysis), a new customer profile will be created. You can see the analysis data in the Shopify admin under "Customers" -> "View customer" and find them in the metadata of the customer profile. The items are the same as the ones in the Klaviyo setup below.
Klaviyo Setup
To enable our Klaviyo synchronization, go to your funnel's "General" settings and click "Add CRM Sync" and choose "Klaviyo" as CRM Type. Afterwards you will need to enter your Klaviyo API key and optionally a list ID if you want to add the customer profile on a dedicated list in addition to the event.
If Klaviyo events are enabled in your account, we will send an event to Klaviyo when a user has completed the analysis. The event is sent with the following properties:
| Property | Type | Description |
|---|---|---|
action | string | "AskStella Analysis Completed" (Name of event) |
askstella_funnel_name | string | Short name of the funnel in which this analysis was performed (the subdomain of the funnel) |
askstella_analysis_id | string | The analysis ID in our system |
askstella_analysis_url | string | URL of the analysis results page for this user |
askstella_analysis_result | string | One of our color types (LIGHT, LIGHT_WARM, WARM, DEEP, VERY_DEEP, SOFT_LIGHT, SOFT_MEDIUM, SOFT_DEEP, SOFT_VERY_DEEP, CLEAR) |
askstella_hair_color | string | The hair color the user selected (VERY_LIGHT, MEDIUM_BLONDE, LIGHT, RED_BLONDE, RED, MID_BROWN, BROWN, BLACK) |
askstella_eye_color | string | The eye color the user selected (BLUE, GREY, GREEN, GREEN_BROWN, AMBER, BROWN, DARK_BROWN) |
askstella_skin_color | string | The skin color the user selected (FAIR, LIGHT, MEDIUM_LIGHT, MEDIUM, MEDIUM_DEEP, DEEP) |
askstella_query_string | string | The query string of the URL that led the user to the analysis (e.g. utm parameters you used) |
askstella_products_all | array | One entry per recommended variant, in CRM order (see How product arrays are ordered below). Each item has the shape described in the product fields table. On the profile (not in the event) this field will always be overwritten by the last analysis, so if you have multiple funnels, the products can be from the one funnel and at a later point in time from the other one. |
askstella_[funnel_subdomain]_all | array | Variant IDs in the same CRM order as askstella_products_all, but each item is only { VariantId: string }. VariantId is the variant ID from your shop system (e.g. Shopify). The key uses your funnel’s subdomain, e.g. askstella_mybrand_all. These filds will only be overwritten on the profile if the user completes another analysis in this same funnel. |
askstella_[funnel_subdomain]_[tab_crm_name] | array | For each result-page tab, { VariantId: string } entries for variants whose product is assigned to that tab, in the same global CRM order as the lists above. The key uses your funnel’s subdomain and the tab’s CRM name, e.g. askstella_mybrand_skincare. If a tab’s CRM name is "all", the key is askstella_[subdomain]_tab-all to avoid colliding with the _all list. |
How product arrays are ordered
All product-related arrays (askstella_products_all, askstella_[subdomain]_all, and each askstella_[subdomain]_[tab]) share one recommendation order. That order is computed when the analysis is completed, based on your funnel's result-page tab configuration and the recommended variants for this analysis.
- Tabs define product sequence. When the funnel uses result-page tabs, products are ordered by walking tabs in ascending tab and within each tab by ascending product row. The first time a product appears in that walk sets its position in the global list; if the same product is configured on multiple tabs, it is not duplicated in the global order.
- Variants of one product stay together. All variants of a product are grouped in one block, in the same relative order the recommendation produced for that product.
- Products not on any tab. Recommended variants whose product is not assigned to any result tab are appended after the tabbed products, preserving their original relative order among themselves.
- No tabs. If the funnel has no product tabs on the result page, the products/variants are ordered by name.
- Per-tab variant arrays.Each tab's array is a filter of that global order: only variants whose product belongs to that tab are included, but their sequence matches the global list. A product assigned to several tabs contributes its variants to each of those tab arrays.
In addition, if you have generic "single selection" steps in your funnel, we will also send the selected value of these steps as properties. The property name will be the step's key name and the key of the value:askstella_[Step Key]: [Options Key]e.g. askstella_skin_dryness: VERY_DRY
Each product in the product list will have the following properties:
| Property | Type | Description |
|---|---|---|
title | string | Name of the product |
image | string | Link to the product image |
short_description | string | (Very) short description of the product |
color | string | HEX Color of the product |
link | string | Link to the product page (including the variant ID if necessary) |
If no user (with this email) exists in Klaviyo, we will create a new customer profile and add the event to this new profile. If the user already exists, the event will be added to the user's profile. The same properties of the event will also be set in the user's profile. This way the customer profile will always show the most recent analysis results of the user, while the event history will show all the analysis results the user has received over time.
Klaviyo List
If you provide a list ID in our CRM settings, we will add the user to this list and subscribe them to email marketing in addition to sending the event. The list ID can be found in Klaviyo under "Lists" -> "View list" -> "Settings" -> "List ID". If you want to use a double opt-in list or if you want to subscribe the user directly to the list, you can set this up in Klaviyo.
Klaviyo Examples
The examples below show common ways to use the analysis data we push into Klaviyo in email template. The first example shows a simple product-recommendation email the send the analysis link to the user and highlights one key product from the recommendations before listing all other products. The second example shows how to render the products of a specific result-page tab by loading the product data from our ID arrays using the Klaviyo ↔ Shopify catalog.
Email Setup Example
Video tutorial demonstrating how to set up a Klaviyo flow to send an automated email after a user has completed an analysis. The tutorial covers creating a flow, setting up triggers, and designing the email template with dynamic content (German only):
Used HTML code in this tutorial:
Hallo {{ person.first_name }}! Vielen Dank, dass Du unsere Analyse durchgeführt hast. Hier geht es zu Deinem Analyse
Ergebnis. {{ event.askstella_analysis_url }}
<div style="margin: 9px 18px">
<strong>Der für Dich passende "Flawless Finish Concealer":</strong>
{% for product in event.askstella_products_all %} {% if "Flawless Finish Concealer" in product.title %}
<div style="margin-bottom: 20px">
<a href="{{ product.link }}">
{% if product.image %}
<img src="{{ product.image }}" alt="{{ product.title }}" style="max-width: 100%; height: auto" />
{% endif %}
<h3>{{ product.title }}</h3>
</a>
</div>
{% endif %} {% endfor %}
</div>
<div style="margin: 9px 18px">
<h2>Hier sind Deine weiteren Produktempfehlungen:</h2>
{% for product in event.askstella_products_all %} {% if "Flawless Finish Concealer" not in product.title %}
<div style="margin-bottom: 20px">
<a href="{{ product.link }}">
{% if product.image %}
<img src="{{ product.image }}" alt="{{ product.title }}" style="max-width: 100%; height: auto" />
{% endif %}
<h3>{{ product.title }}</h3>
</a>
</div>
{% endif %} {% endfor %}
</div>Tab Product Recommendations Example
This example shows how to render the product recommendations of a specific result-page tab inside a Klaviyo email, pulling live product data (image, title, variant, link) from your connected shop catalog at send time. It uses the askstella_[funnel_subdomain]_[tab_crm_name]event/profile property together with Klaviyo's catalog lookup tag and the variant IDs we provide.
This works with any shop system whose catalog is synced into Klaviyo — Shopify, BigCommerce, WooCommerce, custom catalogs fed through Klaviyo's Catalogs API, etc. The only hard requirement is that the variant IDs we send match the IDs in your Klaviyo catalog so the {% catalog %} lookup can resolve them. The snippet below uses integration='shopify' as a concrete example.
Picking the right array
For a funnel with the subdomain my-funnel and a tab whose CRM name is bestseller, the array on the event and profile is named:
askstella_my-funnel_bestseller
In our platform, go to the menu item "StellaMatch" to see all your funnels and their subdomains. Make sure that the CRM sync to Klaviyo is enabled for the funnel you want to use. The CRM name of the result page tab can be found in the settings of the result page of the respective funnel. Go to the funnel settings and click on "Result Page", then scroll down to the product tabs and click on the tab you are interested in. Below the tab name you will see the CRM name (and can change it if you want).
Each entry of the array has the shape { VariantId: string }, where VariantId is the variant ID from your shop system as it appears in your Klaviyo catalog. To iterate over the array, use the lookup filter. If your flow is triggered by ourAskStella Analysis Completed event, use the event object:
{% for w in event|lookup:'askstella_my-funnel_bestseller' %}
{# ... w.VariantId ... #}
{% endfor %}If your flow is triggered from a profile property (list add, segment, etc.), use person object in the lookup filter:
{% for w in person|lookup:'askstella_my-funnel_bestseller' %}
{# ... w.VariantId ... #}
{% endfor %}Available catalog fields
Inside a {% catalog VariantId integration='shopify' %} block the following fields are available on catalog_item when the catalog is synced from Shopify. The variant sub-object reflects the exact variant you looked up (e.g. the color), while the top-level fields describe the parent product. Other integrations expose a similar but not always identical set of fields — when in doubt, render {{ catalog_item }} inside a preview to see what your catalog returns.
| Property | Type | Description |
|---|---|---|
catalog_item.title | string | Parent product title (e.g. “Hydrating Serum”). |
catalog_item.description | string | Product description from your shop. Contains HTML. |
catalog_item.url | string | Link to the product detail page in your shop. |
catalog_item.featured_image.full.src | string | Full-size product image URL. Also available as .thumbnail.src. |
catalog_item.id | string | Internal Klaviyo product ID (the parent product, not the variant). |
catalog_item.variant.title | string | Variant title (e.g. “50 ml / Warm”). Equals "Default Title" when the product has no variants. |
catalog_item.variant.url | string | Deep link to the product page with the variant pre-selected (…?variant=VariantId). Use this instead of catalog_item.url so the customer lands on the exact variant Stella recommended. |
catalog_item.variant.featured_image.full.src | string | Variant-specific image if one is set in Shopify. Can be empty — fall back to catalog_item.featured_image.full.src. |
catalog_item.variant.price | string | Variant price. Wrap with {% currency_format %} to format it for the store currency. |
For a full, always up-to-date reference check Klaviyo's catalog lookup tag documentation.
Template snippet
The block below loops over the first 8 products of the bestseller tab, resolves each variant through the Shopify-synced catalog, and renders a responsive two-column card grid. Products without a usable image are skipped so the layout stays clean. Drop it into a custom HTML / table block in your Klaviyo email template. Replace the subdomain and tab name inaskstella_my-funnel_bestsellerwith your funnel's subdomain and the CRM name of the tab you want to render.
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" style="font-size:0; line-height:0;">
{% if event|lookup:'askstella_my-funnel_bestseller' %}
{% for w in event|lookup:'askstella_my-funnel_bestseller' %}
{% if forloop.counter <= 8 %}
{% catalog w.VariantId integration='shopify' %}
{% if catalog_item.featured_image.full.src != "" %}
<table cellpadding="10" cellspacing="0" border="0"
style="display:inline-block; vertical-align:top; width:50%; max-width:320px;">
<tr>
<td align="center" style="font-size:14px; line-height:1.4;">
<table width="100%" cellpadding="12" cellspacing="0" border="0">
<tr>
<td align="center">
<a href="{{ catalog_item.variant.url }}" target="_blank">
<img
src="{{ catalog_item.variant.featured_image.full.src|default:catalog_item.featured_image.full.src }}"
width="260"
style="width:100%;max-width:260px;height:auto;display:block;border:0;border-radius:12px;"
alt="{{ catalog_item.title }}">
</a>
<br><br>
<strong style="font-size:16px;">
<a href="{{ catalog_item.variant.url }}" target="_blank" style="text-decoration:none;">
{{ catalog_item.title }}
</a>
</strong>
<br>
{% if catalog_item.variant.title != "Default Title" %}
<span style="font-size:13px;">{{ catalog_item.variant.title }}</span>
{% endif %}
</td>
</tr>
</table>
</td>
</tr>
</table>
{% endif %}
{% endcatalog %}
{% endif %}
{% endfor %}
{% endif %}
</td>
</tr>
</table>Adapting the snippet
- Replace
my-funnelwith your funnel's subdomain andbestsellerwith the CRM name of the tab you want to render. The CRM name is the one you configured for the tab in the funnel builder — it is case-sensitive and must match exactly. - Change
forloop.counter <= 8to control how many products are shown. Klaviyo limits practical email size, so keep the number reasonable (typically 4–12). - The
default:filter on the image falls back from the variant image to the parent product image when a variant has no dedicated picture. On integrations that don't exposecatalog_item.variant.featured_image, drop the variant part and just usecatalog_item.featured_image.full.src. - To show a price, add
{% currency_format catalog_item.variant.price %}— this respects your store's currency settings. - If you want a single-column layout for mobile, change
width:50%on the inner card table towidth:100%(or use Klaviyo's responsive table blocks instead of the inline style). - The special array
askstella_[subdomain]_allwill list all products from this funnel if you do not want to filter by a specific tab (or have no tabs).
Tip: when previewing the email, choose a recipient profile that has actually received an AskStella Analysis Completed event for the funnel. Otherwise the array will be empty and the whole block renders nothing, which is the expected behavior but can feel like a bug during authoring.