2.0 Beta

Smootify 2.0 is in public beta. Your 1.x store keeps working. Move when you want.

What changed

Build the product page

The Shopify product on the template page of your Products collection. Covers title, price, gallery, options, add to cart and stock, and says what Smootify needs and what is up to your design.

v2.0 beta
Open .md
On this page
  1. How it fits together
  2. 1. Connect the page to the product
  3. 2. Title, description and product details
  4. Metafields
  5. 3. Price
  6. 4. Gallery
  7. 5. Options
  8. 6. Add to cart
  9. 7. Stock, sale and other states
  10. 8. Subscriptions
  11. 9. Search engines
  12. Before you publish

A product page in Webflow is the template page of your Products collection. Smootify loads the live product from Shopify into it: price, options, stock, images and the add-to-cart form. This guide goes through the page one part at a time. For each part it says what Smootify needs and what is up to your design.

Note

Before you start, Smootify must be installed on the site and your products synced to the Products collection, with the Shopify ID field filled in.

How it fits together

Everything Smootify fills goes inside one element, smootify-product. It holds one product, and the elements inside it read that product and no other.

What Smootify needs:

  • a smootify-product element with the product’s id;
  • inside it, the add-to-cart form, if the page sells.

What is up to you:

  • the layout, the sections, the order of the parts, the classes and the styles;
  • which parts you use. A page can show a price without a gallery, or options without a quantity field.

The smallest page that sells looks like this in the Navigator:

Example structure of the Navigator
smootify-productCustom Elementdata-id=Shopify ID
HeadingH1Nameproduct=title
smootify-priceCustom Element
Text BlockPrice Formatteddata-prop=price
smootify-add-to-cartCustom Element
Form Block
Form
Form Button“Add to cart”Waiting text “Adding…”
Success Message
Text Block“Added”
Error Message
Text Block“Something went wrong”

A Custom element comes from the Add panel. You set its tag in the element settings, and its attributes under Custom attributes in the same panel.

1. Connect the page to the product

  1. On the template page, add a Custom element with the tag smootify-product. It can wrap the whole page or only the product section.
  2. Give it the custom attribute data-id, and take its value from the Shopify ID field of the collection.

Everything else on this page goes inside that element.

  • Shared links to a variant. A link to the page with ?variant= and a variant id opens that variant. An id that is not one of the product’s variants, such as an old link to a variant you deleted, is ignored: the page opens on the first available variant. As the visitor picks options, the address follows the variant, so the link can be shared. This only works for the page’s own product: a smootify-product inside a Collection list, or inside the cart, ignores it.
  • Products Shopify does not return. A product that is unpublished or not sold in the visitor’s market leaves the product block empty, marked with the class w-dyn-bind-empty. Smootify does not redirect.
  • Other products on the page. The same element also loads related products, best sellers or a collection: see the data-id values in smootify-product.

2. Title, description and product details

Add a custom attribute to a Webflow element to fill it with a value of the product. What you type in the Designer stays as a placeholder until the product loads.

AttributePut it onWhat it shows
product="title"a Heading or textthe title
product="description"a Rich text elementthe description, with its formatting
product="vendor"textthe vendor (brand)
product="type", product="category"textthe product type, the category
product="tags"textone copy per tag
product="collections"text or a linkone copy per collection
variant="sku", variant="barcode", variant="weight"textvalues of the selected variant

Tip

Also bind the element’s text to the CMS field, such as the Name field for the title. The published page then has the text before Smootify loads, which helps search engines and avoids a flash of placeholders. Smootify then writes the live value from Shopify over it.

The full lists are in the Reference: product values and variant values.

Metafields

metafield="material" shows the product metafield custom.material. Add namespace="…" when the namespace is not custom, and use variant-metafield for a variant’s metafield. Every metafield type renders, including lists, ratings, JSON and references to other products: see metafield types.

In Shopify, the metafield definition must have Storefront access turned on. Without it the value never reaches the page.

3. Price

Add a Custom element with the tag smootify-price. Inside it, the elements with data-prop get the amounts, in the store’s money format:

  • data-prop="price": the price of the selected variant;
  • data-prop="compareAtPrice": the compare-at price, hidden when the variant is not on sale;
  • data-prop="total": the price times the quantity in the form.

