2.0 Beta

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

What changed

Show metaobjects

Load metaobjects from Shopify into an Astro site, at build time with a loader or in the browser with Smootify elements. Covers a paged list of one type, the metaobjects of a product metafield, a single entry, and how their fields show.

v2.0 beta
Open .md
On this page
  1. 1. A list of one type
  2. 2. The metaobjects of a product or a customer
  3. The logged-in customer’s entries
  4. 3. One entry
  5. 4. Show the fields
  6. 5. Product cards from a field
  7. Before you publish

Metaobjects are structured content you keep in Shopify, such as testimonials, size charts, FAQs or store details. Smootify shows them on the site: you write one entry, and Smootify fills it and repeats it. Your client can then edit that content in Shopify, next to the products. This page covers a list of entries, the entries of a product, and a single entry.

To render the entries on the server instead, with the build loader smootifyMetaobjects({ type }), see Content. This page is about Smootify’s elements, which read the entries in the browser and always show the current ones.

Note

In Shopify, under Settings > Custom data > Metaobjects, the definition must have Storefronts access turned on. Without it, the entries never reach the site. With Active-draft status also turned on, entries saved as draft stay off the site until you make them active.

Three ways to load them, each a section below:

WayElement and what it needsPages
A list of one typesmootify-metaobjects with data-type, the definition’s typeyes, data-limit entries at a time
The metaobjects of a productsmootify-metaobjects with data-type set to metafield. and the metafield’s namespace and key, and data-product-idyes, like a list of one type
One entrysmootify-metaobject on its own, with data-type and data-handle (or data-id)no; when the entry does not exist, the element is removed

Two names you need from Shopify. The type of the definition, such as testimonial, shown on the definition’s page. And the key of each field, such as author_name for a field called “Author name”. Here they are on a testimonial definition, with its entries and what the page shows:

In the Shopify admin and on the page:

  1. Settings > Custom data > Metaobjects: the definition Testimonial, type testimonial, with the fields Author name (key author_name, single line text), Quote (key quote, multi-line text) and Photo (key photo, file). Storefronts access on; Active-draft status on.
  2. Content > Metaobjects > Testimonial: the entries. Anna R. and Marco B. are active; Lena K. is a draft, so it stays off the site until it is made active.
  3. In the markup, inside smootify-metaobject: metaobject="author_name" shows Anna R., metaobject="quote" her quote, metaobject="photo" her photo. The attribute takes the key, not the field’s name.

1. A list of one type

Write the element smootify-metaobjects with the attribute data-type set to the type. Inside it, write the element smootify-metaobject: the template of one entry.

<smootify-metaobjects data-type="testimonial" data-limit="6">
  <div>
    <smootify-metaobject>
      <div metaobject="author_name">Name</div>
      <div metaobject="quote">Quote</div>
    </smootify-metaobject>
  </div>
  <empty-state>No testimonials yet</empty-state>
  <button data-action="load-more">Load more</button>
</smootify-metaobjects>
  • The template. Smootify copies the first smootify-metaobject once per entry, and removes the others you wrote. The copies go next to it, so put it in a div you style as a grid or a list.
  • data-limit sets how many entries load at a time, 10 by default.
  • Pages. A button with data-action="next" or data-action="prev" shows the next or the previous page in place of the current one. data-action="load-more" adds the next entries under the ones shown. Use next and previous, or load more, not both. Each button is hidden when there is no page to go to.
  • Nothing to show. The element empty-state shows while the list is empty.

While it works, smootify-metaobjects has the classes is-loaded, is-empty, has-next and has-prev, which you can style in the component’s CSS. See metaobject list attributes.

The example project has this list as the component content/MetaobjectList.astro: see Write components.

2. The metaobjects of a product or a customer

A product metafield that is a list of metaobjects, such as custom.features, can feed the same list. On the product page:

  • set data-type to metafield. followed by the metafield’s namespace and key, such as metafield.custom.features;
  • add data-product-id with the product’s shopifyId.
<smootify-metaobjects data-type="metafield.custom.features" data-product-id={product.shopifyId}>
  <smootify-metaobject><div metaobject="title">Feature</div></smootify-metaobject>
</smootify-metaobjects>

It pages like a list of one type. For a few entries without pages, a metafield attribute on the product page also repeats them: see Metafields on the page.

The logged-in customer’s entries

The entries a customer created with a metaobject creator that has customer-field, such as their gift lists, are in the customer’s metafield smootify.<type>. On an account page, set data-type to metafield.smootify.gift_list and data-parent-id to customer:

<smootify-metaobjects data-type="metafield.smootify.gift_list" data-parent-id="customer" data-limit="12">
  <div class="grid">
    <smootify-metaobject>
      <div metaobject="occasion">Occasion</div>
      <h3 metaobject="title">List title</h3>
      <div metaobject="date">Date</div>
      <a href="/gift-list" data-handle-param="l">Open the list</a>
    </smootify-metaobject>
  </div>
  <empty-state>No gift lists yet</empty-state>
</smootify-metaobjects>
  • The newest entry comes first. An entry deleted in Shopify is skipped.
  • A visitor who is not logged in, or a customer with no entry yet, sees the empty-state, and the list has is-empty.
  • A link with data-handle-param inside the card links to that entry’s page, such as /gift-list?l=<handle>.

