How to Trigger Custom Functions on Shopify Variant Selection Without Override
When building custom functionality that needs to respond to variant changes in Shopify themes, you often need a way to hook into variant selection events without breaking the theme’s existing functionality. Here are three reliable methods that work across different theme architectures:
Method 1: Modern Theme Events (Recommended for newer themes)
Many modern themes like Loft use custom event systems. Check if your theme dispatches variant change events:
jQuery('#shopify-section-product-template').on('theme:variants:changed', function(evt, variantObj){
console.log('Variant changed to: ' + variantObj.sku);
console.log(variantObj);
// Your custom functionality here
myCustomVariantHandler(variantObj);
});
Method 2: Legacy OptionSelectors Override
For themes using the older Shopify.OptionSelectors
, you can extend the global selectCallback
function:
(function(){
var original_selectCallback = window.selectCallback;
window.selectCallback = function(variant, selector) {
// Always call the original function first
original_selectCallback(variant, selector);
// Then add your custom functionality
if (variant) {
myCustomVariantHandler(variant);
}
};
})();
Method 3: History State Tracking (Modern themes with enableHistoryState)
For modern themes that use enableHistoryState: true
with OptionSelectors, you can track URL changes:
document.addEventListener('DOMContentLoaded', function(){
function usePushState(handler){
// Track history state changes without overriding
function track(fn, handler, before) {
return function interceptor() {
if (before) {
handler.apply(this, arguments);
return fn.apply(this, arguments);
} else {
var result = fn.apply(this, arguments);
handler.apply(this, arguments);
return result;
}
};
}
var currentVariantId = null;
function variantHandler() {
var selectedVariantId = window.location.search.replace(/.*variant=(\d+).*/, '$1');
console.log('Checking variant change to: ' + selectedVariantId);
if (!selectedVariantId || selectedVariantId === currentVariantId) return;
currentVariantId = selectedVariantId;
handler(selectedVariantId);
}
// Intercept history methods
window.history.pushState = track(history.pushState, variantHandler);
window.history.replaceState = track(history.replaceState, variantHandler);
window.addEventListener('popstate', variantHandler);
}
// Initialize with your custom handler
usePushState(function(variantId) {
console.log('Variant changed to ID: ' + variantId);
// Your custom functionality here
myCustomVariantHandler(variantId);
});
});
Implementation Tips
- Test your theme first - Check browser console for existing events before implementing
- Non-destructive approach - These methods preserve existing theme functionality
- Fallback strategy - You can combine methods for maximum compatibility
- Custom handler function - Replace
myCustomVariantHandler()
with your actual functionality
Example Custom Handler
function myCustomVariantHandler(variant) {
// Example: Update custom elements, trigger analytics, etc.
console.log('Custom variant handler triggered', variant);
// Your specific functionality here
if (variant && variant.available) {
// Handle available variant
} else {
// Handle unavailable variant
}
}
Has anyone found other reliable methods for variant change detection? What’s worked best in your experience?