The price follows the variant, the quantity and the selling plan. Put it anywhere inside smootify-product. Inside a swatch button, it shows the price of that button’s value instead.

Example structure of the Navigator
smootify-priceCustom Elementskeleton=text
Text BlockPrice Formatteddata-prop=price
Text BlockCompare at Price Formatteddata-prop=compareAtPrice
Div Blockcondition=on-sale
Text Span“20%”variant=discount-percentage
Text“off”

Attributes on smootify-price change what it shows:

  • no-quantity: the total ignores the quantity;
  • data-ignore="subscription-swatches": the one-time price, whatever selling plan is chosen;
  • data-remove="…": removes that text from the formatted price;
  • data-replace="from|to": replaces one piece of text with another.

variant="discount-percentage" shows 0% on a product that is not on sale. Put it inside an element with condition="on-sale", as above, so the badge only shows during a sale.

condition="not-on-sale" is the opposite: shown while the chosen variant is at full price, for a “regular price” label or a price style without the sale colour.

variant="discounted-amount" shows how much the variant saves, such as “€8.00”. Like the percentage, it comes only from the compare-at price: discount codes and automatic discounts never change it. The cart shows those. It shows €0.00 at full price, so put it inside condition="on-sale" too.

Price per unit. For products sold by weight, volume or length, the European pricing rules ask for the price per unit next to the price. Add variant="unit-price" to a text element: it shows the selected variant’s unit price and its reference unit, such as €1.50/ 100 g. The unit is in a span with the class reference-unit, so you can style it apart. data-format="{{price}} per {{unit}}" writes it your way. The element stays empty when the variant has no unit price.

The unit price comes from Shopify. On the product, in the pricing of each variant, fill in the unit price measurement: the variant’s total amount (such as 500 g) and the base unit to price it by (such as 100 g). Shopify then works out the price per unit. Shopify offers this setting to stores in some countries only.

Where the price format comes from. Smootify writes every amount with the store’s money format: the HTML without currency field of Shopify’s currency formatting (Settings › General, then Change currency formatting). Smootify keeps the format in the visitor’s browser and refreshes it in the background, so after a change, check it in a private window. The useBrowserFormatter option formats prices for each market with the browser’s own rules instead.

A sale that shows in one country and not in another can be Shopify hiding converted compare-at prices from European countries: see Markets.

Add a Div block with product="gallery" and put the parts you need inside it. Every part is optional.

  • gallery="slider" goes on a Webflow Slider. Smootify makes one slide per image, each a copy of the first slide. Put an Image in the first slide, or use the slide’s background. The other slides you design are removed.
  • gallery="thumbnails" goes on the element that repeats once per image, such as a Link block with an Image inside. Design one, and Smootify repeats it. The current one gets the class is-active, and a click moves the slider.
  • gallery="lightbox" goes on a Lightbox link that opens every image. The link keeps what you put in it, such as a zoom icon.
  • gallery="lightboxes" goes on a Lightbox link that repeats once per image, with its picture.
Example structure of the Navigator
Div Blockproduct=galleryinclude-media
Slidergallery=slider
Mask
Slide
ImageSource ImageAlt text Image Alt
Div Block
Link Blockgallery=thumbnails
ImageSource ImageAlt text Image Alt
Lightbox Linkgallery=lightbox
Image

In the image settings, bind the Image of the first slide and of the thumbnail to the Image field, and their Alt text to Image Alt. If your Products collection uses the Image URL field, where the image stays on Shopify, bind the image to that field instead, with the same Image Alt. The page then shows the featured image before Smootify loads, and Smootify replaces it with every image of the product.

Attributes on the product="gallery" element:

  • include-media adds videos, YouTube and Vimeo videos and 3D models. Without it, the gallery shows images only.
  • only-variant-images shows only the images of the variant the visitor picks: only the red t-shirt when they pick Red. How Smootify knows which images are the red ones is just below.
  • variant-images="alt", together with only-variant-images, groups the images by their alt text instead. The tag after the last # names the variant: Oak chair #Oak, # Red / M. An image without a tag shows for every variant. The alt text is public, since screen readers and Google read it, so write it to make sense read aloud.