3. One entry

Use a smootify-metaobject on its own, outside any list, with the attributes data-type and data-handle, the handle of the entry in Shopify. data-handle can be an expression, for example to show a different size chart on each product page. data-id, with the entry’s id, works instead of the handle.

<smootify-metaobject data-type="size_chart" data-handle="shirts">
  <h2 metaobject="title">Size chart</h2>
  <img metaobject="image">
  <div if-metaobject="notes"><div metaobject="notes">Notes</div></div>
</smootify-metaobject>

When the entry does not exist, the element is removed.

The entry named in the page link. With data-handle-param, the handle comes from the page’s URL: data-handle-param="l" on the page /list?l=giulia-birthday shows the entry giulia-birthday. One page then shows every entry a form creates, such as a shared gift list, a saved configuration or a quote, with no page for each. data-id and data-handle stay the fallback when the link has no parameter; without one, or with a handle that does not exist, the element is removed.

<div class="list">
  <smootify-metaobject data-type="gift_list" data-handle-param="l">
    <h1 metaobject="title">Gift list</h1>
    <div metaobject="message">Message</div>
  </smootify-metaobject>
  <div class="not-found">This list does not exist.</div>
</div>

To show a message when the entry is not found, style it hidden and show it once the element is gone, with a rule in the component’s <style> such as .list:not(:has(smootify-metaobject)) .not-found { display: block; }. Anyone with the link can read the entry, so keep emails and addresses out of it. Create the metaobject definition without a display name field: Shopify then gives every entry a random handle, and nobody can guess the link of another one.

4. Show the fields

Inside a smootify-metaobject, metaobject="key" shows that field. Every field type renders, as metafields do: text, rich text, numbers, colours, dates, images and other files, links, lists, and references to products or to other metaobjects. A field without a value hides its element.

  • Images take the size attributes max-width, max-height, crop and pad-color: see image size.
  • Modifiers work as on metafields: data-attr, data-digits, property, separator, and data-path for a JSON field. See Metafields on the page.
  • Conditions. if-metaobject="key" shows an element only when the field has a value, and unless-metaobject="key" only when it has none. Add data-check-value to compare with a value. See metaobject conditions.
  • Loading. Elements with skeleton shimmer until the entry is filled.
  • Languages. Entries come in the page’s language and the visitor’s market: an entry translated in Shopify, for example with Translate & Adapt, shows translated. See Markets, currencies and languages.

How each type renders is in metafield types. The attributes are in metaobject attributes.

5. Product cards from a field

metaobject="key" on a product reference field shows the product’s title, image and link. For full product cards, with price, options, add to cart and wishlist, put a smootify-product with data-id="metaobject.<key>" inside the smootify-metaobject, where <key> is a product reference field or a list of product references of the entry. Design it as one card: Smootify repeats it once per product, in the field’s order.

<smootify-metaobject data-type="gift_list" data-handle-param="l">
  <h2 metaobject="title">List title</h2>
  <div class="grid">
    <smootify-product data-id="metaobject.products">
      <div product="title">Product title</div>
      <div product="price">$0.00</div>
      <smootify-add-to-cart>…</smootify-add-to-cart>
    </smootify-product>
  </div>
</smootify-metaobject>
  • Where it works. Inside a smootify-metaobject: on its own, opened from the page link with data-handle-param, or in each card of a smootify-metaobjects list, each entry with its own products. Outside one, Smootify removes the card.
  • An empty field removes the card. A product the visitor’s market does not sell hides, as in any product list.
  • A class to style. html and body get has-metaobject-<key> when the field has products.
  • In a slider, the card fills the slider like the other product sources.

How many are wanted and how many are taken. When the entry keeps a quantity for each product in a JSON field, such as the quantities of a gift list made with quantities, add to the card data-requested with that field’s key. data-fulfilled names a second JSON field with what is already taken, such as gifted, which the Shopify Flow Gift list: count the gifts fills when an order is paid. Inside the card:

  • metaobject-quantity="requested", metaobject-quantity="fulfilled" and metaobject-quantity="left" show the numbers, for “2 of 6 gifted” or “4 left”;
  • the card gets is-partially-fulfilled while some are taken, then is-fulfilled when none is left, and its add to cart is disabled;
  • the card’s quantity cannot go above what is left;
  • a sold-out product still shows as sold out.
<smootify-product data-id="metaobject.products" data-requested="quantities" data-fulfilled="gifted">
  <div product="title">Product title</div>
  <div><span metaobject-quantity="fulfilled">0</span> of <span metaobject-quantity="requested">1</span> gifted</div>
  <button type="button" data-is="direct-add-to-cart">Add to cart</button>
</smootify-product>

Before you publish

Check these first

  • The list disappears. It has no data-type or no smootify-metaobject inside, or, for a product list, no data-product-id.
  • The list stays empty. The definition does not have Storefronts access, or data-type is not the definition’s type.
  • A field stays empty. metaobject has the field’s name instead of its key: “Author name” is author_name.
  • Some entries are missing. They are saved as draft in Shopify. Make them active.
  • A single entry disappears. Its handle or its type is wrong, so Shopify finds no entry.

    ↑ ↓ to moveEnter to openEsc to close