Smootify
webflow ecommerce plugin to provide headless shopify
Purpose: Bridge between Webflow design flexibility and Shopify ecommerce power, enabling headless Shopify stores within Webflow projects.
Last verified: December 2025
Account Detailsâ
- Notes: webflow ecommerce plugin to provide headless shopify
- Category: WEBSITE
- Account type: INTERNAL
- Created: December 2025
- Access URL: https://dashboard.smootify.io
- Account owner: Ben Power
Overviewâ
Smootify bridges the gap between the design flexibility of Webflow and the robust e-commerce power of Shopify, empowering you to build headless Shopify stores directly within your Webflow projects. This enables you to leverage Webflow's visual design capabilities while using Shopify as the ecommerce backend for products, orders, inventory, and customer management.
Initial Setupâ
Prerequisitesâ
Before starting, ensure you have:
- A Shopify store with products set up
- A Webflow project ready for ecommerce integration
- Access to both Shopify admin and Webflow designer
Installation Stepsâ
-
Install Smootify App
- Install the Smootify app from either the Shopify App Store or Webflow App Store
- Connect your Shopify store and Webflow project
-
Install Shopify Headless App (Critical)
- Install the Shopify Headless App on the same Shopify store
- This enables essential features:
- Order confirmation emails
- Customer accounts
- Other headless commerce functionalities
Shopify Headless App Configurationâ
The Shopify Headless App is essential for proper functionality. Follow these steps:
Development Token vs Live Tokenâ
Important: The Smootify Shopify App automatically generates a development storefront token upon installation. This allows you to quickly preview and begin building without further configuration.
However, before launching your store to the public, you MUST generate a new storefront token using the official Shopify Headless sales channel.
Why Transition to Live Mode?â
-
Order Confirmation Notifications: The development token does not support order confirmation notifications. Generating a token through the Shopify Headless sales channel is essential for enabling these crucial customer communications.
-
Sales Channel Attribution: The development token doesn't allow you to create a sales channel name. For multi-channel stores (Facebook, Instagram, Shop, etc.), it's fundamental to be able to discern sales from the Webflow site. This can only be done by creating a token with the Headless App. The name you use to create the token will be the sales channel name you see in the orders dashboard.
Step 1: Install Headless Appâ
- Install the Shopify Headless App on the same Shopify store
- This enables essential features:
- Order confirmation emails
- Customer accounts
- Other headless commerce functionalities
Step 2: Create Storefrontâ
- In the Shopify Headless App, click Create Storefront
- This sets up the Storefront API connection
Step 3: Manage Storefront APIâ
- Click Manage Storefront API
- Click Edit to configure permissions
- Enable all Storefront API permissions (critical for full functionality)
- Click Save changes
Step 4: Get Public Tokenâ
- After saving, copy the public token (Storefront API access token)
- This token will be used in Smootify dashboard configuration
Step 5: Configure in Smootify Dashboardâ
- Go to Site settings in your Smootify dashboard
- Click Edit Info
- Replace the existing development token with the new live public token from Shopify
- Click Save Info
Important: Without the Shopify Headless App properly configured with a live token, order confirmation emails, customer accounts, and sales channel attribution will not work.
Webflow Project Connectionâ
Connect Your Webflow Projectâ
- In Smootify dashboard, connect your Webflow project
- Ensure you have the correct Webflow site ID
- Verify the connection is active
Create CMS Collectionsâ
After connecting your Webflow project, you'll need to create CMS collections that Smootify will populate with Shopify data:
Required Collections:
- Products collection - For product data
- Collections collection - For product collections/categories
- Vendors collection - For vendor/brand information (if applicable)
Optional Collections:
- Account pages folder - For customer account pages
These collections will be automatically synced with your Shopify store data.
Custom Code Configurationâ
Smootify allows you to customize behaviour using JavaScript configuration scripts. You can either write custom code or use the built-in customizer.
Using the Customizerâ
The Smootify dashboard includes a customizer that generates the proper script without requiring manual coding:
Configuration Options:
| Option | Description |
|---|---|
| Slug of Products CMS collection | The Webflow CMS collection slug for products |
| Slug of Collections CMS collection | The Webflow CMS collection slug for collections |
| Slug of Vendors CMS collection | The Webflow CMS collection slug for vendors |
| Slug of Account pages folder | The Webflow folder slug for account pages |
| Public Key for Customer Accounts | Public key for customer account functionality |
| Order Page Url | URL for order confirmation pages |
| Subscription Page Url | URL for subscription management pages |
| Restricted Pages Redirect | Redirect URL for restricted/unauthorized pages |
| Cache Duration | How long to cache data (performance optimization) |
| Show only images of currently selected variant | Filter product images by selected variant |
| Select market based on browser language | Auto-select market based on user's browser language |
| Enable Auto Analytics Tracking | Automatically track ecommerce events |
| Format prices based on browser settings | Localize price formatting |
| Preload products on idle time | Performance optimization - preload products when browser is idle |
After configuring, click Copy Script to get the generated configuration code.
Custom JavaScript Configurationâ
If you need more control, you can write custom JavaScript configuration. The customizer generates the proper script structure that you can then modify.
Smootify APIsâ
Smootify exposes JavaScript APIs for advanced customization and integration. These APIs allow you to interact with Shopify's Storefront API, manage cart operations, handle customer data, and customise market settings.
Wait for Smootify to Loadâ
The Smootify instance is only available after APIs are loaded. Always wrap your code in the API loaded callback:
document.addEventListener("smootify:loaded", () => {
console.log("Smootify APIs are available");
// Your code here
});
Alternative: Script Loadingâ
If you're hosting scripts elsewhere (not inline), you can use the smootify-load script type. The script will be loaded after APIs are available:
<script
src="https://yourcdnurl.tld/yourscript.js"
type="smootify-load"
data-type="module"
></script>
Note: You can also upload JS files to Shopify > Content > Files and use that as a CDN if needed.
Query APIâ
Access the Shopify Storefront GraphQL API without managing fetch calls, tokens, or authentication:
Syntaxâ
Smootify.query(query);
Smootify.query(query, variables);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | - | GraphQL query string |
variables | Record<string,any> | Optional query variables |
Example: Get Shop IDâ
document.addEventListener("smootify:loaded", async () => {
const result = await Smootify.query(`{
shop {
id
}
}`);
const shopID = result.shop.id;
console.log("Shop ID:", shopID);
});
The Query API handles all authentication, token management, and API calls automatically.
Query Customer APIâ
Query customer fields for the currently logged in customer. This automatically fetches from either the legacy or new Customer Accounts API based on whether you're using passwordless login.
Important: This is limited to querying the Customer object only, not the full Customer Accounts API.
Error Handling: If the customer is not logged in, this will throw an error. Always wrap calls in try/catch blocks.
Syntaxâ
Smootify.queryCustomer(fields);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
fields | string | - | GraphQL fields to query (Customer object schema) |
Example: Load Metafield After Customer Status Loadedâ
document.addEventListener('smootify:user_auth_change', async (event) => {
const shopifyCustomer = event.detail;
if (shopifyCustomer) {
try {
const {customer} = await Smootify.queryCustomer(`
id
customField: metafield(namespace:"custom", key:"my_key") {
value
}
`);
console.log(customer.id, customer.customField);
} catch (e) {
console.log('Customer not logged in or error with the query', e);
}
} else {
// Customer logged out - redirect if needed
}
});
Example: Query Metafield on Button Clickâ
document.getElementById('my-button').addEventListener('click', async () => {
try {
const {customer} = await Smootify.queryCustomer(`
id
customField: metafield(namespace:"custom", key:"my_key") {
value
}
`);
console.log(customer.id, customer.customField);
} catch (e) {
console.log('Customer not logged in or error with the query', e);
}
});
Set Customer Metafields APIâ
Set customer metafields for the currently logged in customer. Ensure metafields are set as readable/writable from Customer Accounts API.
Important:
- If the customer is not logged in, this will throw an error. Handle errors appropriately.
- This method is not available if you're using legacy customer accounts.
Syntaxâ
Smootify.setCustomerMetafields(...metafields);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
metafields | Object | - | One or more metafield objects with key and value properties |
Example: Save Metafield After Customer Status Loadedâ
document.addEventListener('smootify:user_auth_change', async (event) => {
const shopifyCustomer = event.detail;
if (shopifyCustomer) {
try {
await Smootify.setCustomerMetafields(
{
key: "popup_seen",
value: "true"
},
{
key: "last_viewed_page",
value: window.location.pathname
}
);
} catch (e) {
console.log('Error setting customer metafields', e);
}
}
});
Apply Coupon Code APIâ
Apply a coupon code to the cart without user interaction. Useful for adding specific coupon codes based on JavaScript interactions.
Syntaxâ
Smootify.applyCouponCode(code);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
code | string | - | Coupon code to apply |
Example: Add Coupon Code on Button Clickâ
document.getElementById("welcome-button").addEventListener("click", () => {
Smootify.applyCouponCode("welcome20");
});
Change Market By Country ISO Code APIâ
Change the market by ISO country code. Useful for IP localisation or manual market selection.
Syntaxâ
Smootify.changeCountryByIsoCode(isoCode);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
isoCode | string | - | ISO country code (e.g., "IT", "US", "GB") |
Example: Change Market to Italy on Button Clickâ
document.getElementById("italy-button").addEventListener("click", () => {
Smootify.changeCountryByIsoCode("IT");
});
Change Market Language APIâ
Change the market language. Useful for IP localisation or manual language selection.
Syntaxâ
Smootify.changeMarketLanguage(isoCode);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
isoCode | string | - | ISO language code (e.g., "IT", "EN", "FR") |
Example: Change Language to Italian on Button Clickâ
document.getElementById("italy-button").addEventListener("click", () => {
Smootify.changeMarketLanguage("IT");
});
Add to Cart APIâ
Add lines to the cart and automatically refresh the cart render. Optionally redirect directly to checkout.
Syntaxâ
Smootify.addToCart(lines);
Smootify.addToCart(lines, goToCheckout);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
lines | CartLineInput[] | - | Array of cart line items to add |
goToCheckout | boolean | false | Whether to redirect to checkout after adding |
CartLineInput Structureâ
{
attributes?: Array<{
key: string;
value: string;
}>;
quantity: number;
merchandiseId: string; // Format: "gid://shopify/ProductVariant/123"
}
Example: Add Item to Cart on Button Clickâ
document.getElementById("product-card-button").addEventListener("click", () => {
const productsToAdd = [
{
attributes: [
{
key: "Attribute Key",
value: "Attribute value",
},
],
quantity: 1,
merchandiseId: "gid://shopify/ProductVariant/1",
},
];
Smootify.addToCart(productsToAdd);
});
Example: Add Product Based on Cart Contentsâ
document.addEventListener("smootify:cart_updated", (event) => {
const cart = event.detail;
const userAddedMyProduct = !!cart.nodes.find(
(node) => node.merchandise.product.title == "My Product"
);
const userAddedMyOtherProduct = !!cart.nodes.find(
(node) => node.merchandise.product.title == "My Other Product"
);
if (userAddedMyProduct && !userAddedMyOtherProduct) {
const productsToAdd = [
{
attributes: [
{
key: "Attribute Key",
value: "Attribute value",
},
],
quantity: 1,
merchandiseId: "gid://shopify/ProductVariant/1",
},
];
Smootify.addToCart(productsToAdd);
}
});
Get Cart ID APIâ
Get the current cart ID. Useful if you want to directly mutate the cart state using your own GraphQL queries.
Syntaxâ
Smootify.getCartID();
Example: Set a Cart Metafieldâ
document.addEventListener("smootify:loaded", async () => {
const cartId = await Smootify.getCartID();
await Smootify.query(
`mutation cartMetafieldsSet($metafields: [CartMetafieldsSetInput!]!) {
cartMetafieldsSet(metafields: $metafields) {
metafields {
id
value
}
userErrors {
field
message
}
}
}`,
{
metafields: [
{
key: "<your-key>",
ownerId: cartId,
type: "<your-type>",
value: "<your-value>",
},
],
}
);
});
Reload Cart APIâ
Re-render the cart. Useful if you've modified the cart state using your own GraphQL queries.
Syntaxâ
Smootify.reloadCart();
Clear Cart APIâ
Remove all items from the cart.
Syntaxâ
Smootify.clearCart();
Format Money APIâ
Format a string (cents) or number as a money string based on the Shopify format.
Syntaxâ
Smootify.formatMoney(cents);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
cents | string | number | - | Price in cents (as string or number) |
Example: Set Text Element as Formatted Priceâ
document.querySelector('.my-text').textContent = Smootify.formatMoney('100');
Add Box to Cart APIâ
Add a group of products as a box. This function requires the Magic Box Add-on to be enabled.
Syntaxâ
Smootify.addBoxToCart(lines);
Smootify.addBoxToCart(lines, boxOptions);
Smootify.addBoxToCart(lines, boxOptions, goToCheckout);
Parametersâ
| Parameter | Type | Default | Description |
|---|---|---|---|
lines | CartLineInput[] | - | Array of cart line items to add as a box |
boxOptions | BoxOptions | - | Optional box configuration (title, image) |
goToCheckout | boolean | false | Whether to redirect to checkout after adding |
BoxOptions Structureâ
{
title?: string; // Custom box title
image?: string; // Image URL (must be hosted on Shopify CDN)
}
Example: Add Box to Cartâ
const productsToAdd = [
{
attributes: [
{
key: "Attribute Key",
value: "Attribute value",
},
],
quantity: 1,
merchandiseId: "gid://shopify/ProductVariant/123123123",
},
{
attributes: [
{
key: "Attribute Key",
value: "Attribute value",
},
],
quantity: 1,
merchandiseId: "gid://shopify/ProductVariant/12312312312",
},
];
const boxOptions = {
title: "My Custom Box",
image: "https://cdn.shopify.com/s/files/1/0563/0689/2909/files/image.webp", // Must be hosted on Shopify CDN
};
Smootify.addBoxToCart(productsToAdd, boxOptions);
JS Eventsâ
Smootify dispatches custom events that you can listen to for any action made on Smootify elements. These events allow you to react to user interactions, cart changes, product loads, and more.
Global Eventsâ
Global events are dispatched on the document element and can be listened to from anywhere in your code.
API Loaded Eventâ
Dispatched after all Smootify modules have been loaded. Use this to ensure APIs are available before using them.
Event Name: smootify:loaded
Example:
document.addEventListener('smootify:loaded', () => {
console.log("Smootify APIs are available");
// Your code here
});
User Auth Change Eventâ
Dispatched on login status change and on page load to notify if a user is effectively logged in or not.
Event Name: smootify:user_auth_change
Event Detail: Customer object (or null if logged out)
Example:
document.addEventListener('smootify:user_auth_change', (event) => {
const customer = event.detail;
if (customer) {
// User is logged in - do something with the customer object
console.log('Customer logged in:', customer);
} else {
// User is logged out - redirect if needed
console.log('Customer logged out');
}
});
Cart Updated Eventâ
Dispatched on any cart changes, including on the cart's first load. Useful for updating UI elements like free shipping bars, cart totals, or analytics tracking.
Event Name: smootify:cart_updated
Event Detail: Cart object
Example:
document.addEventListener('smootify:cart_updated', (event) => {
const cart = event.detail;
// Send cart analytics, open a popup, modify the free shipping bar, etc.
console.log('Cart updated:', cart);
});
Added to Cart Eventâ
Dispatched when any product is added to the cart.
Event Name: smootify:added_to_cart
Event Detail: Object containing lines, cart, and goToCheckout
Example:
document.addEventListener('smootify:added_to_cart', (event) => {
const {lines, cart, goToCheckout} = event.detail;
// Do something with the payload
console.log('Items added:', lines);
console.log('Updated cart:', cart);
console.log('Going to checkout:', goToCheckout);
});
Removed from Cart Eventâ
Dispatched when any product is removed from the cart.
Event Name: smootify:removed_from_cart
Event Detail: Array of line IDs that were removed
Example:
document.addEventListener('smootify:removed_from_cart', (event) => {
const lineIds = event.detail;
// lineIds is an array of elements removed from the cart
console.log('Items removed:', lineIds);
});
Product Loaded Eventâ
Dispatched for each product loaded from the API.
Event Name: smootify:product_loaded
Event Detail: Object containing id and product
Example:
document.addEventListener('smootify:product_loaded', (event) => {
const {id, product} = event.detail;
// Do something with the product
console.log('Product loaded:', id, product);
});
Images Module Loaded Eventâ
Dispatched every time after the Images JS module gets loaded. Note that module loaded doesn't ensure all images have been loaded.
Event Name: smootify:productImagesModuleLoaded
Example:
document.addEventListener('smootify:productImagesModuleLoaded', () => {
// Images module is loaded
console.log('Product images module loaded');
});
Addon State Changed Eventâ
Dispatched if you have an add to cart with Magic Addons every time an add-on gets added or removed.
Event Name: addon:state_change
Event Detail: Object containing wrapper, product, variant, and included
Example:
document.addEventListener('addon:state_change', (event) => {
const {wrapper, product, variant, included} = event.detail;
// Do something (e.g., if the addon is included, show up a property input)
if (included) {
console.log('Addon included for variant:', variant);
} else {
console.log('Addon removed for variant:', variant);
}
});
Product Custom Element Eventsâ
These events are dispatched only on the Smootify Product Custom Element (<smootify-product>).
Variant Change Eventâ
Dispatched each time a new variant has been selected.
Event Name: changeVariant
Event Detail: Variant object
Example:
const productWrapper = document.querySelector('smootify-product'); // First product wrapper element
productWrapper.addEventListener('changeVariant', (event) => {
const variant = event.detail;
// Do something with the variant
console.log('Variant changed:', variant);
});
Plan Change Eventâ
Dispatched each time the variant plan (subscription) changes.
Event Name: changePlan
Event Detail: Object containing plan and variant. Note: plan will be null if the subscription option has been deselected.
Example:
const productWrapper = document.querySelector('smootify-product'); // First product wrapper element
productWrapper.addEventListener('changePlan', (event) => {
const {plan, variant} = event.detail;
// Do something with the variant and the plan
if (plan) {
console.log('Subscription plan selected:', plan);
} else {
console.log('Subscription plan deselected');
}
console.log('Current variant:', variant);
});
Product Variant Custom Element Eventsâ
These events are dispatched by the Variant Custom Element.
Variants Rendered Eventâ
Dispatched each time the variants get rendered.
Event Name: variantsRendered
Example:
document.body.addEventListener('variantsRendered', (event) => {
// Do something after variants have been rendered
console.log('Variants rendered');
});
CSS Snippetsâ
Useful CSS snippets to create features that in Webflow are still not very easy to do and require pseudo elements or advanced CSS selectors.
Variant Buttons Tooltipsâ
When using Variant Buttons swatches, it's sometimes useful to show the buttons without any title (only image or colour for example). By adding the snippet below, you'll get a pseudo element that appears on hover and dynamically shows the title of the option.
Snippet:
<style>
variant-swatches button {
position: relative;
}
variant-swatches button:hover::before {
content: attr(data-value);
position: absolute;
top: -70%;
left: 50%;
z-index: 9999;
padding: 0.2rem 0.5rem;
transform: translateX(-50%);
height: auto;
border-radius: 0.3rem;
background-color: black;
color: white;
font-size: 0.8rem;
}
</style>
Feel free to modify the style according to your own design needs.
Disable Cart Item Skeletonâ
If you want to disable the cart item skeleton loading animation, add the following snippet:
<style>
cart-item.loading>:before,
cart-item.loading bundle-item>:before,
cart-item.loading img {
animation: none !important;
}
</style>
Useful Selectorsâ
Below is a list of useful CSS selectors you might need in Webflow with custom code.
Custom Radio Checkedâ
Webflow allows you to apply the checked state only to the radio input. With the following selector, you can select the Radio Element instead:
.w-radio:has(.w--redirected-checked) {
/* Add your style */
}
Custom Checkbox Checkedâ
Webflow allows you to apply the checked state only to the checkbox input. With the following selector, you can select the Checkbox Element instead:
.w-checkbox:has(.w--redirected-checked) {
/* Add your style */
}
Navbar Openâ
Webflow allows you to apply the open state on the menu only. With the following selector, you can select the body when a menu is open. Further refine the selector if you have multiple menus:
body:has(.w-nav-menu[aria-expanded="true"]) {
/* Add your style */
}
Custom Elementsâ
Smootify provides custom elements that act as the bridge between Shopify and Webflow. These elements enable:
- Product display and variants
- Collection filtering
- Cart functionality
- Checkout integration
- Customer account features
Custom elements are added to your Webflow project and automatically connect to your Shopify store data.
Metaobjectsâ
Metaobjects allow you to load structured data directly from Shopify into your Webflow site. This is useful when you need to let customers modify content directly from Shopify without accessing your Webflow project, or when you want to use Smootify's Add-on Metaobject Creator for complex interactions.
Key Conceptsâ
Metaobject Template:
- You design a single 'Metaobject Template' in Webflow
- Smootify, leveraging the Shopify Storefront API, automatically replicates that template for each metaobject you have in Shopify
- Dynamic data from the metaobject fields is then populated into each Metaobject Template
Dynamic Data Binding:
- Custom attributes and Custom Elements within the 'Metaobject Template' dictate where dynamic Shopify data will be injected into the static elements by Smootify
Shopify Configurationâ
Before using metaobjects in Webflow, you need to configure them in Shopify:
- Go to Shopify panel â Settings â Custom Data â Metaobjects
- Create the metaobject definition in whatever way you like
- Critical: Be sure to enable these options:
- Active-draft status
- Storefronts API access
Metaobject Listingâ
How to design your listings in Webflow to display multiple metaobjects fetched from your Shopify store.
When to Use Metaobject Listingâ
Use metaobject listings when you need to:
- Display multiple metaobjects in a grid or list
- Let customers modify content from Shopify without accessing Webflow
- Use Smootify's Add-on Metaobject Creator for complex interactions
- Show more than 10 metaobject references (Product Metafields are limited to 10)
How to Create a Metaobject Listingâ
Step 1: Copy the Componentâ
- Copy the Metaobject Listing component from Smootify
- This component contains a list of metaobjects fetched from Shopify
Step 2: Customize the Attributesâ
On the Custom Element smootify-metaobjects, modify the following Custom Attributes:
Type:
| Name | Value |
|---|---|
data-type | metaobject_type_to_load |
For example, if you created a Metaobject definition with type "testimonials", use:
| Name | Value |
|---|---|
data-type | testimonials |
Product Metafield (Optional):
Starting from Smootify v1.0.5, you can select metaobjects by a product metafield. This is useful when you need to show more references or use pagination.
To use this feature, set the data-type attribute to:
| Name | Value |
|---|---|
data-type | metafield.namespace.key |
Where you replace namespace.key with the actual namespace and key of the metafield. Note: The metafield type must be a list of Metaobjects.
Additionally, add the attribute:
| Name | Value |
|---|---|
data-product-id | product id |
If you're in the Product Template page, you can bind the value to the CMS:
| Name | Value |
|---|---|
data-product-id | Shopify ID |
Limit (Optional):
Modify the number of metaobjects loaded by setting:
| Name | Value |
|---|---|
data-limit | number |
By default it's set to 10. Avoid adding more than 100 as limit.
Step 3: Style the Grid Elementâ
Inside the component, you'll find a Grid Element that will contain all loaded metaobjects. Style it according to your needs.
Step 4: Style the Pagination Elementsâ
Inside the component, you'll find 3 pagination buttons with the following attributes:
- Next button:
data-action="next" - Previous button:
data-action="prev" - Load more button:
data-action="load-more"
Style them according to your needs. Important: Do not keep all 3 buttons visible at the same time. Either use previous/next OR use the load more button.
Step 5: Design the Metaobject Template Itemâ
In the component, you'll find a Custom Element with tag smootify-metaobject. Add inside it all Webflow elements you require to style your Metaobject Template Item.
Step 6: Add the Metaobject Attributesâ
On any Webflow static element you added inside the smootify-metaobject custom element, you can add the attribute:
| Name | Value |
|---|---|
metaobject | metaobject_field_key |
This binds that static element to the corresponding field defined for the metaobject.
Supported Fieldsâ
| Shopify Type | Webflow Elements | Info |
|---|---|---|
| Single Line Text | Any text element | Will output the text of the field |
| Multi Line Text | Any text element | Will output the text of the field |
| Integer Number | Any text element | Will output the number of the field |
| Double Number | Any text element | Will output the number of the field. The number of digits can be customized with data-digits attribute (e.g., data-digits="2") |
| URL | Any link element | Will output the selected link |
| Color | Any element | Will output on the element the CSS variable --metafield-color, unless you use property="--your-css-variable" |
| File / Generic File | Any link element | If you select generic file, you can output the link |
| File / Image File | Any link, image, and div element | If used on a link element, the link to the image will be rendered. On all other elements, you'll see the image or background image |
| File / Video File | Any div element | Will output a video player of the file |
| Date / Date Time | Any text element | Will output the date/date time in the current browser format |
| Dimension / Volume / Weight | Any text element | Will output the selected value |
| Money | Any text element | Will output the money using the Shopify currency format |
| True or False | Any element | Will hide/show the element based on that value |
| List of Single Line Text | Any text element | Will show all texts concatenated by a comma. Change the separator using separator=",". If you use separator="repeat", the element itself will be repeated |
| List of File / Generic File | Any link element | The link element will be duplicated once for each file. The text content will be the "alt" of the file and the link will be connected to the file link |
| List of File / Image File | Any image element | The image element will be duplicated once for each file |
Additional Attribute for Single Line Text:
Only for fields of type Single Line Text, you can use an additional attribute:
| Name | Value |
|---|---|
data-attr | attribute-to-modify |
This will output the value inside the specified attribute instead of setting the value as the text of the element.
Example:
| Name | Value |
|---|---|
data-attr | data-id |
This will set the value of the field in the data-id attribute of the element.
Fields Visibilityâ
Learn how to show or hide elements based on whether a field exists and what its value is.
Basic Visibility Attributesâ
To control visibility of an element, use these custom attributes:
Show if field exists:
| Name | Value |
|---|---|
if-metaobject | field_key |
This attribute will show the element if the field exists, with 2 exceptions:
- For fields of type True / False: It will be shown if the field is set and is set as True
- For fields of type Integer Number: The element will be shown if the metafield is set and the value is higher than 0
Hide if field exists:
| Name | Value |
|---|---|
unless-metaobject | field_key |
This attribute acts in the opposite way - the element will show only if the metafield doesn't exist.
Check for Valueâ
By default, metafield visibility attributes will just check for the existence of the metafield. If you wish to check for the value inside the metafield, add also the attribute:
| Name | Value |
|---|---|
data-check-value | Desired Value |
Example:
If you created a field of type Single Line Text with key my_option and you want to show an element only when the metafield value is "Option 1", use:
| Name | Value |
|---|---|
if-metaobject | my_option |
data-check-value | Option 1 |
Single Metaobjectâ
Load a specific metaobject directly from Shopify for use in specific contexts.
When to Use Single Metaobjectâ
Use single metaobjects when you need:
- Specific, structured data for a particular context
- To enhance the Vendor Page with brand information
- Dynamic banner/CTA sections controlled from Shopify
- Product-specific content like size charts, ingredients, FAQs (though Product Metafields may be more appropriate for product-specific cases)
How to Fetch a Metaobject from Shopifyâ
Step 1: Copy the Componentâ
- Copy the Metaobject component from Smootify
- This component loads a single metaobject from Shopify
Step 2: Customize the Attributesâ
On the Custom Element smootify-metaobject, modify the following Custom Attributes:
Type:
| Name | Value |
|---|---|
data-type | metaobject_type_to_load |
For example, if you created a Metaobject definition with type "testimonials", use:
| Name | Value |
|---|---|
data-type | testimonials |
Handle:
You must modify the attribute:
| Name | Value |
|---|---|
data-handle | metaobject_handle |
With the handle of the specific metaobject you want to load.
Note: You can naturally bind the value to a CMS value if needed.
Step 3: Add the Metaobject Attributesâ
On any Webflow static element you added inside the smootify-metaobject custom element, you can add the attribute:
| Name | Value |
|---|---|
metaobject | metaobject_field_key |
This binds that static element to the corresponding field defined for the metaobject.
Supported Fieldsâ
The supported fields are identical to those listed in the Metaobject Listing section above. Refer to that section for the complete list.
Fields Visibilityâ
The fields visibility attributes work the same way as described in the Metaobject Listing section. Refer to that section for details.
Example Use Casesâ
Enhance the Vendor Page:
- Load a single metaobject of type "brand" on the Webflow Vendor template page
- Add different fields controlled directly from Shopify without tampering with the Webflow CMS
Banner:
- Create a CTA section in Webflow with dynamic content loaded directly from Shopify
- Allow the store owner to dynamically change a promo section without going into Webflow
Product-Specific Cases:
- For product-specific metaobjects like Size Charts, List of ingredients, FAQs, etc., consider using Product Metafields instead, which may be more appropriate for those use cases.
Domain Configurationâ
Proper domain configuration is critical for headless stores. Incorrect setup will break checkout functionality.
Configuration Rulesâ
Critical: To use the headless channel, you must set up different domains on Shopify and Webflow. If you attach both domains to Shopify and Webflow, checkout will not work, as the page would be intercepted by Webflow hosting.
Configuration:
- Main domain (e.g.,
www.mysite.com) â Webflow only - Subdomain (e.g.,
store.mysite.com) â Shopify only
Step-by-Step Domain Setupâ
1. Attach Main Domain to Webflowâ
- The main domain like
www.mysite.commust be connected only and exclusively to Webflow - Use
wwwas the default in Webflow since most common domain registrars do not support CNAME flattening, ALIAS, or ANAME records - Webflow documentation: Domain Setup Guide
2. Detach Main Domain from Shopifyâ
- If your main domain (e.g.,
www.mysite.com) was previously attached to Shopify, you must detach it - Otherwise, your checkout will not work since the URL will be intercepted by Webflow server
- Shopify documentation: Managing Domains
3. Attach Subdomain to Shopifyâ
- Even though you can use the default
.myshopify.comURL for checkout, it's better for customer trust to see checkout on a URL that belongs to your domain - Use a subdomain on your Shopify store like
store.mystore.com - Shopify documentation: Adding Domains
Domain Provider Considerationsâ
The exact configuration depends on your domain provider, but ensure:
- Main domain points to Webflow
- Subdomain points to Shopify
- DNS records are correctly configured
- Allow time for DNS propagation (can take up to 48 hours)
Shopify Redirect Themeâ
If you don't want to use the Online Store channel on your Shopify store, install the Smootify Redirect Theme.
Purposeâ
The redirect theme redirects all pages of the Online Store to the Webflow site, except the Cart page. This is useful when you must use an app embed that works only on the Online Store on the cart page (like pickup apps).
Additional Featuresâ
The theme has 2 additional settings that you can customize:
- products_base: Allows correct redirection of product pages according to collection slugs used in Webflow
- collections_base: Allows correct redirection of collection pages according to collection slugs used in Webflow
This eliminates the need for additional 301 redirects.
Setupâ
Step 1: Download the Themeâ
- Download the Smootify Redirect Theme
- The theme is a mix of the official Hydrogen Redirect theme and Dawn theme
Step 2: Install the Themeâ
- Navigate to Online Store â Themes in your Shopify admin
- Upload the theme file you downloaded
Step 3: Configure the Themeâ
- From Online Store â Themes, press Customize
- Navigate to Theme settings â Storefront
- Configure the following options:
| Setting | Value | Example |
|---|---|---|
| storefront_hostname | The domain attached to your Webflow project | www.yourdomain.com (include www to avoid double redirect) |
| products_base | The slug of your Product CMS collection in Webflow | product |
| collections_base | The slug of your Collection CMS collection in Webflow | collection |
Step 4: Publishâ
- Publish the theme
- All traffic from Online Store will now redirect to your headless Webflow site
Integration Best Practicesâ
Pre-Launch Checklistâ
Use this comprehensive checklist before launching your store:
Webflowâ
- Designed all pages
- Optimized assets (images, videos, etc.)
- Configured SEO (meta titles, descriptions, Open Graph)
- Configured cookie banner
- Configured analytics integrations (GA4, GTM, etc.)
- (Optional) Configured Smootify Settings
- Project transferred to the client
- Main domain correctly configured
Shopifyâ
- Store transferred to the client
- Payments and taxes settings configured
- Subdomain connected to Shopify (e.g.,
store.domain.com) - Installed Headless Sales channel
- Generated a Storefront Token (live token, not development)
- (Optional) Configured Customer Accounts
- Removed password protection
Smootifyâ
- Shared site with the customer
- Added the previously generated storefront token into site settings
- Correctly added the live domain into site settings
Development Setup Checklistâ
For initial development:
- Install Smootify app (Shopify or Webflow)
- Install Shopify Headless App on Shopify store
- Create Storefront API connection
- Enable all Storefront API permissions
- Copy development token to Smootify dashboard (for testing)
- Connect Webflow project in Smootify dashboard
- Create required CMS collections in Webflow
- Configure custom code settings
- Test product sync
- Test checkout flow (in development mode)
Performance Optimizationâ
- Cache Duration: Set appropriate cache duration based on how frequently product data changes
- Preload Products: Enable idle-time preloading for better perceived performance
- Image Optimization: Ensure product images are optimized in Shopify
- Lazy Loading: Use Webflow's native lazy loading for product images
Analytics Integrationâ
- Enable Auto Analytics Tracking: Automatically tracks ecommerce events
- Custom Events: Use Smootify APIs to track custom events
- Integration with GTM: Smootify events can be captured by Google Tag Manager
Localizationâ
- Market Selection: Enable browser language-based market selection
- Price Formatting: Format prices based on browser settings for better UX
- Currency Handling: Ensure Shopify markets are configured correctly
Variant Managementâ
- Variant Images: Enable "Show only images of currently selected variant" for better UX
- Variant Selection: Ensure variant selection elements are properly configured in Webflow
Troubleshootingâ
Order Confirmation Emails Not Sendingâ
- Verify Shopify Headless App is installed
- Critical: Ensure you're using a live token (not the development token)
- Check Storefront API permissions are enabled
- Verify public token is correctly configured in Smootify dashboard
- Check Shopify email settings
- Verify the token was generated through the Headless sales channel, not automatically by Smootify
Checkout Not Workingâ
- Verify domain configuration: main domain on Webflow, subdomain on Shopify
- Check that main domain is detached from Shopify
- Verify subdomain is correctly attached to Shopify
- Check DNS propagation (can take up to 48 hours)
- Ensure redirect theme is installed if using Online Store channel
Products Not Syncingâ
- Verify Webflow CMS collections are created with correct slugs
- Check collection slugs match Smootify configuration
- Verify Shopify store connection is active
- Check Smootify dashboard for sync errors
API Not Availableâ
- Ensure you're using the
smootify:loadedevent listener - Check browser console for errors
- Verify Smootify script is loaded on the page
- Use
smootify-loadscript type for external scripts
Custom Code Not Workingâ
- Verify script is wrapped in
smootify:loadedevent listener - Check browser console for JavaScript errors
- Verify configuration options are correct
- Test with customizer-generated script first, then modify
Official Resourcesâ
- Smootify Dashboard: https://dashboard.smootify.io
- Smootify Documentation: https://docs.smootify.io
- Shopify Storefront API: Shopify Storefront API Documentation
Related Toolsâ
- Shopify: Ecommerce backend that powers Smootify
- Webflow: Design platform where Smootify integrates
- Google Tag Manager: For tracking Smootify ecommerce events