Which images belong to which variant. In Shopify, each variant can have one image of its own, chosen on the variant’s page. That image is where the variant’s group starts: the group takes it and the images after it, in their Shopify order, up to the next image chosen for another variant. Photos placed before the first of these images belong to no variant, so the gallery never shows them once a variant is picked. Pick a colour and switch between the two ways:

Example: a t-shirt in three colors

1 The product's images in Shopify, in their order

1
—Cotton t-shirt
2
image of RedFront # Red
3
—Back # Red
4
—Fabric # Red
5
image of BlueFront # Blue
6
—Back # Blue
7
image of GreenFront # Green
8
—Back # Green

2 The visitor picks a colour

3 The gallery shows

To show a photo with every colour, such as the photo of the model, group the images by alt text (variant-images="alt"): an image without # in its alt text shows with every variant.

When the variant changes, the slider moves to its image. Clicking an image does not change the variant. More in gallery parts.

5. Options

A picker shows the values of one option, such as Colour or Size, and changes the variant. There are four, each built on a different Webflow element:

variant-swatches

Buttons, one per value

Built with
A Custom element
Inside
One Custom element with the tag button: the template of every value.
variant-dropdown

A Webflow Dropdown

Built with
A Custom element around a Dropdown
Inside
One Dropdown link: the template of every value.
variant-popover

A panel that opens over the page

Built with
A Custom element with a popover inside
Inside
Links or buttons inside the popover element.
variant-selector

The browser's own select

Built with
A Custom element around a Select field
Inside
Only the Select field: Smootify writes its options.

A picker goes anywhere inside smootify-product, inside or outside the add-to-cart form. You can use more than one kind on the same page, such as swatches for Colour and a dropdown for Size.

Design three pickers. A Shopify product has up to three options, such as Colour, Size and Material, and one template page serves every product. So give the page three pickers, one per option: data-option="1", "2" and "3". A picker removes itself when the product does not have that option: a product with one option shows one picker, a product with three shows all three, a product without options shows none.

Which option. Use data-option="1" for the first option, 2 for the second, or data-option-name="Color,Colour" for the first of those names that the product has, written exactly as in Shopify. The name is useful when products name their options differently, or in more than one language. Without either attribute, the picker shows the first option.

Design only the first value. The first button, or the first link, is the template. Smootify copies it for every value and removes the others you designed, so every attribute goes on the first one.

Example structure of the Navigator
smootify-add-to-cartCustom Element
Form Block
Form
Div Blockhas-option=0
Div Block
Text Span“Option”variant=option1-name
Text“:”
Text Span“Value”variant=option1-value
variant-swatchesCustom Elementdata-option=1
buttonCustom Element
Text Spanoption=bg-color
Text Span“Value”option=title
Text Span“+ $0”option=price-difference
Div Blockhas-option=1
Div Block
Text Span“Option”variant=option2-name
Text“:”
Text Span“Value”variant=option2-value
variant-swatchesCustom Elementdata-option=2
buttonCustom Element
Text Span“Value”option=title
Div Blockhas-option=2
Div Block
Text Span“Option”variant=option3-name
Text“:”
Text Span“Value”variant=option3-value
variant-swatchesCustom Elementdata-option=3
buttonCustom Element
Text Span“Value”option=title
Form Button“Add to cart”Waiting text “Adding…”

Each group holds the option’s name (variant="option1-name"), the value picked (variant="option1-value") and the picker. The group’s Div block has has-option, so it goes away together with its picker when the product does not have that option. Here the count starts at 0: has-option="0" is the first option, "1" the second, "2" the third. has-option works inside the add-to-cart form.

Inside the value of swatches, dropdowns and popovers:

  • option="title": the value’s name;
  • option="bg-color" or option="color": the swatch colour, as a background or as the text colour;
  • option="image": the swatch image;
  • option="price-difference": how much more the value costs than the cheapest one, such as ”+ €180”. It is hidden on the cheapest value, and data-format="+ {{price}}" changes the text.

Swatch colours and images come from Shopify: the option’s own swatches, or the option metaobject in the product metafield custom.options. A native select can only hold text. On variant-selector, data-format="{{value}} {{difference}}" on the Select field adds the difference to each option’s text.

The selected value gets the class is-active. A value that cannot be bought gets is-disabled but stays clickable, because a sold-out variant can still be chosen. Style both with combo classes.

