The variant:change event in Shopify (and why it does not fire in Spotlight)
You added document.addEventListener('variant:change', ...) to your Shopify Spotlight theme, expected it to fire when a shopper picks a color, and got silence. You are not doing it wrong. The variant:change event is a real convention in a lot of Shopify themes, but Dawn-family themes like Spotlight do not dispatch it. This post explains what the event actually is, which themes fire it, why Spotlight does not, and the one approach that works on any theme.
This is a developer post, so it gets specific with code. If you are here because you just want variant images to swap correctly without hand-coding an event listener at all, skip to the end: that is exactly what Rubik Variant Images does, and it exposes its own event you can hook.
In this post
- What the variant:change event is
- Which themes dispatch it
- Why Spotlight and Dawn do not
- A reliable, theme-agnostic hook
- The Rubik swatch event
- Frequently asked questions
- Related reading
What the variant:change event is
In themes that support it, variant:change is a custom DOM event dispatched when the shopper selects a different variant. You listen for it on the document and read the newly selected variant from the event detail:
document.addEventListener('variant:change', function (event) {
var variant = event.detail.variant;
if (!variant) return;
console.log('Selected variant:', variant.id, variant.title);
// your custom logic: swap a PDF, update a badge, fire analytics
});
It is a clean pattern. When a theme fires it, you get a single, reliable hook for “the shopper just changed the variant,” with the full variant object in event.detail. That is why so much third-party code and so many tutorials assume it exists.
Which themes dispatch it
The variant:change event is a convention several theme vendors adopted, not an official Shopify standard. Themes known to dispatch a document-level variant:change (or a closely related event) include a number of premium themes such as those from RoarTheme (Be Yours), plus Motion and Symmetry. If you are on one of those, the listener above just works.
The catch: because it is a convention and not a platform guarantee, the exact event name and payload differ from theme to theme. Some dispatch variant:change, some use a slightly different name, some put the variant in event.detail.variant and others nest it elsewhere. Always confirm against your specific theme’s JavaScript before relying on it.

Why Spotlight and Dawn do not
Spotlight is one of Shopify’s free Online Store 2.0 themes, built on the same architecture as Dawn. And Dawn-family themes do not broadcast a global variant:change DOM event. Instead, they handle variant selection through an internal publish/subscribe system in the theme’s JavaScript, where the variant picker publishes to subscribers inside the theme rather than firing a document-level event that outside code can catch.
That is the entire reason your variant:change listener stays silent on Spotlight. The event you are waiting for is never dispatched, because this theme family talks to itself through a different channel. It is not a bug, and it is not your code. It is an architectural difference between the theme that documented variant:change in a tutorial you read and the Dawn-family theme you are actually on.
A reliable, theme-agnostic hook
When you cannot count on a theme-specific event, drop to the layer every theme shares: the variant picker’s form inputs. A shopper changing a variant always changes a radio input or a select, so listen for change on the variant selector itself:
document
.querySelectorAll('variant-selects, variant-radios, .product-form__input input, .product-form__input select')
.forEach(function (el) {
el.addEventListener('change', function () {
// a variant option changed; recompute the selected variant here
});
});
This is more work than a single tidy event, because you have to map the selected options back to a variant yourself, but it fires on every theme, including Dawn and Spotlight. It is the honest fallback when a theme does not give you a clean event.
“Within the constraints of Shopify’s deliberately incomplete, needlessly complicated, and clunky interface, Rubik is intuitive. It beautifully performs a function a great many sellers need. Customer service is outstanding, interactive, genuinely concerned with helping you, following through, and updating users on changes that affect performance.”
Podrunner-Groovelectric, US, 2024-11-24. Rubik Variant Images on the Shopify App Store
The Rubik swatch event
If the reason you wanted variant:change was to react to a shopper picking a color (swap an image, update a badge, fire analytics), Rubik Variant Images gives you a dedicated event that works the same on every supported theme, Spotlight included. When a shopper clicks a Rubik swatch, the app dispatches:
window.addEventListener('rubik-swatch-clicked', function (event) {
var d = event.detail;
// d.optionName, d.optionValue, d.optionValueId, d.element
console.log('Rubik swatch:', d.optionName, '=', d.optionValue);
});
Four properties, one consistent event, no per-theme guesswork: optionName, optionValue, optionValueId, and the clicked element. You get a reliable variant-change hook without reverse-engineering each theme’s internals, and the app also handles the actual image filtering for you. That is usually the point where hand-coding stops being worth it.
Prefer to see it before wiring anything: the live demo store, the demo video, or the supported themes documentation. For the general merchant setup on this theme, see our Spotlight theme variant images guide.
Frequently asked questions
Why is my variant:change listener not firing in Spotlight?
Because Spotlight is a Dawn-family theme, and Dawn-family themes do not dispatch a global variant:change DOM event. They handle variant selection through an internal publish/subscribe system instead, so a document-level variant:change listener never receives anything. Listen to the variant picker’s change event, or use an app event, instead.
Which Shopify themes support the variant:change event?
It is a convention adopted by several theme vendors, not an official Shopify event. A number of premium themes dispatch it, including some from RoarTheme, Motion, and Symmetry. The exact event name and payload vary by theme, so always confirm against your theme’s JavaScript rather than assuming.
How do I detect a variant change on any theme?
Listen for the change event on the variant picker’s inputs (variant-selects, variant-radios, or the product form’s radios and selects). That fires on every theme because a variant change always changes an input. You then map the selected options back to a variant. It is more code than a single event but fully portable.
Does Rubik Variant Images expose an event I can hook?
Yes. When a shopper clicks a Rubik swatch, the app dispatches a rubik-swatch-clicked event on window with four properties in event.detail: optionName, optionValue, optionValueId, and the clicked element. It fires consistently across all supported themes, so you get a reliable variant-change hook without theme-specific code.
Do I need to code this at all?
Only if you have custom logic to run on variant change. If your goal is simply to show the correct images when a shopper selects a variant, Rubik Variant Images handles the filtering natively on 350+ themes with no code, and exposes its event only for developers who want to extend it.
Related reading
- Spotlight theme variant images guide
- Rubik Variant Images FAQ
- How to add color swatches on Shopify
- Select a variant by clicking an image
- Shopify combined listings explained
The lesson under all of this: Shopify never standardized a variant-change event, so every theme reinvented it, and Dawn-family themes like Spotlight opted out of the DOM-event approach entirely. Listen to the inputs for a portable hook, or use an app’s own event if you want one clean line instead of a theme-archaeology project.




