How to accurately determine what variant is displayed by default without Liquid

Not sure if this is the best category for this as it’s not strictly metafield-related but here’s the problem:

Creating a product-level metafield with JavaScript to be used as a dynamic source from the theme editor (note that dynamic sources cannot use variant metafields). The use case is to allow users to add data to a page tab or accordion. The display is based on the current variant. If there’s no variant parameter, i.e. when the default URL is accessed, determining what to display can be tricky and I’m curious what people are doing to make this determination.

There’s a few approaches I have considered:

  1. Use the form[action*="/cart/add"] [name="id"]- this is very nice but I think there will be too many edge cases that make this problematic
  2. Require users to add an app extension to their theme that uses selected_or_first_available_variant to set a JS variable that’s referenced by the metafield’s JS
  3. Figure out what will be shown by default server-side using variant sorting + availability (or whatever the selected_or_first_available_variant algorithm is) and generate metafield based on that

Leaning towards 3 as it requires less user setup and does not rely on page structure but still have some concerns about accuracy and keeping the value up-to-date. Having to listen to order and fulfillment webhooks is not fun for server load!

What are others using to determine what variant will be displayed by default?

Hi @sshaw Option 3 is the right call here, but you don’t need to replicate the algorithm yourself — the Storefront API has a field that does it for you.

Product.selectedOrFirstAvailableVariant mirrors the Liquid selected_or_first_available_variant algorithm exactly. Called with no selectedOptions argument, it returns the first available variant and falls back to variants[0] if everything’s sold out:

query GetDefaultVariant($handle: String!) {
  product(handle: $handle) {
    selectedOrFirstAvailableVariant {
      id
      title
      availableForSale
      selectedOptions { name value }
    }
  }
}

Shopify runs the same three-tier logic Liquid uses (untracked inventory → oversell policy → inventory_quantity > 0, position-ordered, fallback to first variant), so you get exact parity without maintaining your own implementation.

On keeping it fresh: You don’t need order or fulfillment webhooks. products/update and inventory_levels/update are sufficient — those fire when variant availability actually changes, which is the only thing that affects which variant is “first available.” Order/fulfillment events are noisier than you need.

Docs: Storefront API selectedOrFirstAvailableVariant | Liquid equivalent

…but you don’t need to replicate the algorithm yourself — the Storefront API has a field that does it for you.

Hurmm yes a Storefront call is probably best. Only downside is we don’t request that permission now so it will not work until a shop logs in again.

You don’t need order or fulfillment webhooks. products/update and inventory_levels/update are sufficient

products/update huh :sweat_smile:

Thanks!