Show the option and the chosen value. Inside the picker, selected-option="name" writes the option’s name and selected-option="title" the chosen value, for example in a label or a dropdown toggle that reads “Size: M”. The name comes from the picker’s data-option-name or data-option, so the label never needs to be typed again:

Example structure of the Navigator
variant-swatchesCustom Elementdata-option-name=Size
Div Block
Text Span“Size”selected-option=name
Text“:”
Text Span“M”selected-option=title
buttonCustom Element
Text Span“S”option=title

Anywhere else in smootify-product, use variant="option1-value" (or option2-value, option3-value) for the value and variant="option1-name" for the name, as in the groups above.

Two attributes on smootify-add-to-cart change how pickers behave. allow-unavailable lets the native select pick values that cannot be bought. avoid-option-update keeps the value picked in a dropdown or popover when the variant changes from another picker.

The page’s product loads all its variants, even above 250.

6. Add to cart

Add a Custom element with the tag smootify-add-to-cart and put a Webflow Form Block inside it. The form is required: without one, the element is removed.

Example structure of the Navigator
smootify-add-to-cartCustom Element
Form Block
Form
quantity-inputCustom Element
buttonCustom Elementdata-action=minus
Text“-”
Text FieldName “quantity”
buttonCustom Elementdata-action=plus
Text“+”
buttonCustom Elementtype=submit
Text Block“Add to cart”data-state=default
Text Block“Adding…”data-state=loading
buttonCustom Elementtype=submitname=buy-now
Text“Buy now”
Success Message
Text Block“Added”
Error Message
Text Block“Something went wrong”

The buttons. The add button can be either of the first two kinds. Buy now is optional, a second button next to it:

A Webflow Form Button

For
A button with text only.
Loading
Its Waiting text setting.
data-state

A Custom element with the tag button

For
An icon, two labels, anything inside.
Loading
Two elements inside: data-state="default" and data-state="loading".
name="buy-now"

A second button, for Buy now

For
Skipping the cart.
Built with
A Custom element with the tag button and type="submit". Not a Webflow Button: that is a link.

Quantity. Add a Custom element with the tag quantity-input. Put a Text field named quantity inside it. The minus and plus buttons are optional: they are Custom elements with the tag button and data-action="minus" or data-action="plus". Without a quantity field, the product is added once. The minus button is disabled and gets is-disabled at the lowest quantity, and the plus button at the highest: the stock left, or the maximum of a B2B quantity rule. data-disable-max on quantity-input removes that upper limit.

Extra fields. Any other field in the form, such as a text field, a select or a checkbox, is saved on the cart line. Its field name is the label, and it shows at checkout: use it for an engraving or a gift message. A name that starts with _ is saved but hidden at checkout. A name that starts with ##ignore is not saved. Extra fields never change the price: for options that cost more, use add-ons or the product configurator.

When the variant cannot be bought. If the variant is sold out, or the picked combination does not exist, every submit button in the form is disabled and gets the class is-disabled. Shopify’s errors, such as a quantity above the stock, appear in the form’s Error message. The Success message is never shown: the form stays on screen, ready for the next product.

A button outside the form. A sticky bar with its own Add to cart button can sit anywhere on the page. Give the Form an ID in its settings, such as product-form, and make the button a Custom element with the tag button, the custom attribute type set to submit and form set to that ID. It adds to the cart, shows its loading label and is disabled with the others. The ID must be unique on the page, so use it on the product page, not in a list of cards.

7. Stock, sale and other states

An element with condition="…" inside smootify-product shows only while the product is in that state. The element stays on the page and Smootify shows or hides it. This is separate from Webflow’s conditional visibility. Each card shows a value of condition and the kind of message you would put in that element:

in-stock

The selected variant can be bought.

out-of-stock

The selected variant cannot be bought.

low-stock

5 or fewer left (0 counts too).

low-not-last-stock

2 to 5 left.

last-in-stock

Exactly one left.

many-in-stock

More than 5 left.

in-backorder

Out of stock but still sold.

on-sale

A compare-at price above the price.

disabled

The picked combination does not exist.

is-new

Published less than 30 days ago (data-new-days changes it).

subscription

A selling plan is chosen.

no-subscription

No selling plan is chosen.

