Product lists from Shopify
Best sellers, newest products, related and complementary products, a custom query, one collection or the products in a metafield, filled straight from Shopify with one attribute on smootify-product.
On this page
Some lists cannot come from the content collection: best sellers need Shopify’s sales history, and related products are computed by Shopify. For these, a smootify-product fills itself from Shopify. You write one card, give it a data-id value, and Smootify repeats it once per product. There is no loop over entries.
Note
Before you start, Smootify for Astro must be installed (see Install). These lists read Shopify directly, so the products do not need to be in the content collection. For a list that the build can answer, such as one collection, you can also map the entries yourself: the cards are then in the HTML before Smootify loads (see Content).
How it works
- Write an element for the grid, or a slider (see below).
- Inside it, write a
smootify-productand design it as a product card, inside an element with the classsm-dyn-item. - Set its
data-idto one of the values below, andlimitto the number of products.
<div>
<h2>Best sellers</h2>
<div>
<div class="sm-dyn-item">
<smootify-product data-id="best-seller" limit="8">
<a product="url" href="#">Product name</a>
<smootify-price><span data-prop="price">$0.00</span></smootify-price>
</smootify-product>
</div>
</div>
</div>When the products arrive, the card takes the first one, and Smootify places a copy of the card after it for each of the others. In a slider, each product gets its own slide (see below).
How many. Without limit, a list shows 3 products. Related and complementary products are the exception: without limit they show all the products Shopify returns. A metafield list always shows all the products picked in it.
When the list is empty. If Shopify returns no product, the card is removed. The heading you put next to it stays, unless you hide it: see “Hide a section when its list is empty” below.
The lists
Each data-id fills the card from a different place:
The best sellers, over the whole life of the store.
Nothing else to add
The newest products, by their Shopify creation date.
Nothing else to add
Products that can be bought now.
Nothing else to add
Products that match a Shopify search.
Also needsdata-queryoptionaldata-sort
The products of one collection, in its Shopify order.
Also needsdata-collection-handle
Products Shopify finds related to a product.
Also needsdata-parent-id
Products that go with a product.
Also needsdata-parent-id
The products picked in a metafield of a product.
Also needsdata-parent-id
The products picked in a metafield of the customer.
Also needsdata-parent-id=
Best sellers, newest, available
best-seller, created-at and purchasable need nothing else. best-seller uses the store’s sales history, which the loaders do not have, and created-at lists the newest products first.
A custom query
data-id="custom-query" lists the products that match data-query, written in Shopify’s product search syntax:
tag:giftfor a tag;vendor:Acmefor a vendor;product_type:Shoesfor a product type;variants.price:<50for a price range.
data-sort sets the order with one of Shopify’s product sort keys, such as TITLE, PRICE or CREATED_AT. The order runs one way only: PRICE is the lowest price first.
One collection
data-id="specific-collection" with data-collection-handle="summer" lists the products of that collection, in the order set in Shopify. It is useful where the page is not the collection’s own page, such as the home page.
In a list of your collections, set data-collection-handle to the entry’s id (its handle): each collection then shows its own products. A collection entry loaded with withProducts also carries its products, which Astro can render itself: see Content.
Related and complementary products
On the product page, data-id="related" or data-id="complementary" lists products for the product in data-parent-id. Set data-parent-id to the entry’s shopifyId.
---
const p = entry.data;
---
<div condition="has-related">
<h2>You may also like</h2>
<div slider-track>
<div class="sm-dyn-item">
<smootify-product data-id="related" data-parent-id={p.shopifyId} limit="6"><a product="url" href="#">Product name</a></smootify-product>
</div>
</div>
</div>- Shopify computes related products by itself.
- Complementary products are the ones you pick for each product in Shopify’s Search & Discovery app. If none are set there, the list stays empty.
- Without
data-parent-id, the element is removed.
For the same lists in the cart, based on what the visitor added, see Cart upsells.
Products picked in a metafield
data-id="metafields.custom.pairs_with" lists the products of the product metafield custom.pairs_with of the product in data-parent-id. Write the namespace and the key of your own metafield after metafields..
- The metafield must be of type product reference, or a list of product references. Any other type gives no products.
- Its definition in Shopify needs Storefront access.
data-repeat="2"repeats the list twice, which helps a slider that has only a few products.
The merchant then picks the products for each product in Shopify, such as “Complete the look”. To show the referenced products without prices or add to cart, the metafield attribute is lighter: see Metafields on the page.
Alternatives when a variant is sold out
Instead of a dead end, the product page can offer other products while the chosen variant cannot be bought. It takes only attributes on the page’s smootify-product: nothing goes into the content collection.
- In Shopify, create a variant metafield of type List of products, such as
custom.alternatives, with Storefront access. On each variant that needs them, pick its alternatives: a sold-out size can point to similar products. - Inside the page’s
smootify-product, write an element withcondition="out-of-stock". It shows only while the chosen variant cannot be bought. - Inside it, write an element with
if-variant-metafield="alternatives"and put your heading in it. It shows only when the chosen variant has alternatives. - Inside that element, write an
<a>withvariant-metafield="alternatives", holding an<img reference="image">and an element withreference="title". It repeats once per alternative.
---
const p = entry.data;
---
<smootify-product data-id={p.shopifyId}>
<div condition="out-of-stock">
<div if-variant-metafield="alternatives">
<h2>Sold out. You may like these instead</h2>
<a href="#" variant-metafield="alternatives">
<img reference="image">
<div reference="title">Product</div>
</a>
</div>
</div>
</smootify-product>Everything follows the chosen variant: the block shows for a sold-out size that has alternatives, changes with the size, and hides when the visitor picks a size in stock. More about references and if-variant-metafield: Metafields on the page.
These links show the image and the title of each alternative. For cards with a price and an add-to-cart button, use a product metafield with a smootify-product list, as above, inside the same condition="out-of-stock" block: the alternatives are then the same for every variant, and if-metafield="alternatives" on the element around the heading hides it when the product has none.
Products picked for each customer
With data-parent-id="customer", the same data-id="metafields.<namespace>.<key>" lists the products of a metafield of the logged-in customer: a list the merchant curates for each customer, such as their usual order or the catalog of a wholesale buyer.
<smootify-product data-id="metafields.custom.my_products" data-parent-id="customer">
<div product="title">Product name</div>
<smootify-price><span data-prop="price">$0.00</span></smootify-price>
</smootify-product>- The metafield is a customer metafield, of type product reference or a list of product references. Create it in Shopify under Settings › Custom data › Customers, with its Customer accounts access set to Read, then pick the products on each customer.
- Customer accounts must be set up on the site: see Customer accounts.
- For a visitor who is not logged in, or a customer with no products in the metafield, the element is removed.
data-repeatworks as for a product metafield. While the list has products, the page’sbodygets the classhas-customer-followed by the namespace and key, such ashas-customer-custom-my_products.
Lists in a slider
Write the card inside a [slider-track], as in the related products example above. Each product after the first goes into its own slide: Smootify places a copy of the card’s sm-dyn-item for each of them. A card that hides, such as one with hide-if-product-in-cart whose product is in the cart, hides its whole slide, so the slider leaves no gap.
No placeholder slides. Astro needs none: see placeholder cards.
The arrows and dots are yours. The slider’s parts are written as in Cards in a slider, and a small <script> in the component keeps them in step with the track. The script disables the arrows at the ends and builds the dots again when the slides change.
Hide a section when its list is empty
While a list has products, the page’s body gets the class has- followed by the list’s value: has-best-seller, has-related, and so on. For a metafield list, the class is has- with the namespace and key, such as has-custom-pairs_with.
For related and complementary products, two conditions do the work: an element with condition="has-related" or condition="has-complementary" shows only while that list has products. Put it on the section around the heading and the list, as in the example above. For the other lists, the body class can be used in CSS: see CSS.
Other lists
- The visitor’s wishlist: see Wishlist.
- Recently viewed products: see Recently viewed.
- Filtered lists the visitor can change: see Filters, sorting and pagination.
Before you publish
Check these first
- Only 3 products show. That is the default. Add
limitwith the number you want. - Related or complementary products disappear.
data-parent-idis missing or empty. Set it to the entry’sshopifyId. - Complementary products never show. No complementary products are set for that product in Shopify’s Search & Discovery app.
- The metafield list is empty. The metafield is not a product reference, or its definition has no Storefront access.
- The customer’s list never shows. The visitor is not logged in, the metafield is not a customer metafield, or its Customer accounts access is off.
- The heading stays when the list is empty. Put
condition="has-related"orcondition="has-complementary"on the section, or use thebodyclass for the other lists.