Shopify Variants

Lets Craft editors pick individual Shopify product variants, not just products. Builds on the synced catalog from craftcms/shopify.

Two things ship in the box:

  • Shopify Variants field: an ordered, optionally capped list of variants.
  • Shopify variant link type: a single variant, for Craft's native Link field.

Requirements

Both the field type and the link type only appear while the Shopify plugin is installed and enabled.

The field

Add a Shopify Variants field, drop it in a field layout, and editors get a search box over the synced catalog with results grouped by product.

SettingDefaultNotes
maxVariantsblankMost variants an editor may select. Blank means no limit. Enforced server-side as well as in the picker.

Search matches product title, variant title, and SKU. Shopify joins a variant's option values into its title ("Black / S"), so searching an option value works too.

Value

Persisted as JSON: [{"productGid": "...", "variantGid": "..."}, ...].

In Twig the field returns a SelectedVariantCollection. Each item is a SelectedVariant:

  • productGid, variantGid: the stored GIDs, always present.
  • product, variant: the resolved Shopify models, or null if that variant is gone from the sync.
  • isResolved(): true only when both resolved.
  • label: product and variant title combined, with Shopify's Default Title placeholder suppressed.
  • image: {url, alt}, or null. Falls back to the product image, since Shopify carries no variant image on single-variant products. Prefer this over variant.image, which is null for those.

A variant can disappear from Shopify after it was picked, so always guard on product and variant:

{% for selection in entry.featuredVariants %}
  {% if selection.isResolved() %}
    {% set product = selection.product %}
    {% set variant = selection.variant %}
    {% set image = selection.image %}
    {% if image %}<img src="{{ image.url }}" alt="{{ image.alt }}">{% endif %}
    <a href="{{ product.url }}?variant={{ variant.shopifyId }}">
      {{ selection.label }} {{ variant.price }}
    </a>
  {% endif %}
{% endfor %}

Stale selections are deliberately kept rather than silently dropped: the picker flags them so an editor can fix the entry.

The link type

Enable Shopify variant on any Link field. The stored value is a compound productGid|variantGid string, and it renders as a storefront deep link: <product url>?variant=<numeric variant id>.

It renders as an empty string when the product has no URL, so give Shopify products a URI format in the Shopify plugin's settings if you need the link to resolve.

The search endpoint

The picker fetches a page at a time from shopify-variants/variants/search rather than rendering the whole catalog into the page.

ParamDefaultNotes
search''product title, variant title, SKU
page0zero-indexed, paginated by product
limit20products per page, clamped to 100

Returns {groups, total, hasMore}. Control Panel requests from a logged-in user only; no extra permission, since this is the same catalog data an editor already needs to fill in the field.

Checking an install

php craft shopify-variants/check

Asserts that the catalog searches, paginates, and round-trips: pick an option, resolve it back, and get the same product and variant. Worth running after any craftcms/shopify upgrade. Shopify 8 moved the full GID off Variant::$shopifyId (now numeric) onto Variant::$shopifyGid, and that class of change fails silently: the picker keeps working while every stored selection resolves as missing.

Installation Instructions

To install this plugin, copy the command above to your terminal.

Reviews

This plugin doesn't have any reviews.

Active Installs
0
Version
1.0.0
License
Craft
Compatibility
Craft 5
Last release
August 26, 2026
Activity (30 days)
0
Closed Issues
0
Open Issues
0
Merged PRs
0
Open PRs