Every condition is in product conditions.

  • Variants. condition="is-variable" shows an element when the product has more than one variant, such as the options block, and is-not-variable when it has only one.
  • Subscriptions. condition="subscription" follows the visitor’s choice: it shows while a selling plan is chosen in subscription-swatches, and no-subscription while the one-time purchase is. It does not tell whether the product offers subscriptions.
  • Tags. tagged="gift,new" keeps an element only when the product has every one of those tags. Add any="true" to keep it when the product has at least one. not-tagged does the opposite: see tag conditions.

smootify-product also carries classes for the same states, such as is-available, is-on-sale, low-stock, is-variable and loaded. You can style them as combo classes: see state classes.

When the product is not available. Shopify does not return a product that is not published on the Headless channel, or not sold in the visitor’s market. The page’s smootify-product is then hidden, and the page gets the class product-unavailable. Two conditions work anywhere on the page, outside smootify-product too:

  • condition="product-unavailable" shows an element only in that case, such as a message with a country switcher;
  • condition="product-available" does the opposite: it hides an element in that case.
Example structure of the Navigator
Div Blockcondition=product-unavailable
Text Block“This product is not available in your country.”
country-switcherCustom Element
Dropdown
Dropdown Toggle
Text Block“Country”data-prop=name
Dropdown List
Dropdown Link
Text Block“Country”data-prop=name

When the visitor picks a country where the product is sold, the class goes away, the message hides and the product shows. Only the page’s own product counts: cards in Collection lists, cart lines and products inside other products are hidden as before, and do not turn the condition on.

While it loads. skeleton="text", "button", "block" or "image" shows a placeholder shimmer on an element until Smootify fills it, and skeleton="hide" hides it until then. Only elements that have the attribute shimmer. See loading.

8. Subscriptions

To sell by subscription, the store needs a Shopify subscription app that creates the selling plans. Smootify shows and sells them.

Put a Custom element with the tag subscription-swatches inside the form, with a Webflow Tabs element in it:

  • the first tab is the one-time purchase, and is removed when the product can only be bought by subscription;
  • the second tab is the template for each selling plan group. In its pane, a Radio button is the template for each plan;
  • subscription-group="name" shows the group’s name in the tab. A smootify-price inside a plan’s Radio button shows that plan’s price.
Example structure of the Navigator
subscription-swatchesCustom Element
Tabs
Tabs Menu
Tab Link
Text Block“One-time purchase”
Tab Link
Text Block“Subscribe”subscription-group=name
Tabs Content
Tab Pane
Text Block“Pay once”
Tab Pane
Field Label
Radio Button
Text Span“Plan”class=w-form-label
smootify-priceCustom Element
Text Span“$0.00”data-prop=price

On a product without selling plans, subscription-swatches is removed. The attributes that preselect a plan are in subscription-swatches.

9. Search engines

Smootify adds the product’s structured data (JSON-LD) to the page, so Google can show the product as a rich result. It includes:

  • the name, description, images and brand;
  • for each variant, the price in the visitor’s currency and whether it is available;
  • the rating, when the page shows the reviews.rating and reviews.rating_count metafields (Google wants a marked-up rating to be visible on the page).

There is nothing to add. If the page already has its own Product structured data, Smootify leaves it alone. To turn it off, set structuredData: false in the Smootify options.

For Google Shopping, the product feed of Shopify’s Google & YouTube app is still the reference.

Before you publish

On your .webflow.io address, press Alt⇧ ShiftD (⌥ Option⇧ ShiftD on a Mac) to turn on Smootify’s debugger. On a phone, open the page with ?smootify-debug at the end of the address. Its button then shows on every page of the site, and its panel lists the elements that are out of place. The debugger explains the rest.

Check these first

  • Nothing loads. data-id is empty or not bound to the Shopify ID field.
  • Attributes on a swatch do nothing. They are on the second button: only the first one is the template.
  • A picker disappears. The product does not have that option, or the picker is inside an element hidden by Webflow’s conditional visibility, which removes it.
  • A metafield stays empty. Its definition in Shopify needs Storefront access.
  • Videos are missing from the gallery. Add include-media to the product="gallery" element.
  • The gallery does not move. gallery="slider" only works on a Webflow Slider.
  • Buy now does nothing. It is a Webflow Button, which is a link. Use a Custom element with the tag button.

    ↑ ↓ to moveEnter to openEsc to close