How to Update the Main Product Price

Please note this document is included as a courtesy to aide developers in customizations related to Product Customizer, so you should be familiar with HTML / liquid to implement changes listed below.

This walks you through a generic method to update the main product price; it relies on the theme handling variant pricing updates in a standard way. If your theme does not handle variant pricing the way most Shopify themes do, you may have to adjust the following approach.

1

Locate the line that looks like:

new Shopify.OptionSelectors('product-select', { product: {{ product | json }}, onVariantSelected: selectCallback });
	

This is typically found in the templates/product.liquid template, the product form snippet (if used), or layout/theme.liquid. Note the value passed to onVariantSelected, e.g. selectCallback, this is the name of the callback function that updates the variant price, and which we'll be using in step 3.

2

Locate the definition of the callback function, often this will be right in product.liquid, just above the new Shopify.OptionSelectors( ... ) but it could be in another template, snippet, or even javascript asset. Once you've found the function, note the CSS rule(s) used to select the product price element, which will be used in step 5.

Often this looks something like:

selectCallback = function(variant, selector) {
  var $product = $('#product-' + selector.product.id);
  ...
  $('.product-price', $product).html(Shopify.formatMoney(variant.price));
  ...
}
	

If this isn't used (sometimes the entire selectCallback body is delegated to the timber framework), or the rule doesn't match the price element on the simple product template (some themes will use a different markup or CSS id/class for variable vs. simple product price element) view the source from a simple (non-variable) product and determine the best CSS rule to match the product price element.

3

Add the following JavaScript just before the new Shopify.OptionSelectors( ... ) line:

  window.selectCallbackOriginal = window.selectCallbackOriginal || selectCallback;
  selectCallback = function(variant, selector) {
    if (variant && typeof(shopifyOptionSelectors) !== 'undefined' && typeof(shopstorm) !== 'undefined' && typeof(shopstorm.apps) !== 'undefined' && typeof(shopstorm.apps.productCustomizer) !== 'undefined' && typeof(shopstorm.apps.productCustomizer.sumOptionsCost) !== 'undefined') {
      variant = jQuery.extend({}, variant);
      var productId = '{{ product.id }}';
      if (!productId && typeof(selector) !== 'undefined' && typeof(selector.product) !== 'undefined' && typeof(selector.product.id) !== 'undefined') {
          productId = selector.product.id;
      }
      if (productId) {
          variant.price += shopstorm.apps.productCustomizer.sumOptionsCost(productId);
      }
    }
    window.selectCallbackOriginal(variant, selector);
  };
	

Note: make sure you use the function name from Step 1. on on the right-hand side of the assignment window.selectCallbackOriginal = window.selectCallbackOriginal || selectCallback;

4

Modify the new Shopify.OptionSelectors( ... ) itself to assign a variable named window.shopifyOptionSelectors like so:

window.shopifyOptionSelectors = window.shopifyOptionSelectors || [];
window.shopifyOptionSelectors[{{ product.id }}] = new Shopify.OptionSelectors('product-select', { product: {{ product | json }}, onVariantSelected: selectCallback });
	
5

Add the following JavaScript, making sure that it's available for both simple and variable products (some themes will conditionally exclude the selectCallback and/or new Shopify.OptionSelectors( ... ) code for simple products), and also ensuring that it appears after the code added in step 4:

$('.product-customizer-options[data-product-id="{{ product.id }}"]').on('product-customizer-show-options-cost', function(event, optionsCost) {
  if (typeof(shopifyOptionSelectors) !== 'undefined' && typeof(shopifyOptionSelectors[$(this).data('product-id')]) !== 'undefined') {
    // first param doesn't seem to be used, and second param is necessary to keep the library happy
    shopifyOptionSelectors[$(this).data('product-id')].updateSelectors(0, {});
  } else {
    var $product = $('#product-' + $(this).data('product-id'));
    $('.product-price', $product).html(
      shopstorm.apps.productCustomizer.formatMoney(
        {{ product.price }} + optionsCost,
        shopstorm.shop.moneyFormat
      )
    );
  }
});
if (typeof(shopstorm) !== 'undefined' && typeof(shopstorm.apps) !== 'undefined' && typeof(shopstorm.apps.productCustomizer) !== 'undefined' && typeof(shopstorm.apps.productCustomizer.options) !== 'undefined' && typeof(shopstorm.apps.productCustomizer.options.showOptionsCost) !== 'undefined') {
  shopstorm.apps.productCustomizer.options.showOptionsCost({{ product.id }});
} else {
  $(document).on('product-customizer-script-loaded', function() {
    shopstorm.apps.productCustomizer.options.showOptionsCost({{ product.id }});
  });
}
	

Note how the $product variable is set, and used to update the correct .product-price element, similar to how the theme's selectCallback function works, as determined in step 2.

6

Test to make sure the updates are working for products both with and without variants. It's possible you may need to add a condition such as or product.metafields.product_customizer != empty to the end of something like {% if product.variants.size > 1 or product.options.size > 1 %}.

Still need help? Contact Us Contact Us