Subscription widget local installation

Learn how to speed up the subscription widget load time on your shop

Each theme is a bit different and some themes require some customization to make the subscription widget (aka subscription plan selector) work as expected. Local installation will help make sure the plan selector works and loads immediately. It's also a good way to make your own unique customizations.


Installing the plan selector locally requires some snippets which the Awtomic team will provide. Just reach out to [email protected] and ask for the files required to install the plan selector locally in your theme.


Installation

  1. Add the provided awtomic-imports.liquid file to the snippets folder in your theme
  2. Add the provided awtomic-plan-selector.liquid file to the snippets folder in your theme
  3. Render awtomic-imports just before the close of your body tag in theme.liquid

    {% comment %} Awtomic Subscriptions {% endcomment %}
    {% capture awtomic-imports %}{% render 'awtomic-imports' %}{% endcapture %}
    {% unless awtomic-imports contains "Liquid error" %}
      {{ awtomic-imports }}
    {% endunless %}
    {% comment %} End Awtomic Subscriptions {% endcomment %}
    
    Notice that we've wrapped the import in a check to be sure that the file exists. This will ensure that an error message isn't rendered in your theme if you accidentally delete the awtomic-imports.liquid file from your theme.
  4. Render awtomic-plan-selector in any product form in which you want the subscription plans selector to appear. It should be inside the form where the hidden input with name=”id” (ie the hidden selected variant id input) exists and is updated.

    {% comment %} Awtomic Subscriptions {% endcomment %}
    {% capture awtomic_plan_selector %}{% render 'awtomic-plan-selector', product: product %}{% endcapture %}
    {% unless awtomic_plan_selector contains "Liquid error" %}
    {{ awtomic_plan_selector }}
    {% endunless %}
    {% comment %} End Awtomic Subscriptions {% endcomment %}
    

Optional: Translations Files

To update strings in the Customer Portal, Build-a-box UI and Subscription Widget or add translations for various languages you can follow these steps:

  1. Add the awtomic-translations.liquid file to the snippets folder
  2. Add the provided locale file json addition to the locales json files under the field awtomatic at the root of the locale json you're updating
  3. Render the awtomic-translations just before the close of the head tag in theme.liquid

    {% comment %} Awtomic Subscriptions {% endcomment %}
    {% capture awtomic-translations %}{% render 'awtomic-translations' %}{% endcapture %}
    {% unless awtomic-translations contains "Liquid error" %}
      {{ awtomic-translations }}
    {% endunless %}
    {% comment %} End Awtomic Subscriptions {% endcomment %}
    

🚧

Future theme upgrades often require that you repeat local installation

Themes making major updates often require that you re-add any customizations that you've made in the past. Whenever you upgrade your theme make sure to check that your subscription widget is still loading as expected


Troubleshooting & FAQs:

  • Sometimes when themes have custom variant selectors you'll have to use the formDomChangeElementsSel setting. To update this setting you can add the key formDomChangeElementsSel just above hideIfUnavailable in the settings object in the awtomic-imports.liquid file and the value should be a CSS selector for elements that you want the plan selector to listen for clicks on. (ex "label.my-custom-variant-button-class")
  • If the price labels aren't updating and you've tried the formDomChangeElementsSel troubleshooting tip above then you might need to tell the plan selector the exact element where the price label is being rendered. To update this setting you can add the key priceContainerSel just above hideIfUnavailable in the settings object in the awtomic-imports.liquid file and the value should be a CSS selector for element that contains the price label. (ex "div.my-custom-price-label-class")
  • Once you've done a local install, the control over whether or not to default to subscriptions is going to be set by the settings object locally instead of by the setting you've selected in the Awtomic app. To update it, update the defaultSubscription value in the object at the top of the awtomic-imports.liquid file




Files


🚧

Reach out to support for the latest files required for local installation

These files are often updated or added to. To be sure you have the latest files, we ask that you contact [email protected] and ask for the files required to install the plan selector locally in your theme.

For immediate need - you can find a version of the files at the end of this article


awtomic-imports.liquid

<script>
  
    (function () {
      window.bundleapp = window.bundleapp || {};
      window.bundleapp.settings = Object.assign(
        {},
        window.bundleapp.settings || {},
        // All configs that where here have been moved to other places
        // the moneyFormat is now fetched below via ajax
        // other settings are set to the global namespace on the script tag handler
        // So this code here is only a reminder that the attribute exists
  
        /**
        * Theme specific settings:
        * This is a quick and dirty way to get some theme specific settings into the app.
        *
        * priceContainerSel Array<String> selector string for the price container
        * comparePriceContainerSel Array<String> selector string for compare at price container
        * priceBadgeContainer Array<String> selector string for the price Badge container
        * hideIfUnavailable Boolean hides selling plans if variant is unavailable/out of stock
        * containerClass String Adds a class to the container where the widget renders
        * renderInsideSel String Selector to render the widget inside
        * renderAfterSel String Selector to render the widget after
        * renderBeforeSel String Selector to render the widget before
        * useRadioButtonFrequencySelector Boolean use radio buttons instead of a select
        * addToCartButtonSel Selector string to locale the add to cart button inside form[action='/cart/add']
        * formDomChangeElementsSel String selector for items to listen to and trigger handleFormDomChanged (ex: 'li.variantSwatch' or 'li.variantSwatch, button.variantItem')
        *   - use this when the items to select variant are not input fields and as such would not be listened to by our script naturally
        * */
        {
          hideIfUnavailable: false,
          proxy: '/tools/bundle-subscriptions',
          appPublic: true,
          moneyFormat: '$\{\{amount\}\}',
          shopStyleSettings: {},
          defaultSubscription: true,
        },
      );
  
      window.bundleapp.setThemeConfigs = (obj) => {
        window.bundleapp.settings = Object.assign(
          {},
          window.bundleapp.settings,
          obj,
        );
      };
  
      var showPreviewModeControl = function () {
        const previewModeControlHtml = `
          <div id="awt-preview-mode-control">
            <div class="awt-logo">
              <div class="awt-logo--image"></div>
              <span>Preview</span>
              <a href="https://help.awtomatic.app/en/articles/5593674-previewing-and-testing-your-subscriptions" target="_blank"><div class="awt-logo--info-icon"></div></a>
            </div>
            <div>
              <!-- <button id="awt-preview-mode-control__hide">Hide</button> -->
              <button id="awt-preview-mode-control__close">Close</button>
            </div>
          </div>
        `;
        const $previewModelEl = document.createElement('div');
        $previewModelEl.innerHTML = previewModeControlHtml;
        document.querySelector('body').appendChild($previewModelEl);
  
        // not removing this yet bc its set to be used in a v2 version of the preview mode controls
        const hidePreviewControl = function () {
          document
            .querySelector('#awt-preview-mode-control')
            .classList.add('hidden');
        };
        const closePreviewMode = function () {
          window.localStorage.removeItem(PREVIEW_MODE_STORAGE_KEY);
          insertUrlParam('awt-preview');
          window.location.reload();
        };
        // document
        //   .querySelector('#awt-preview-mode-control__hide')
        //   .addEventListener('click', hidePreviewControl);
        document
          .querySelector('#awt-preview-mode-control__close')
          .addEventListener('click', closePreviewMode);
      };
  
      var getShopInfo = function () {
        const moneyFormat =
          window.moneyFormat ||
          (window.theme && window.theme.moneyFormat) ||
          (window.theme &&
            window.theme.strings &&
            window.theme.strings.moneyFormat) ||
          (window.theme &&
            window.theme.settings &&
            window.theme.settings.moneyFormat) ||
          (window.bundleapp && window.bundleapp.settings && window.bundleapp.settings.moneyFormat);
        if (moneyFormat) {
          window.bundleapp.settings = Object.assign({}, window.bundleapp.settings, {
            moneyFormat: moneyFormat,
          });
          return Promise.resolve();
        }
  
        return fetch(window.bundleapp.settings.proxy + '/shop-info')
          .then(function (res) {
            return res.json();
          })
          .then(function (data) {
            window.bundleapp.settings = Object.assign(
              {},
              window.bundleapp.settings,
              data,
            );
          });
      };
  
      var setCssVars = function (styleSettings) {
        if (styleSettings) {
          // update CSS vars
          var root = document.querySelector(':root');
          for (var styleSettingsKey in STYLE_VAR_MAP) {
            styleSettings[styleSettingsKey] &&
              root.style.setProperty(
                STYLE_VAR_MAP[styleSettingsKey].cssVar,
                styleSettings[styleSettingsKey],
              );
          }
        }
      };
  
      var insertUrlParam = function (key, value) {
        if (history.replaceState) {
          let searchParams = new URLSearchParams(window.location.search);
          if (value) {
            searchParams.set(key, value);
          } else {
            searchParams.delete(key);
          }
          let newurl =
            window.location.protocol +
            '//' +
            window.location.host +
            window.location.pathname +
            '?' +
            searchParams.toString();
          window.history.replaceState({ path: newurl }, '', newurl);
        }
      };
  
      var formatMoney = function (cents, format) {
        if (typeof cents == 'string') {
          cents = cents.replace('.', '');
        }
        var value = '';
        var placeholderRegex = /\{\{\s*(\w+)\s*\}\}/;
        var formatString = format || window.bundleapp.settings.moneyFormat;
  
        function defaultOption(opt, def) {
          return typeof opt == 'undefined' ? def : opt;
        }
  
        function formatWithDelimiters(number, precision, thousands, decimal) {
          precision = defaultOption(precision, 2);
          thousands = defaultOption(thousands, ',');
          decimal = defaultOption(decimal, '.');
  
          if (isNaN(number) || number == null) {
            return 0;
          }
  
          number = (number / 100.0).toFixed(precision);
  
          var parts = number.split('.'),
            dollars = parts[0].replace(
              /(\d)(?=(\d\d\d)+(?!\d))/g,
              '$1' + thousands,
            ),
            cents = parts[1] ? decimal + parts[1] : '';
  
          return dollars + cents;
        }
  
        switch (formatString.match(placeholderRegex)[1]) {
          case 'amount':
            value = formatWithDelimiters(cents, 2);
            break;
          case 'amount_no_decimals':
            value = formatWithDelimiters(cents, 0);
            break;
          case 'amount_with_comma_separator':
            value = formatWithDelimiters(cents, 2, '.', ',');
            break;
          case 'amount_no_decimals_with_comma_separator':
            value = formatWithDelimiters(cents, 0, '.', ',');
            break;
        }
  
        return formatString.replace(placeholderRegex, value);
      };
      // FIXME eslint error
      // eslint-disable-next-line no-undef
      debounce = function (func, wait, immediate) {
        var timeout;
        return function () {
          var context = this,
            args = arguments;
          var later = function () {
            timeout = null;
            if (!immediate) func.apply(context, args);
          };
          var callNow = immediate && !timeout;
          clearTimeout(timeout);
          timeout = setTimeout(later, wait);
          if (callNow) func.apply(context, args);
        };
      };
      // Method to get closes matching parent source: https://gomakethings.com/a-native-vanilla-javascript-way-to-get-the-closest-matching-parent-element/
      if (window.Element && !Element.prototype.closest) {
        Element.prototype.closest = function (s) {
          var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i,
            el = this;
          do {
            i = matches.length;
            // FIXME eslint error
            // eslint-disable-next-line no-empty
            while (--i >= 0 && matches.item(i) !== el) {}
          } while (i < 0 && (el = el.parentElement));
          return el;
        };
      }
  
      var priceBadgeContainer = () =>
        [
          'form.product__form--add-to-cart .product__price', // Boundless
          '.product-single__meta .price-container', //Brooklyn
          '.product__price .price__pricing-group', // Debut
          '.product__content .price__pricing-group', // Express
          '.product-single__prices', // Minimal, Simple
          '.product__content-header .product__price', // Narrative
          '.inline-list.product-meta', // Supply
          '.product-single__meta-list', // Venture
        ]
          .concat(window.bundleapp.settings.priceBadgeContainer || [])
          .join(', ');
  
      const priceContainerSel = () =>
        [
          '.price__regular', // debut, express
          '.product-single__price', // brooklin, minimal
          '.product__current-price', // narrative
          '#productPrice-product-template', // supply, venture
          '.product__price--reg', // boundless
        ]
          .concat(window.bundleapp.settings.priceContainerSel || [])
          .join(', ');
  
      const comparePriceContainerSel = () =>
        [
          '.price--on-sale .price__sale', // debut, express
          '.product-single__price--compare-at', // brooklin
          '.product-single__sale-price', // minimal
          '.product__compare-price', //narrative
          '.product-single__price--compare', // simple, venture
          '.product__price .product__price--sale', // boundless
          '.product-meta .sale-tag', // supply
        ]
          .concat(window.bundleapp.settings.comparePriceContainerSel || [])
          .join(', ');
  
      const planSelectorSel = '.bundleapp-plan-selector-plan';
  
      const addToCartButtonSel = () =>
        ['button[type=submit]']
          .concat(window.bundleapp.settings.addToCartButtonSel || [])
          .join(', ');
  
      const PREVIEW_MODE_STORAGE_KEY = 'awtomatic-preview-mode';

      /* Functions for gift form data validation */
      const getField = (fieldId) => document.getElementById(fieldId);
      const getFieldValue = (fieldId) => getField(fieldId).value;
      const isEmpty = (str) => str === '';
      const emailIsValid = (email) =>
        /^[A-Z0-9._%+-]+@([A-Z0-9-]+\.)+[A-Z0-9]+$/i.test(email);
      const isFieldValid = (fieldId) =>
        getField(fieldId).getAttribute('data-invalid') == undefined;
      const toggleAddToCart = (target, isValidForm) => {
        const form = target.closest('form');
        const addToCartBtn = form.querySelector(addToCartButtonSel());
        if (addToCartBtn) {
          if (isValidForm) {
            addToCartBtn.removeAttribute('disabled');
          } else {
            addToCartBtn.setAttribute('disabled', true);
          }
        }
        const customizeBtn = form.querySelector('#awt-customize-box-btn');
        if (customizeBtn) {
          if (isValidForm) {
            customizeBtn.removeAttribute('disabled');
          } else {
            customizeBtn.setAttribute('disabled', true);
          }
        }
      };

      const toggleFieldValid = (field, isInvalid, message) => {
        const msg = field.parentElement.getElementsByClassName('awt-error-msg');
        if (isInvalid) {
          field.classList.add('awt-input-error');
          field.classList.add('awt-error');
    
          field.setAttribute('data-invalid', true);
          if (msg.length === 0) {
            const errorLabel = document.createElement('div');
            errorLabel.classList.add('awt-error-msg');
            errorLabel.innerText = message;
            field.parentElement.insertBefore(
              errorLabel,
              field.parentElement.lastElementChild,
            );
          }
        } else {
          field.classList.remove('awt-input-error');
          field.classList.remove('awt-error');
    
          if (msg.length > 0) {
            msg[0].remove();
          }
          field.removeAttribute('data-invalid');
        }
      };

      const isGiftFormValid = () =>
        isFieldValid('awtGiftInfoFirstName') &&
        isFieldValid('awtGiftInfoLastName') &&
        isFieldValid('awtGiftInfoEmail');

      const validateRequiredField = (event) => {
        const isFieldEmpty = isEmpty(getFieldValue(event.target.id));
        toggleFieldValid(event.target, isFieldEmpty, 'Required');
        toggleAddToCart(event.target, isGiftFormValid());
      };

      const validateEmailField = (event) => {
        const isValidEmail = emailIsValid(getFieldValue(event.target.id));
        toggleFieldValid(event.target, !isValidEmail, 'Invalid email');
        toggleAddToCart(event.target, isGiftFormValid());
      };
  
      /**
      * Awtomatic Selector Widget
      * */
  
      function BundleAppWidget($selector, product) {
        this.product = product;
        this.isGiftSelected = false;
        this.$selector = $selector;
        this.$sellingPlanField = this.$selector.querySelector(
          'input[name=selling_plan]',
        );
        this.$wrapper = this.$selector.closest(
          'div[data-section-type], .shopify-section, body',
        );
        this.$planGroups = this.$selector.querySelectorAll(
          '.bundleapp-plan-selector-group',
        );
        this.$form = this.$selector.closest('form');
        this.$variantSelect = this.$form.querySelector('[name=id]');
        this.$badgePriceEl = this.$wrapper.querySelector(priceBadgeContainer());
        if (!this.$badgePriceEl)
          console.warn('Did not find a badge container element');
        // FIXME eslint error
        // eslint-disable-next-line no-undef
        this.setPlansVisibility = debounce(
          this._baseSetPlansVisibility.bind(this),
          50,
        );
  
        this.init();
        this.setPlansVisibility();
        if (window.bundleapp.settings.onInit) {
          window.bundleapp.settings.onInit.call(this);
        }
        if (window.bundleapp.onInit) {
          console.warn(
            'onInit will be deprecated soon. Please use bundleapp.settings.onInit instead',
          );
          window.bundleapp.onInit.call(this);
        }
      }
  
      Object.assign(BundleAppWidget.prototype, {
        init: function () {
          this.$selector.style.display = 'block';
          this.$planGroups.forEach(
            function (elem) {
              var $planGroupRadio = elem.querySelector(
                "input[name='bundleapp-plan-selector-group']",
              );
              var groupId = $planGroupRadio.value;
              var selectedPlanGroup = this.product.selling_plans_by_id[
                this.product.selected_selling_plan
                  ? this.product.selected_selling_plan.id
                  : null
              ];
              var isSelectedGroup = !!(
                selectedPlanGroup &&
                selectedPlanGroup.selling_plan_group_id === groupId
              );

              this.handleGiftVisibility(isSelectedGroup);

              $planGroupRadio.addEventListener(
                'change',
                this.handlePlanRadioChange.bind(this),
              );
              elem
                .querySelector('select')
                .addEventListener(
                  'change',
                  this.handlePlanOptionsChange.bind(this),
                );
              var $radioButtonsfrequencySelector = elem.querySelectorAll(
                '.bundleapp-plan-selector-radio__input',
              );
              for (
                let index = 0;
                index < $radioButtonsfrequencySelector.length;
                index++
              ) {
                $radioButtonsfrequencySelector[index].addEventListener(
                  'change',
                  this.handlePlanOptionsChange.bind(this),
                );
              }
            }.bind(this),
          );
  
          //Ads an event listener to every element in the form
          const $selectorElements = Array.from(
            this.$selector.querySelectorAll('input, select'),
          );
          Array.from(this.$form.elements).forEach(
            function (el) {
              if (
                !$selectorElements.includes(el) &&
                el.tagName !== 'BUTTON' &&
                el.type !== 'hidden'
              ) {
                el.addEventListener('change', this.handleFormDomChanged.bind(this));
              }
            }.bind(this),
          );
  
          if (window.bundleapp.settings.defaultSubscription) {
            const $oneTimeRadio = this.$selector.querySelector('[data-one-time]');
    
            // Only if one time is available and defaultSubscription enabled we set checked
            // the first selling plan group. If there is no one-time option, we already
            // mark the first selling plan checked
            if ($oneTimeRadio) {
              const $firstSellingPlanGroup = this.$selector.querySelector(
                '[data-one-time] + .bundleapp-plan-selector-group input',
              );
              $firstSellingPlanGroup.dispatchEvent(new Event('change'));
            }
          }
          
          if (window.bundleapp.settings.formDomChangeElementsSel) {
            const $variantEls = document.querySelectorAll(
              window.bundleapp.settings.formDomChangeElementsSel,
            );
            $variantEls.forEach(
              function (el) {
                el.addEventListener('click', this.handleFormDomChanged.bind(this));
              }.bind(this),
            );
          }
        },
  
        getTranslation: function (key, fallback) {
          let translation = this.product?.translations[key];
          if (translation.includes('ranslation missing')) {
            translation = fallback;
          }
          return translation;
        },

        handleGiftVisibility: function (isSelectedGroup) {
            let isGiftable =
              this.product &&
              this.product.gift_selling_plans &&
              this.product.gift_selling_plans.includes(
                this.product.selected_selling_plan &&
                  this.product.selected_selling_plan.id,
              );
            const giftCheckBox = document.querySelector('input[name="awt-is-gift"]');
      
            if (isGiftable && !giftCheckBox && isSelectedGroup) {
              this.isGiftSelected = true;
              let isGiftCheckboxLabel = document.createElement('label');
              isGiftCheckboxLabel.classList.add('awt-checkbox');
              let isGiftCheckbox = document.createElement('input');
              const giftTitle = this.getTranslation(
                'gift_recipient_info_title',
                'Recipient info',
              );
              const giftFirstNameLabel = this.getTranslation(
                'gift_first_name_label',
                'First name',
              );
              const giftFirstNamePlaceholder = this.getTranslation(
                'gift_first_name_placeholder',
                'First name',
              );
              const giftLastNameLabel = this.getTranslation(
                'gift_last_name_label',
                'Last name',
              );
              const giftLastNamePlaceholder = this.getTranslation(
                'gift_last_name_placeholder',
                'Last name',
              );
              const giftEmailLabel = this.getTranslation(
                'gift_email_label',
                'Email address',
              );
              const giftEmailPlaceholder = this.getTranslation(
                'gift_email_placeholder',
                'Email address',
              );
              const giftEmailWarning = this.getTranslation(
                'gift_email_warning',
                'Important: Gift emails will be sent here',
              );
              const giftNoteLabel = this.getTranslation('gift_note_label', 'Note');
              const giftNotePlaceholder = this.getTranslation(
                'gift_note_placeholder',
                'Note',
              );
      
              isGiftCheckbox.addEventListener('change', function (event) {
                const isGiftSelected = event.currentTarget.checked;
                this.isGiftSelected = isGiftSelected;
      
                if (isGiftSelected) {
                  const giftsMarkUp = `<div class="gift">
                  <p class="awt-gift-info-title">${giftTitle}</p>
                      <div class="awt-form-group">
                        <label for="awtGiftInfoFirstName" class="awt-floating-label">
                            <input type="text" id="awtGiftInfoFirstName" class="awt-gift-input" required name="properties[_giftFirstName]" placeholder="${giftFirstNamePlaceholder}" data-invalid>
                            <span class="awt-gift-label">${giftFirstNameLabel}*</span>
                        </label>
                        <label for="awtGiftInfoLastName" class="awt-floating-label">
                            <input type="text" id="awtGiftInfoLastName" class="awt-gift-input" required name="properties[_giftLastName]" placeholder="${giftLastNamePlaceholder}" data-invalid>
                           <span class="awt-gift-label">${giftLastNameLabel}*</span>
                        </label>
                      </div>
                      <div class="awt-gift-input-container">
                        <label for="awtGiftInfoEmail" class="awt-floating-label">
                            <input type="email" id="awtGiftInfoEmail" class="awt-gift-input" required name="properties[_giftEmail]" placeholder="${giftEmailPlaceholder}" data-invalid>
                            <span class="awt-gift-label">${giftEmailLabel}*</span>
                            <div class="awt-floating-label-warning">${giftEmailWarning}</div>
                        </label>
                      </div>
                      <div class="awt-gift-input-container">
                        <label for="awtGiftInfoNote" class="awt-floating-label">
                            <textarea id="awtGiftInfoNote" class="awt-gift-input" placeholder="${giftNotePlaceholder}" name="properties[_giftNote]"></textarea>
                            <span class="awt-gift-label">${giftNoteLabel}</span>
                        </label>
                      </div>
              </div>`;
      
                  let giftInfoContainer = document.createElement('div');
                  giftInfoContainer.setAttribute('name', 'awt-gift-info-container');
                  giftInfoContainer.classList.add('awt-gift-info-container');
      
                  giftInfoContainer.innerHTML = giftsMarkUp;
                  isGiftCheckboxLabel.parentElement.appendChild(giftInfoContainer);
                  getField('awtGiftInfoFirstName').addEventListener(
                    'blur',
                    validateRequiredField,
                  );
                  getField('awtGiftInfoLastName').addEventListener(
                    'blur',
                    validateRequiredField,
                  );
                  getField('awtGiftInfoEmail').addEventListener(
                    'blur',
                    validateEmailField,
                  );
                  toggleAddToCart(getField('awtGiftInfoEmail'), isGiftFormValid());
                } else {
                  const giftInfoContainer = document.querySelector(
                    'div[name="awt-gift-info-container"]',
                  );
                  getField('awtGiftInfoFirstName').removeEventListener(
                    'blur',
                    validateRequiredField,
                  );
                  getField('awtGiftInfoLastName').removeEventListener(
                    'blur',
                    validateRequiredField,
                  );
                  getField('awtGiftInfoEmail').removeEventListener(
                    'blur',
                    validateEmailField,
                  );
                  toggleAddToCart(getField('awtGiftInfoEmail'), true);
                  giftInfoContainer &&
                    giftInfoContainer.parentNode &&
                    giftInfoContainer.parentNode.removeChild(giftInfoContainer);
                }
              });
              isGiftCheckbox.type = 'checkbox';
              isGiftCheckbox.name = 'awt-is-gift';
              isGiftCheckboxLabel.appendChild(isGiftCheckbox);
              isGiftCheckboxLabel.appendChild(
                document.createTextNode(
                  this.getTranslation('gift_checkbox_label', 'This is a gift'),
                ),
              );
              const planDescription = document.querySelector(
                '.bundleapp-plan-selector-description',
              );
              planDescription &&
                planDescription.parentNode.insertBefore(
                  isGiftCheckboxLabel,
                  planDescription.nextSibling,
                );
            }
            if (!isGiftable) {
              if (giftCheckBox) {
                const giftCheckBoxLabel = giftCheckBox.parentNode;
                giftCheckBoxLabel.parentNode.removeChild(giftCheckBoxLabel);
                const giftInfoContainer = document.querySelector(
                  'div[name="awt-gift-info-container"]',
                );
      
                giftInfoContainer &&
                  giftInfoContainer.parentNode &&
                  giftInfoContainer.parentNode.removeChild(giftInfoContainer);
              }
            }
          },
  
        // This is marked as a private function because this is not intended to be used
        // directly. Use the debounced version of it this.setPlansVisibility()
        _baseSetPlansVisibility: function () {
          if (window.bundleapp.settings.hideIfUnavailable) {
            //If variant is not available hide the whole widget
            this.$selector.style.display = this.product.selected_variant.available
              ? 'block'
              : 'none';
          }
  
          var selling_plan_group_ids = this.product.selected_variant.selling_plan_allocations.map(
            function (i) {
              return i.selling_plan_group_id;
            },
          );
          var planId = '';
          const hasPlanWithMultipleDeliveries = this.product.selected_variant.selling_plan_allocations.some(
            (sp) => sp.price !== sp.per_delivery_price,
          );
          // @TODO: translate suffix
          const suffix = hasPlanWithMultipleDeliveries
            ? this.getTranslation('delivery_suffix', '/delivery')
            : '';
          this.$planGroups.forEach(
            function (elem) {
              var bundleAppSettings = window.bundleapp.settings || {};
              var $planGroupRadio = elem.querySelector(
                "input[name='bundleapp-plan-selector-group']",
              );
              var groupId = $planGroupRadio.value;
              elem.style.display =
                selling_plan_group_ids.includes(groupId) || !groupId
                  ? 'block'
                  : 'none';
              var selectedPlanGroup = this.product.selling_plans_by_id[
                this.product.selected_selling_plan
                  ? this.product.selected_selling_plan.id
                  : null
              ];
              var isSelectedGroup = !!(
                selectedPlanGroup &&
                selectedPlanGroup.selling_plan_group_id === groupId
              );

              this.handleGiftVisibility(isSelectedGroup);
  
              var $selectorPlan = elem.querySelector(planSelectorSel);
              $selectorPlan.style.display = isSelectedGroup ? 'block' : 'none';
  
              if (!$planGroupRadio.value && !isSelectedGroup) {
                // If value is falsy a.k.a one-time purchase
                $planGroupRadio.checked = true;
              } else {
                $planGroupRadio.checked = isSelectedGroup;
  
                if (this.$planGroups.length === 1) {
                  elem.classList.add('bundleapp-plan-selector-group--single-group');
                }
  
                // if this is the selected group add the selected class
                if (isSelectedGroup) {
                  elem.classList.add('bundleapp-plan-selector-group--selected');
                  if (bundleAppSettings.useRadioButtonFrequencySelector) {
                    const selectedGroupPlans = elem
                      .querySelector('.bundleapp-plan-selector-radio')
                      .getElementsByTagName('input');
                    const isPlanChecked = Array.from(selectedGroupPlans).some(
                      ({ checked }) => checked,
                    );
                    if (!isPlanChecked) {
                      // if no plan is checked, select the first one
                      selectedGroupPlans[0].checked = true;
                      elem
                        .querySelector('.bundleapp-plan-selector-radio label')
                        .classList.add(
                          'bundleapp-plan-selector-radio__label--selected',
                        );
                    }
                  }
                }
              }
  
              if (bundleAppSettings.useRadioButtonFrequencySelector) {
                let $radioButtonPlanSelector = elem.querySelector(
                  '.bundleapp-plan-selector-radio',
                );
  
                $radioButtonPlanSelector.style.display = isSelectedGroup
                  ? 'block'
                  : 'none';
                let $selectPlanSelector = elem.querySelector(
                  '.bundleapp-plan-selector-select',
                );
                $selectPlanSelector.style.display = 'none';
              } else {
                let $radioButtonPlanSelector = elem.querySelector(
                  '.bundleapp-plan-selector-radio',
                );
                $radioButtonPlanSelector.style.display = 'none';
                let $selectPlanSelector = elem.querySelector(
                  '.bundleapp-plan-selector-select',
                );
                $selectPlanSelector.style.display =
                  isSelectedGroup && $selectPlanSelector.options.length > 1
                    ? 'block'
                    : 'none';
              }
  
              if (isSelectedGroup) {
                const planSel = bundleAppSettings.useRadioButtonFrequencySelector
                  ? `${planSelectorSel} .bundleapp-plan-selector-radio input:checked`
                  : `${planSelectorSel} select`;
  
                planId =
                  elem.querySelector(planSel) && elem.querySelector(planSel).value;
              }
  
              //update pricing label of each group
              const planGroup = this.product.selling_plan_groups.find(
                (p) => p.id === groupId,
              );
              const $priceLabel = elem.querySelector(
                '.bundleapp-plan-selector-group-pricing',
              );
  
              const currentVariant = this.product.variants.find(
                (variant) => variant.id === this.product.selected_variant.id,
              );
  
              if (planGroup && $priceLabel) {
                const values = planGroup.selling_plans.map(function (i) {
                  return parseInt(i.price_adjustments[0]?.value);
                });
  
                const sellingPlansFromCurrentGroup = currentVariant.selling_plan_allocations.filter(
                  (sp) => sp.selling_plan_group_id === planGroup.id,
                );
                if (sellingPlansFromCurrentGroup && values) {
                  const lowestPriceInGroup = Math.min.apply(
                    null,
                    sellingPlansFromCurrentGroup.map((sp) => sp.per_delivery_price),
                  );
                  const isSame = values.every(function (val) {
                    return val === values[0];
                  });
                  const prefix = isSame ? '' : this.getTranslation('from', 'from');
                  $priceLabel.innerHTML = `${prefix} ${formatMoney(
                    lowestPriceInGroup,
                  )}${suffix}`;
                  $priceLabel.dataset.test = `planPriceInSelector-${
                    sellingPlansFromCurrentGroup?.selling_plan_group_id ||
                    sellingPlansFromCurrentGroup[0]?.selling_plan_group_id
                  }`;
                }
              }
  
              if (this.product?.selling_plan_groups?.length === 1) {
                // check to see. IF just one selling plan group, and does not offer discount
                // then we wont display itemized prices.
                const $itemizedPrices = this.$selector.querySelectorAll(
                  '.bundleapp-plan-selector-group-pricing',
                );
  
                const oneTimePurchasePrice = currentVariant?.price;
  
                const pricesInSellingPlans = currentVariant.selling_plan_allocations.map(
                  (sp) => sp.price,
                );
                const allEqual = (arr) => arr.every((val) => val === arr[0]);
  
                if (allEqual([oneTimePurchasePrice, ...pricesInSellingPlans])) {
                  $itemizedPrices.forEach((price) => {
                    price.style.display = 'none';
                  });
                }
              }
            }.bind(this),
          );
  
          //check if theres a visible option selected
          //If not: check first
          if (
            !Array.from(this.$planGroups).filter(
              (el) => el.offsetParent && el.querySelector('input').checked,
            ).length
          ) {
            // get first input that's visible
            const firstVisibleGroup = Array.from(this.$planGroups).filter(
              (el) => el.offsetParent,
            )[0];
            if (firstVisibleGroup) {
              const $firstRadio = firstVisibleGroup.querySelector('input');
              if (!$firstRadio.checked) {
                $firstRadio.checked = true;
                $firstRadio.dispatchEvent(new Event('change'));
                // if we are using radio buttons get the first plan and check it
                if (window.bundleapp.settings.useRadioButtonFrequencySelector) {
                  let $radioButtonPlanSelector = firstVisibleGroup.querySelector(
                    '.bundleapp-plan-selector-radio',
                  );
                  const firstPlan = $radioButtonPlanSelector.querySelector('input');
                  if (!firstPlan.checked) {
                    firstPlan.checked = true;
                    firstPlan.dispatchEvent(new Event('change'));
                  }
                }
              }
            }
          }
  
          //Updates input field
          if (this.$sellingPlanField) {
            this.$sellingPlanField.value = planId ? planId : '';
          }
          //Update url only if we are in the product page
          if (window.location.pathname.includes('/products/')) {
            insertUrlParam('selling_plan', planId);
          }
  
          //Updates one-time purchase price
          const $oneTimePrice = this.$selector.querySelector(
            '[data-one-time].bundleapp-plan-selector-group .bundleapp-plan-selector-group-pricing',
          );
          if ($oneTimePrice) {
            $oneTimePrice.innerHTML = `${formatMoney(
              this.product.selected_variant.price,
            )}${suffix}`;
            // data-test attribute for testing
            $oneTimePrice.dataset.test = 'oneTimePriceInSelector';
          }
  
          // do not update prices if there are no selling plans groups on the product
          if (this.product?.selling_plan_groups?.length) {
            this.updatePrice(planId);
            this.updateBadgePrice(planId);
          }
          this.replaceAddBtnForBundles();
        },
  
        replaceAddBtnForBundles: function () {
          // only replace button on BaB bundle
          if (
            !this.product?.metafields?.isBundle ||
            this.product?.metafields?.type === 'shuffle'
          ) {
            return;
          }
  
          const $btn = this.$form.querySelector(addToCartButtonSel());
  
          // remove "buy it now" button
          const $shopifyPaymentBtn = $btn.parentElement.querySelector(
            '.shopify-payment-button',
          );
          if ($shopifyPaymentBtn) {
            $shopifyPaymentBtn.remove();
          }
  
          let $clonedBtn = this.$form.querySelector('#awt-customize-box-btn');
          if (!$clonedBtn) {
            $clonedBtn = $btn.cloneNode(true);
            $clonedBtn.id = 'awt-customize-box-btn';
            $clonedBtn.type = 'button';
            $clonedBtn.innerText = this.getTranslation(
              'customize_my_box',
              'Customize my box',
            );
            $clonedBtn.classList.remove('btn--secondary-accent');
            $clonedBtn.classList.add('btn--primary-accent');
            $clonedBtn.removeAttribute('@click.prevent');
            $clonedBtn.removeAttribute('x-show:');
            $clonedBtn.removeAttribute(':disabled');
            $clonedBtn.removeAttribute(':class');
            // remove any href in case the theme has been customized and isn't a standard add-to-cart button
            $clonedBtn.removeAttribute('href');
  
            $btn.style.display = 'none';
            $btn.classList.add('awt-hidden-add-to-cart-button');
            $btn.parentNode.insertBefore($clonedBtn, $btn.nextSibling);
          } else {
            // clone the previous clone and replace
            var secondClone = $clonedBtn.cloneNode(true);
            $clonedBtn.parentNode.replaceChild(secondClone, $clonedBtn);
  
            // reference new button so we can add event listener
            $clonedBtn = secondClone;
          }
  
          var handleCustomizeBoxButtonClick = function (event) {
            event.stopPropagation();
  
            let params = new URLSearchParams(window.location.search);
            let search = window.location.search;
            // only use product.selected_variant.id arg if variant is not already in the
            // url params. Otherwise we might be overriding the latest selection
            if (!search.includes('variant') && this.product?.selected_variant?.id) {
              params.append('variant', this.product?.selected_variant?.id);
            }
  
            // only use selectedSellingPlanId arg if variant is not already in the
            // url params. Otherwise we might be overriding the latest selection
            let selectedSellingPlanId = this.product?.selected_selling_plan?.id;
            if (!selectedSellingPlanId) {
              // if selectedSellingPlanId wasn't on the product check for the hidden input
              selectedSellingPlanId = document.querySelector(
                'input[name="selling_plan"]',
              )?.value;
            }
            if (!search.includes('selling_plan') && selectedSellingPlanId) {
              params.append('selling_plan', selectedSellingPlanId);
            }
  
            let priceAdjustments = this.product?.selected_selling_plan
              ?.price_adjustments;
            if (
              priceAdjustments &&
              priceAdjustments[0] &&
              priceAdjustments[0].value
            ) {
              params.append(
                'd',
                `${priceAdjustments[0].value}-${
                  priceAdjustments[0].value_type === 'percentage' ? 'p' : 'q'
                }`,
              );
            }
  
            let url = new URL(
              `${window.location.origin}${window.bundleapp.settings.proxy}/bundle/${this.product.id}`,
            );
            url.search = params.toString();
            let isGiftable = this.product.gift_selling_plans.includes(
              this.product.selected_selling_plan?.id,
            );
            if (isGiftable && this.isGiftSelected) {
              const giftFirstName = document.getElementById('awtGiftInfoFirstName');
              const giftLastName = document.getElementById('awtGiftInfoLastName');
              const giftEmail = document.getElementById('awtGiftInfoEmail');
              const giftNote = document.getElementById('awtGiftInfoNote');
              const giftInformation = {
                firstName: giftFirstName?.value,
                lastName: giftLastName?.value,
                email: giftEmail?.value,
                note: giftNote?.value,
              };
              sessionStorage &&
                sessionStorage.setItem(
                  'awt-gift-information',
                  JSON.stringify(giftInformation),
                );
            }
  
            window.location.href = url.toString();
          };
          $clonedBtn.addEventListener(
            'click',
            handleCustomizeBoxButtonClick.bind(this),
          );
        },
  
        updatePrice: function (planId) {
          var planAllocation = this.product.selected_variant.selling_plan_allocations.find(
            (allo) => allo.selling_plan_id == planId,
          );
  
          // var planOption = this.product.selling_plans_by_id[planId];
          let $comparePriceSpan = this.$wrapper.querySelector(
            '.bundleapp-compareAtPrice',
          );
          const $priceRegular = this.$wrapper.querySelector(priceContainerSel());
          
          const $priceSale = this.$wrapper.querySelector(
            comparePriceContainerSel(),
          );
  
          if (!$priceRegular) console.warn('Did not find a price element');
          if (!$priceSale) console.warn('Did not find a compare price element');
  
          if (!$comparePriceSpan) {
            $comparePriceSpan = document.createElement('span');
            $comparePriceSpan.classList.add('bundleapp-compareAtPrice');
            if ($priceRegular) {
              const priceStyles = window.getComputedStyle($priceRegular);
              Array.from(priceStyles).forEach((key) =>
                $comparePriceSpan.style.setProperty(
                  key,
                  priceStyles.getPropertyValue(key),
                  priceStyles.getPropertyPriority(key),
                ),
              );
              $priceRegular.after($comparePriceSpan);
            }
            $comparePriceSpan.style.textDecoration = 'line-through';
            $comparePriceSpan.style.webkitTextDecorationLine = 'line-through';
            $comparePriceSpan.style.marginLeft = '10px';
  
            // for testing purpose
            if ($comparePriceSpan)
              $comparePriceSpan.dataset.test = 'bundlePriceOnSale';
          }
  
          setTimeout(
            function () {
              // Since the theme wants to change the price we need to wait a bit to make our changes,
              // hence, the timeout
              if (planAllocation) {
                if ($priceRegular) {
                  $priceRegular.innerHTML = `${formatMoney(planAllocation.price)}`;
  
                  if (
                    planAllocation.compare_at_price &&
                    planAllocation.compare_at_price !== planAllocation.price
                  ) {
                    $comparePriceSpan.innerHTML = `${formatMoney(
                      planAllocation.compare_at_price,
                    )}`;
                    $comparePriceSpan.style.display = 'inline';
                  } else if (
                    product.compare_at_price &&
                    product.compare_at_price !== planAllocation.price
                  ) {
                    $comparePriceSpan.innerHTML = `${formatMoney(
                      product.compare_at_price,
                    )}`;
                    $comparePriceSpan.style.display = 'inline';
                  }
                   else {
                    $comparePriceSpan.style.display = 'none';
                  }
                }
              } else {
                if ($priceRegular) {
                  $priceRegular.innerHTML = `${formatMoney(
                    this.product.selected_variant.price,
                  )}`;
                }
                if (this.product.selected_variant.compare_at_price) {
                  $comparePriceSpan.innerHTML = formatMoney(
                    this.product.selected_variant.compare_at_price,
                  );
                  $comparePriceSpan.style.display = 'inline';
                } else {
                  $comparePriceSpan.style.display = 'none';
                }
              }
  
              // make sure theme did not try to display=block
              if ($priceRegular) $priceRegular.style.display = 'inline';
  
              //for testing purposes
              if ($priceRegular) $priceRegular.dataset.test = 'priceRegular';
  
              // hide this because we are not longer using this elements.
              if ($priceSale) $priceSale.style.display = 'none';
              //for testing purposes
              if ($priceSale) $priceSale.dataset.test = 'priceOnSale';
  
              // make sure theme did not tried to decorate text
              if ($priceRegular) $priceRegular.style.textDecoration = 'none';
  
              if (
                this.product?.selected_variant?.compare_at_price ===
                  this.product.selected_variant.price ||
                this.product?.selected_variant?.compare_at_price ===
                  planAllocation?.price ||
                this.product?.selected_variant?.price === planAllocation?.price
              ) {
                if ($comparePriceSpan) $comparePriceSpan.style.display = 'none';
              }
            }.bind(this),
            100,
          );
        },
  
        updateBadgePrice: function (planId) {
          var planAllocation = this.product.selected_variant.selling_plan_allocations.find(
            (allo) => allo.selling_plan_id == planId,
          );
          var planOption = this.product.selling_plans_by_id[planId];
  
          var $priceAdjustment = this.$wrapper.querySelector(
            '.bundleapp-price-adjustment',
          );
  
          if (planAllocation) {
            var value_type = planOption.price_adjustments[0].value_type;
            var value = planOption.price_adjustments[0].value;
  
            var symbol = value_type === 'percentage' ? '%' : '';
            var strValue = value_type === 'percentage' ? value : formatMoney(value);
  
            var discount = value > 0 ? `${strValue}${symbol}` : '';
  
            // find out if this selling plan is part of a selling plan group with multiple selling plans/frequencies
            const planAllocationBrothers = this.product.selected_variant.selling_plan_allocations.reduce(
              (acc, curr) => {
                if (
                  curr.selling_plan_group_id ===
                    planAllocation.selling_plan_group_id &&
                  curr.selling_plan_id !== planAllocation.selling_plan_id
                ) {
                  acc.brothers = acc.brothers + 1;
  
                  if (curr.price !== planAllocation.price) {
                    acc.dynamicSavings = acc.dynamicSavings + 1;
                  }
                }
  
                return acc;
              },
              { brothers: 0, dynamicSavings: 0 },
            );
  
            const subscriptionLabel = `<span data-test="subscriptionLabel">${this.getTranslation(
              'subscription',
              'SUBSCRIPTION',
            )}</span>`;
            const dotSeparatorLabel =
              '<span data-test="dotSeparatorLabel"> · </span>';
            const saveLabel = `<span data-test="saveLabel">${this.getTranslation(
              'save',
              'Save',
            )} ${discount}</span>`;
            const extraDiscountLabel = `<span data-test="extraDiscountLabel">${this.getTranslation(
              'extra',
              'Extra',
            )} ${discount} ${this.getTranslation('off', 'off')}</span>`;
  
            let badgeLabel = subscriptionLabel + dotSeparatorLabel + saveLabel;
  
            if (!discount) {
              badgeLabel = subscriptionLabel;
            }
  
            if (
              this.product.selected_variant.compare_at_price &&
              this.product.selected_variant.price != planAllocation.price
            ) {
              badgeLabel = extraDiscountLabel;
            }
  
            const html = `<span data-test="subscriptionBadge">${badgeLabel}</span>`;
  
            if (this.$badgePriceEl) {
              if ($priceAdjustment) {
                $priceAdjustment.innerHTML = html;
              } else {
                var div = document.createElement('div');
                div.classList.add('bundleapp-price-adjustment');
                div.innerHTML = html;
                this.$badgePriceEl.appendChild(div);
              }
            }
          } else {
            if ($priceAdjustment) {
              $priceAdjustment.remove();
            }
          }
        },
  
        setSupportInformation: function () {
          var $description = this.$selector.querySelector(
            '.bundleapp-plan-selector-description',
          );
  
          if ($description) {
            if (
              this.product.selected_selling_plan &&
              this.product.selected_selling_plan.description
            ) {
              $description.innerHTML = `<span>${this.product.selected_selling_plan.description}</span>`;
            } else {
              $description.innerHTML = '';
            }
          }
        },
  
        handlePlanRadioChange: function (e) {
          var target = e.currentTarget || e.target;
          var $planGroup = target.closest('.bundleapp-plan-selector-group');
  
          // remove selected class from previously selected group
          var $previouslySelected = this.$form.querySelectorAll(
            '.bundleapp-plan-selector-group--selected',
          );
          $previouslySelected.forEach((selectedGroup) =>
            selectedGroup.classList.remove(
              'bundleapp-plan-selector-group--selected',
            ),
          );
  
          // add selected class to newly selected group
          $planGroup.classList.add('bundleapp-plan-selector-group--selected');
  
          var $planSelect = $planGroup.querySelector('select');
          var planId = $planSelect.value;
          this.product.selected_selling_plan = this.product.selling_plans_by_id[
            planId
          ];
  
          this.setPlansVisibility();
          this.setSupportInformation();
        },
  
        handlePlanOptionsChange: function (e) {
          var target = e.currentTarget || e.target;
          var planId = target.value;
  
          if (window.bundleapp.settings.useRadioButtonFrequencySelector) {
            // remove selected class from previously selected plan label
            var $previouslySelectedLabels = document.querySelectorAll(
              '.bundleapp-plan-selector-radio__label--selected',
            );
            $previouslySelectedLabels.forEach((selectedLabel) =>
              selectedLabel.classList.remove(
                'bundleapp-plan-selector-radio__label--selected',
              ),
            );
  
            // add selected class to selected label
            var $label = document.querySelector(
              `.bundleapp-plan-selector-radio__label[for="${planId}"]`,
            );
            if ($label) {
              $label.classList.add(
                'bundleapp-plan-selector-radio__label--selected',
              );
            }
          }
  
          this.product.selected_selling_plan = this.product.selling_plans_by_id[
            planId
          ];
          this.setPlansVisibility();
        },
  
        handleFormDomChanged: function (e) {
          setTimeout(
            function () {
              var variantId = this.$form.querySelector('[name=id]').value;
              this.product.selected_variant = this.product.variants.find(
                (v) => v.id == variantId,
              );
              this.setPlansVisibility();
            }.bind(this),
            20,
          );
        },
      });
  
      //Validates app is public
      const inPreviewMode = !!(
        window.location.search.includes('awt-preview') ||
        window.localStorage.getItem(PREVIEW_MODE_STORAGE_KEY) === 'true'
      );
  
      // make sure preview mode is set in local storage if in preview mode
      inPreviewMode &&
        window.localStorage.setItem(PREVIEW_MODE_STORAGE_KEY, inPreviewMode);
  
      // if we're in preview mode we can get rid of the URL param
      inPreviewMode && insertUrlParam('awt-preview');
  
      // show preview control if !appPublic and inPreviewMode
      if (inPreviewMode && !window.bundleapp.settings.appPublic) {
        showPreviewModeControl();
      }
  
      // update CSS vars
      setCssVars(window.bundleapp.settings.shopStyleSettings);
  
      if (window.bundleapp.settings.appPublic || inPreviewMode) {
        window.bundleapp.BundleAppWidget = BundleAppWidget;
        document.dispatchEvent(new Event('bundleapp:ready'));
      }
  
      /**
      * Iterating over forms
      */
      var shopInfoPromise = getShopInfo();
  
      window.bundleapp.initializeForms = function () {
        var $forms = document.querySelectorAll("form[action='/cart/add']");
        $forms.forEach(function (el) {
          // if we found more than one form, lets make sure we're adding only to the
          // forms that we want to..
          if ($forms.length > 1) {
            // check if this is the installments form (from Dawn theme) before
            // initializing the plan selector widget
            if (el.getAttribute('id') && el.getAttribute('id').includes('product-form-installment')) {
              return;
            }
  
            // additional checks will go here
          }
          var settings = window.bundleapp.settings;
          var $variantEl = el.querySelector('[name=id]');
  
          // Checking if the widget has been initialized already
          if (el.querySelector('[data-bundleapp-wrapper]')) {
            console.warn('Bundleapp: Form already initialized');
            return;
          }
          if ($variantEl) {
            var pathname = window.location.pathname;
            var search = window.location.search;
            var searchParams = new URLSearchParams(search);
            var reqParams = new URLSearchParams();
  
            //gets product handle if in a product page
            let productHandle = pathname.includes('/products/')
              ? pathname.split('/').filter(Boolean).pop()
              : null;
  
            // If there is a container selector we want to try to get the handle from it.
            // This because in collection pages or product pages with recommended products it
            // will be easier: ie <div data-bundleapp-widget="{{product.handle}}"/>
  
            var $containerSel = el.querySelector(
              settings.containerSel || '[data-bundleapp-widget]',
            );
  
            if (
              $containerSel &&
              $containerSel.dataset &&
              $containerSel.dataset.bundleappWidget
            ) {
              productHandle = $containerSel.dataset.bundleappWidget;
            }
  
            if (productHandle) {
              reqParams.append('productHandle', productHandle);
            }
            var getProductSelector = function () {
                return;
              return fetch(
                settings.productSelectorUrl
                  ? settings.productSelectorUrl +
                      productHandle +
                      '?view=selector&' +
                      reqParams.toString()
                  : settings.proxy + '/product-selector?' + reqParams.toString(),
              ).then(function (res) {
                if (!res.ok) {
                  throw new Error(res.statusText);
                }
                return res.text();
              });
            };
  
            // gets selected variant
            var variantId = $variantEl.value;
            if (variantId) {
              reqParams.append('variant', variantId);
            }
  
            // gets selected selling plan
            var sellingPlan = searchParams.get('selling_plan');
            if (sellingPlan) {
              reqParams.append('selling_plan', sellingPlan);
            }
  
            var compareHtmlStrings = function (html1, html2) {
              // We need to remove this uuid from the string since it is always different
              // This is used to uniquely identify each widget. and it cannot be any product related
              // attribute because we could have multiple selectors for the same product
              var regexWrapperIdHtml = /data-bundleapp-wrapper=["|']\d+["|']/gm;
              var regexWrapperIdJs = /"widget_id":\s?"\d+"/gm;
  
              var str1 = (html1 || '')
                .replace(regexWrapperIdHtml, '')
                .replace(regexWrapperIdJs, '');
              var str2 = (html2 || '')
                .replace(regexWrapperIdHtml, '')
                .replace(regexWrapperIdJs, '');
              return str1 === str2;
            };
  
            var cachedSelector;
            var selectorStorageKey = `bundleSelector1${productHandle + variantId}`;
  
            // We check first if there is a cached selector in local storage
            // to speed the render time
            try {
              cachedSelector = window.localStorage.getItem(selectorStorageKey);
              if (cachedSelector && cachedSelector !== 'undefined') {
                Promise.all([shopInfoPromise]).then(function () {
                  if (window.bundleapp.settings.appPublic || inPreviewMode) {
                    addAndInitiateSelector(
                      cachedSelector,
                      window.bundleapp.settings.shopStyleSettings,
                    );
                  }
                });
              }
            } catch (err) {
              console.error(err);
            }
  
            // we want to store the selector in a cache
            // in case there is a new version we can remove it and
            // create and initiate a new one
            var cachedDivContainer;
            var addAndInitiateSelector = function (htmlString, styleSettings) {
              var addSelector = function ($el) {
                // if selector style is selected use that
                if (styleSettings && styleSettings.SelectorStyle) {
                  $el.classList.add(styleSettings.SelectorStyle);
                }
                // if a container class has been set in the settings this means
                // that we've manually set them up, use this class
                else if (settings.containerClass) {
                  $el.classList.add(settings.containerClass);
                }
                // if styleSettings exist but no selector style has been chosen, default to awt-style-1
                else if (styleSettings && !styleSettings.SelectorStyle) {
                  $el.classList.add('awt-style-1');
                }
                // final default is bundleapp-container
                else {
                  $el.classList.add('bundleapp-container');
                }
  
                $el.innerHTML = htmlString.trim();
  
                var $renderBeforeEl, $renderAfterEl, $renderInsideEl;
                if (
                  settings.renderAfterSel ||
                  (styleSettings && styleSettings.RenderAfterSel)
                ) {
                  $renderAfterEl = el.querySelector(
                    settings.renderAfterSel || styleSettings.RenderAfterSel,
                  );
                } else if (
                  settings.renderBeforeEl ||
                  (styleSettings && styleSettings.RenderBeforeSel)
                ) {
                  $renderBeforeEl = el.querySelector(
                    settings.renderBeforeEl || styleSettings.RenderBeforeSel,
                  );
                } else if (
                  settings.renderInsideSel ||
                  (styleSettings && styleSettings.RenderInsideSel)
                ) {
                  $renderInsideEl = el.querySelector(
                    settings.renderInsideSel || styleSettings.RenderInsideSel,
                  );
                }
  
                // If there is a custom selector to render the widget
                if ($renderInsideEl) {
                  $renderInsideEl.append($el);
                } else if ($containerSel) {
                  // if the default container selector is available
                  $containerSel.append($el);
                } else if ($renderAfterEl) {
                  // else if renderAfterSel is set, render widget after that
                  $renderAfterEl.parentNode.insertBefore(
                    $el,
                    $renderAfterEl.nextSibling,
                  );
                } else if ($renderBeforeEl) {
                  // else if renderBeforeSel is set, render widget after that
                  $renderBeforeEl.parentNode.insertBefore($el, $renderBeforeEl);
                } else if ($variantEl) {
                  // else render the widget after the input field
                  $variantEl.parentNode.insertBefore($el, $variantEl.nextSibling);
                }
              };
  
              if (cachedDivContainer) {
                var newEl = document.createElement('div');
                addSelector(newEl);
                cachedDivContainer.parentNode.removeChild(cachedDivContainer);
              } else {
                cachedDivContainer = document.createElement('div');
                addSelector(cachedDivContainer);
              }
  
              const scriptMatches = [
                ...htmlString.matchAll(/<script type=.*>(.+)<\/script>/gims),
              ];
              if (scriptMatches.length && scriptMatches[0] && scriptMatches[0][1]) {
                try {
                  var product = JSON.parse(scriptMatches[0][1]);
                  /**
                  * Initiates the widget selector
                  */
                  var $selector = document.querySelector(
                    "[data-bundleapp-wrapper='" + product.widget_id + "']",
                  );
                  new window.bundleapp.BundleAppWidget($selector, product);
                } catch (err) {
                  console.warn('Bundle: Could not parse and initiate widget', err);
                }
              }
            };
  
            try {
              var prodSelectorPromise = getProductSelector();
              Promise.all([prodSelectorPromise, shopInfoPromise]).then((values) => {
                const responseText = values[0];
                // replaces to minify a bit the html string
                // .replace(/\n|\t/g, ' ') // replaces newlines and tabs
                // .replace(/>[\s]*?</g, '><') // removes spaces between open and close brackets
                // .replace(/[\s]*?</g, '<'); // removes spaces at start
  
                if (
                  (window.bundleapp.settings.appPublic || inPreviewMode) &&
                  !compareHtmlStrings(responseText, cachedSelector)
                ) {
                  window.localStorage.setItem(selectorStorageKey, responseText);
                  addAndInitiateSelector(
                    responseText,
                    window.bundleapp.settings.shopStyleSettings,
                  );
                }
              });
            } catch (err) {
              console.error(
                'Something went wrong while fetching and parsing the product',
                err,
              );
            }
          }
        });
      };
  
      window.bundleapp.initializeForms();
    })();
</script>
  
<style>

    .bundleapp-wrapper {
        border: none;
        padding: 0;
        margin-bottom: 20px;
        width: 100%;
    }
    .bundleapp-wrapper legend {
        font-size: 90%;
        margin-bottom: 5px;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-group {
        margin-bottom: 5px;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-group > label {
        display: flex;
        align-items: center;
        font-size: 90%;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-group label > input {
        min-height: 30px;
        margin-right: 10px;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-group select {
        width: 100%;
        margin-bottom: 20px;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-group-pricing {
        margin-left: auto;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-plan {
        margin-left: 23px;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-plan > label {
        font-size: 80%;
        display: block;
        text-align: left;
    }
    .bundleapp-wrapper .bundleapp-plan-selector-description span {
        border: solid 1px #dfe3e8;
        padding: 16px;
        height: auto;
        margin-top: 16px;
        border-radius: 0px;
        font-size: 90%;
        margin-left: 23px;
        display: block;
    }
    .bundleapp-price-adjustment {
        display: inline-block;
        margin-left: 10px;
        border: 1px solid;
        border-color: inherit;
        font-size: 80%;
        padding-left: 10px;
        padding-right: 10px;
        border-radius: 3px;
    }
    .bundleapp-legend {
        text-align: left;
        margin-bottom: 5px;
    }
    .awt-hidden-add-to-cart-button {
        display: none !important;
    }
    /**** PLAN SELECTOR BASICS ****/
    .awt-style-1, .awt-style-2 {
        width: 100%;
        margin-top: 20px;
        margin-bottom: 20px;
    }
    .awt-style-1 .bundleapp-wrapper, .awt-style-2 .bundleapp-wrapper {
        margin-bottom: 0;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-description span, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-description span {
        margin-left: 0;
    }
    /**** PLAN SELECTOR BASICS ****/
    /**** CUSTOM DROP DOWN ****/
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select {
        padding: 14px 50px 14px 17px;
        margin-bottom: 8px;
        appearance: none;
        -webkit-appearance: none;
        background-repeat: no-repeat;
        background-position: center right;
        background-image: url("data:image/svg+xml,%3Csvg width='44' height='24' xmlns='http://www.w3.org/2000/svg' role='presentation' focusable='false' aria-hidden='true' class='icon-chevron '%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath transform='rotate(90 12.414 12.4145)' stroke='null' id='svg_1' d='m10.121,19.122l6,-6a1,1 0 0 0 0,-1.415l-6,-6a1,1 0 0 0 -1.414,0a1,1 0 0 0 0,1.415l5.293,5.292l-5.293,5.293a1,1 0 1 0 1.414,1.415z' fill-rule='evenodd' fill='currentColor'/%3E%3C/g%3E%3C/svg%3E");
        background-size: 35px;
        background-color: #fff;
        border: 1px solid var(--awt-border-color);
        outline: 0;
        height: auto;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select:focus-visible, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select:focus-visible {
        box-shadow: none;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select:hover, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group select.bundleapp-plan-selector-select:hover {
        cursor: pointer;
    }
    /**** END CUSTOM DROP DOWN ****/
    /**** CUSTOM RADIO BUTTON ****/
    .awt-style-1 .bundleapp-wrapper input[type='radio'], .awt-style-2 .bundleapp-wrapper input[type='radio'] {
        /* Add if not using autoprefixer */
        -webkit-appearance: none;
        /* Remove most all native input styles */
        appearance: none;
        /* For iOS < 15 */
        background-color: #fff;
        /* Not removed via appearance */
        margin: 0 10px 0 0;
        color: currentColor;
        width: 20px;
        height: 20px;
        border: 1px solid currentColor;
        border-radius: 50%;
        /* transform: translateY(-0.075em);
        */
        display: grid;
        place-content: center;
        min-height: 0 !important;
        min-width: 20px;
        outline: none;
        padding: 0;
    }
    .awt-style-1 .bundleapp-wrapper input[type='radio']:focus .awt-style-2 .bundleapp-wrapper input[type='radio']:focus {
        /* remove outline */
        outline: none;
    }
    .awt-style-1 .bundleapp-wrapper input[type='radio']::before, .awt-style-2 .bundleapp-wrapper input[type='radio']::before {
        content: '';
        width: 10px;
        height: 10px;
        border-radius: 50%;
        transform: scale(0);
        transition: 120ms transform ease-in-out;
        background-color: var(--awt-radio-button-background);
        transition: background-color 0.3s;
    }
    .awt-style-1 .bundleapp-wrapper input[type='radio']:checked::before, .awt-style-2 .bundleapp-wrapper input[type='radio']:checked::before {
        transform: scale(1);
    }
    /**** END CUSTOM RADIO BUTTON ****/
    /**** CUSTOM FREQUENCY BUTTONS ****/
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-radio input, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-radio input {
        clip: rect(0, 0, 0, 0);
        overflow: hidden;
        position: absolute;
        height: 1px;
        width: 1px;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-radio__label, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-radio__label {
        display: inline-block;
        text-align: center;
        min-width: 36px;
        padding: 6px 10px;
        border: var(--awt-freq-button-border);
        color: var(--awt-freq-button-color);
        background-color: var(--awt-freq-button-background);
        cursor: pointer;
        border-radius: var(--awt-freq-button-border-radius);
        margin: 6px 8px 6px 0;
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-radio__label:hover, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-radio__label:hover {
        color: var(--awt-freq-button-color-hover);
        background-color: var(--awt-freq-button-background-hover);
        border: var(--awt-freq-button-border-hover);
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-radio__label.bundleapp-plan-selector-radio__label--selected, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-radio__label.bundleapp-plan-selector-radio__label--selected {
        background-color: var(--awt-freq-button-background-selected);
        color: var(--awt-freq-button-color-selected);
        border: var(--awt-freq-button-border-selected);
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-radio__label.bundleapp-plan-selector-radio__label--selected:hover, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-radio__label.bundleapp-plan-selector-radio__label--selected:hover {
        background-color: var(--awt-freq-button-background-hover-selected);
        color: var(--awt-freq-button-color-hover-selected);
        border: var(--awt-freq-button-border-hover-selected);
    }
    /**** END CUSTOM FREQUENCY BUTTONS ****/
    /**** CUSTOM LABEL ACCENT ****/
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group > label .awt-accent, .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group > label .awt-accent {
        background-color: var(--awt-accent-background);
        padding: 2px 8px;
        border-radius: 20px;
        font-size: 12px;
        display: inline-block;
        color: var(--awt-accent-color);
    }
    /**** END CUSTOM LABEL ACCENT ****/
    /*****************************************/
    /*****************************************/
    /**************** STYLE 1 ****************/
    /*****************************************/
    /*****************************************/
    /**** CUSTOM PLAN SELECTOR ****/
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group > label {
        font-weight: 400;
        margin-bottom: 0;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group > label:hover {
        cursor: pointer;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group {
        margin-bottom: 10px;
        padding: 10px 15px;
        border-radius: var(--awt-border-radius);
        border: 1px solid var(--awt-border-color);
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group .bundleapp-plan-selector-select {
        margin-bottom: 0;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group .bundleapp-plan-selector-plan {
        margin-top: 10px;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group .bundleapp-plan-selector-plan > label {
        margin-bottom: 8px;
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group.bundleapp-plan-selector-group--selected {
        border-color: var(--awt-selected-plan-border-color);
        background-color: var(--awt-selected-plan-background);
    }
    .awt-style-1 .bundleapp-wrapper .bundleapp-plan-selector-group.bundleapp-plan-selector-group--single-group {
        //border: none;
        background-color: initial;
        border-color: var(--awt-border-color);
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    /**** END CUSTOM PLAN SELECTOR ****/
    /*****************************************/
    /*****************************************/
    /**************** STYLE 2 ****************/
    /*****************************************/
    /*****************************************/
    /**** CUSTOM PLAN SELECTOR ****/
    .awt-style-2 .bundleapp-wrapper {
        border: 1px solid var(--awt-border-color);
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group:not(:last-child) {
        border-bottom: 1px solid var(--awt-border-color);
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group > label {
        font-weight: 400;
        margin-bottom: 0;
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group > label:hover {
        cursor: pointer;
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group .bundleapp-plan-selector-plan {
        margin-top: 10px;
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group .bundleapp-plan-selector-plan > label {
        margin-bottom: 8px;
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group {
        margin-bottom: 0;
        padding: 8px 20px;
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    .awt-style-2 .bundleapp-wrapper .bundleapp-plan-selector-group.bundleapp-plan-selector-group--selected {
        border-color: var(--awt-selected-plan-border-color);
        background-color: var(--awt-selected-plan-background);
        border-bottom: 0;
    }
    /**** END CUSTOM PLAN SELECTOR ****/
    /**** CUSTOMIZE CP ****/
    .bundle-button.button--primary:enabled {
        background-color: var(--awt-primary-button-background);
        color: var(--awt-primary-button-color);
        border-style: solid;
        border: var(--awt-primary-button-border);
        border-radius: var(--awt-primary-button-border-radius);
        transition: color 0.3s, background-color 0.3s, border-color 0.3s, border-width 0.3s;
    }
    .bundle-button.button--primary:enabled:hover {
        background-color: var(--awt-primary-button-background-hover);
        color: var(--awt-primary-button-color-hover);
        border: var(--awt-primary-button-border-hover);
    }
    /**** END CUSTOMIZE CP ****/
    /**** BaB UI ****/
    .bundleapp-modal__logo {
        background-image: url();
        background-position: center;
    }
    .awtomatic-progress-item {
        transition: border 0.3s, color 0.3s, background-color 0.3s;
    }
    .awtomatic-progress-item.awtomatic-progress-item--completed {
        background-color: var(--awt-progress-bar-background);
    }
    .awtomatic-progress-item.awtomatic-progress-item--completed .bundle-text--subheading {
        color: var(--awt-progress-bar-color);
    }
    .bundle-stepper-counter--complete {
        background-color: var(--awt-progress-bar-background);
        color: var(--awt-progress-bar-color);
    }
    .bundle-stepper-item:after {
        transition: border-color 0.3s;
    }
    .bundle-stepper-item--complete:after {
        border-bottom-color: var(--awt-progress-bar-background);
    }
    /**** End BaB UI ****/
    
    /**** Gift styling ****/
    .awt-gift-info-title {
        font-weight: 400;
        font-size: 16px;
        text-align: start;
    }
    .awt-error-msg {
        color: #ff2a51;
        text-align: start;
    }
    .awt-input-error.awt-error {
        background-color: rgba(255,42,81,.1);
        border: 2px solid #ff2a51;
    }
    .awt-floating-label {
        display: block;
        position: relative;
        border-radius: 5px;
        width: 100%;
    }
    .awt-floating-label:last-child {
        margin-bottom: 0;
    }
    .awt-floating-label input, .awt-floating-label textarea {
        font-family: inherit;
        width: 100%;
        height: 40px;
        border: none;
        outline: none;
        background-color: #f8f8f8;
        border-radius: 8px;
        padding: 0 12px;
        font-size: 16px;
        margin: 0px;
        font-family: inherit;
    }
    .awt-floating-label textarea {
        height: 120px;
        padding: 12px;
    }
    .awt-floating-label input::placeholder, .awt-floating-label textarea::placeholder {
        opacity: 0;
    }
    .awt-floating-label span {
        position: absolute;
        top: 20px;
        left: 8px;
        transform: translateY(-50%);
        font-size: 16px;
        padding: 0 4px;
        transition-duration: 300ms;
        border-radius: 5px;
    }
    label.awt-floating-label:focus-within > span, .awt-floating-label input:not(:placeholder-shown) + span, .awt-floating-label textarea:not(:placeholder-shown) + span {
        transform: translateY(-150%);
        font-size: 11px;
        background-color: rgba(255, 255, 255);
    }
    .awt-floating-label-warning {
        font-size: 14px;
        padding: 0 2px;
        text-align: start;
    }
    /*! form field group in 2 columns */
    .awt-form-group {
        display: flex;
        justify-content: space-between;
    }
    .awt-form-group > * {
        width: calc(50% - 4px);
        padding-bottom: 16px;
    }
    .awt-gift-input-container {
        padding-bottom:16px 
    }
    /*! custom checkbox */
    .awt-checkbox {
        display: flex;
        align-items: center;
        margin: 16px 0;
    }
    .awt-checkbox input[type="checkbox"] {
        /* Add if not using autoprefixer */
        -webkit-appearance: none;
        /* Remove most all native input styles */
        appearance: none;
        /* For iOS < 15 */
        background-color: #fff;
        width: 18px;
        height: 18px;
        margin-right: 4px;
        position: relative;
        border-radius: 2px;
        box-shadow: 0 0 0 1px inset #000;
    }
    .awt-checkbox input[type="checkbox"]:checked {
        /* For iOS < 15 */
        background-color: #000000;
    }
    .awt-checkbox input[type="checkbox"]:checked::before {
        content: "";
        position: absolute;
        left: 4px;
        top: 8px;
        background: white;
        width: 2px;
        height: 2px;
        box-shadow: 2px 0 0 white, 4px 0 0 white, 4px -2px 0 white, 4px -4px 0 white, 4px -6px 0 white, 4px -8px 0 white;
        transform: rotate(45deg);
    }
    .awt-checkbox input[type="checkbox"]:disabled {
        background-color: #f8f8f8;
        cursor: not-allowed;
    }
    /**** End Gift styling ****/

    /*** PREVIEW CONTROL ***/
    #awt-preview-mode-control {
        position: fixed;
        bottom: 15px;
        left: 50%;
        transform: translateX(-50%);
        height: 75px;
        z-index: 2147483647;
        background-color: #fff;
        color: #222;
        padding: 17px;
        display: flex;
        justify-content: space-between;
        align-content: center;
        box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.08);
        border-radius: 8px;
        box-sizing: border-box;
    }
    #awt-preview-mode-control.hidden {
        display: none;
    }
    #awt-preview-mode-control div.awt-logo {
        display: flex;
        height: 100%;
        align-items: center;
        flex-wrap: nowrap;
    }
    #awt-preview-mode-control div.awt-logo span {
        margin-top: 3px;
        font-size: 16px;
        font-family: sans-serif;
        color: #3700ff;
    }
    #awt-preview-mode-control div.awt-logo .awt-logo--image {
        display: block;
        background-image: url('https://bundle-public-assets.s3.amazonaws.com/customerPortal/awtomatic-no-dot.svg');
        background-repeat: no-repeat;
        background-size: contain;
        background-position: center;
        width: 95px;
        height: 100%;
        margin-right: 6px;
    }
    #awt-preview-mode-control div.awt-logo .awt-logo--info-icon {
        display: block;
        background-image: url('https://bundle-public-assets.s3.amazonaws.com/customerPortal/info-icon.svg');
        background-repeat: no-repeat;
        background-size: contain;
        background-position: center;
        width: 15px;
        height: 15px;
        margin: 5px 25px 0 9px;
    }
    #awt-preview-mode-control button {
        display: inline-block;
        border: 1px solid #eee;
        background-color: #fff;
        border-radius: 4px;
        padding: 5px 15px;
        margin: 0;
        text-decoration: none;
        color: #000;
        font-family: sans-serif;
        font-size: 15px;
        cursor: pointer;
        text-align: center;
        transition: background 250ms ease-in-out, transform 150ms ease;
        -webkit-appearance: none;
        -moz-appearance: none;
        font-weight: bold;
        height: 100%;
        outline: none;
        box-shadow: none;
    }
    #awt-preview-mode-control button:hover, #awt-preview-mode-control button:focus {
        background-color: #fbfbfb;
    }
    #awt-preview-mode-control button:focus {
        outline: none;
    }
    #awt-preview-mode-control button:active {
        transform: scale(0.99);
    }
    button#awt-preview-mode-control__hide {
        background-color: #fff;
        color: #000;
    }
    #awt-preview-mode-control button#awt-preview-mode-control__hide:hover, #awt-preview-mode-control button#awt-preview-mode-control__hide:focus {
        background: #eee;
    }
    @media only screen and (max-width: 480px) {
        #awt-preview-mode-control button#awt-preview-mode-control__hide {
            display: none;
        }
    }
    /*** END PREVIEW CONTROL ***/ 

</style>

awtomic-plan-selector.liquid

{% liquid
    assign hiddenShopGroupNames = ''
    assign visibleProductGroupNames = ''
    if shop.metafields.awtomic.hidden_selling_plan_groups
        assign hiddenShopGroupNames = shop.metafields.awtomic.hidden_selling_plan_groups.value | join: ","
    endif
    if product.metafields.awtomic.visible_selling_plan_groups
        assign visibleProductGroupNames = product.metafields.awtomic.visible_selling_plan_groups.value | join: ","
    endif
    assign hasNonHiddenPlans = false
    for group in product.selling_plan_groups
        unless hiddenShopGroupNames contains group.name
            assign hasNonHiddenPlans = true
        endunless
        if visibleProductGroupNames contains group.name
            assign hasNonHiddenPlans = true
        endif
    endfor
    
    assign isBaB = false
    if product.metafields.bundle.isBundle and product.metafields.bundle.type != 'shuffle'
        assign isBaB = true
    endif
%}

{% if hasNonHiddenPlans or isBaB %}

{%- comment -%} Awtomic App {%- endcomment -%}
{%- assign selected_selling_plan_id = product.selected_selling_plan -%}
{% assign min = 10 %}
{% assign max = 80 %}
{% assign diff = max | minus: min %}
{% assign uuid = "now" | date: "%N" | modulo: diff | plus: min | append: product.id %}
{%- assign variant = product.selected_or_first_available_variant -%}

{% comment %} Translations {% endcomment %}
{% assign one_time_purchase_label = 'awtomatic.plan_selector.one_time_purchase_label' | t %}
{% if one_time_purchase_label contains 'translation missing' %}
{% assign one_time_purchase_label = 'One-time purchase' %}
{% endif %}
{% assign purchase_options_label = 'awtomatic.plan_selector.purchase_options_label' | t %}
{% if purchase_options_label contains 'translation missing' %}
{% assign purchase_options_label = 'Purchase options' %}
{% endif %}

<div class="awt-style-1">
<fieldset data-bundleapp-wrapper="{{uuid}}" class="bundleapp-wrapper" style="display: none">
    {%- if product and product.selling_plan_groups.size > 0 -%}
    <input type="hidden" name="selling_plan" value="{{selected_selling_plan_id}}" />
    {% if product.selling_plan_groups.size > 1 %}
    <legend class="bundleapp-legend">{{ purchase_options_label }}</legend>
    {% endif %}

    {% unless product.requires_selling_plan %}
    <div class="bundleapp-plan-selector-group {% if selected_selling_plan_id == nil %}bundleapp-plan-selector-group--selected{% endif %}"
        data-one-time data-test="oneTimePrice">
        <label>
            <input type="radio" name="bundleapp-plan-selector-group" value="" {%- if selected_selling_plan_id==nil
                -%}checked{%-endif-%} />
            <span>{{ one_time_purchase_label }}</span>
            <span class="bundleapp-plan-selector-group-pricing">{{ product.selected_or_first_available_variant.price |
                money}}</span>
        </label>

        <div class="bundleapp-plan-selector-plan" style="display: none">
            <select class="bundleapp-plan-selector-select">
                <option value=""></option>
            </select>
            <div class="bundleapp-plan-selector-radio" style="display: none">
                <input type="radio" name="plan" value="" id="one-time-purchase" {%- if selected_selling_plan_id==nil
                    -%}checked{%-endif-%}>
            </div>
        </div>
    </div>
    {% endunless %}

    {% for selling_plan_group in product.selling_plan_groups %}
      {% liquid
        assign isHiddenGroupName = false
        if hiddenShopGroupNames contains selling_plan_group.name
          assign isHiddenGroupName = true
        endif
        if visibleProductGroupNames contains selling_plan_group.name
          assign isHiddenGroupName = false
        endif
      %}

      {%- unless isHiddenGroupName -%}
        {%- if selling_plan_group.app_id == "bundlesubscriptions" -%}
        <div class="bundleapp-plan-selector-group" style="display: none" data-test="{{ selling_plan_group.id }}">

            {%- comment -%}
            Labels:
            This first code block figures out the largest value of a subscription plan to now the "up to N"
            {%- endcomment -%}
            {% assign is_same_value = true %}
            {% assign prev_value = selling_plan_group.selling_plans[0].price_adjustments[0] %}
            {% assign largest_value = selling_plan_group.selling_plans[0].price_adjustments[0] %}
            {% for plan in selling_plan_group.selling_plans %}
            {% if prev_value.value != plan.price_adjustments[0].value %}
            {% assign is_same_value = false %}
            {% endif %}
            {% if largest_value.value < plan.price_adjustments[0].value %} {% assign largest_value=plan.price_adjustments[0]
                %} {% endif %} {% assign prev_value=plan.price_adjustments[0] %} {% endfor %} {%- comment -%} This numbers
                helps figuring out when to show or hide certain aspects of the UI ie: Hide the radio button when there is
                only a single subscription plan. {%- endcomment -%} {%- assign show_thresshold=0 -%} {%- if
                product.requires_selling_plan -%} {%- assign show_thresshold=1 -%} {%- endif -%} <label>
                <input type="radio" name="bundleapp-plan-selector-group" value="{{ selling_plan_group.id }}"
                    style="{% if product.selling_plan_groups.size <= show_thresshold %}display:none{% endif %}" />
                <span>{{ selling_plan_group.name }}</span>
                <span class="bundleapp-plan-selector-group-pricing"></span>
                </label>

                <div class="bundleapp-plan-selector-plan" id="bundleapp-plan-selector-{{selling_plan_group.id}}"
                    style="display: none">
                    {%- if selling_plan_group.selling_plans.size > 1 -%}
                    {% unless selling_plan_group.options[0].name == '*no_prefix*' %}
                    <label data-test="prefixFromSellingPlanGroup-{{ selling_plan_group.id }}">{{
                        selling_plan_group.options[0].name }}</label>
                    {% endunless %}
                    {%- else -%}
                    <label>
                        {% unless selling_plan_group.options[0].name == '*no_prefix*' %}
                        <span data-test="prefixFromSellingPlanGroup">{{ selling_plan_group.options[0].name }} </span>
                        {% endunless %}
                        <span data-test="prefixFromSellingPlan-{{ selling_plan_group.selling_plans[0].id }}">{{
                            selling_plan_group.selling_plans[0].options[0].value }}</span>
                    </label>
                    {%- endif -%}

                    <select class="bundleapp-plan-selector-select"
                        style="{% if selling_plan_group.selling_plans.size <= 1 %}display:none{% endif %}">
                        {% for plan in selling_plan_group.selling_plans %}
                        <option data-test="prefixFromSellingPlan-{{ plan.id }}" value="{{ plan.id }}" {%- if
                            selected_selling_plan_id==plan.id -%}selected{%-endif-%}>
                            {%- capture value -%}
                            {% if plan.price_adjustments[0].value_type == "percentage" %}
                            {% if plan.price_adjustments[0].value != 0 %} (Save {{plan.price_adjustments[0].value}}%){%
                            endif %}
                            {% else %}
                            {% if plan.price_adjustments[0].value != 0 %} (Save {{plan.price_adjustments[0].value |
                            money}}){% endif %}
                            {% endif %}
                            {%- endcapture -%}
                            {{ plan.options[0].value }}{% if is_same_value == false %} {{value}}{% endif %}
                        </option>
                        {% endfor %}
                    </select>

                    <div class="bundleapp-plan-selector-radio" style="display: none">
                        <div style="{% if selling_plan_group.selling_plans.size <= 1 %}display:none{% endif %}">
                            {% for plan in selling_plan_group.selling_plans %}
                            {%- capture valueOption -%}
                            {% if plan.price_adjustments[0].value_type == "percentage" %}
                            {% if plan.price_adjustments[0].value != 0 %} (Save {{plan.price_adjustments[0].value}}%){%
                            endif %}
                            {% else %}
                            {% if plan.price_adjustments[0].value != 0 %} (Save {{plan.price_adjustments[0].value |
                            money}}){% endif %}
                            {% endif %}
                            {%- endcapture -%}
                            <label
                                class="bundleapp-plan-selector-radio__label {% if selected_selling_plan_id == plan.id %}bundleapp-plan-selector-radio__label--selected{% endif %}"
                                for={{ plan.id }}>
                                <input
                                    class="bundleapp-plan-selector-radio__input {% if selected_selling_plan_id == plan.id %}bundleapp-plan-selector-radio__input--selected{% endif %}"
                                    type="radio" name="plan" data-test="prefixFromSellingPlan-{{ plan.id }}"
                                    value="{{ plan.id }}" id="{{ plan.id }}" {%- if selected_selling_plan_id==plan.id
                                    -%}checked{%-endif-%}>
                                {{ plan.options[0].value }}{% if is_same_value == false %} {{valueOption}}{% endif %}
                            </label>
                            {% endfor %}
                        </div>
                    </div>

                </div>
        </div>
        {%- endif -%}
      {%- endunless -%}
    {% endfor %}

    <div class="bundleapp-plan-selector-description">
        {% if product.selected_selling_plan.description and product.selected_selling_plan.description != '' %}<span>{{
            product.selected_selling_plan.description }}</span>{% endif %}
    </div>
    {%- endif -%}
</fieldset>
</div>

<script type="application/json">
  {%- assign selectedVariantId = variant.id -%}
  {%- assign selectedSellingPlanId = product.selected_selling_plan.id -%}
  {
    "widget_id": {{uuid | json}},
    "id": {{ product.id | json }},
    "title": {{ product.title | json }},
    "selling_plan_groups": {{ product.selling_plan_groups | json }},
    "variants": {{ product.variants | json }},
    "selected_variant": {%- liquid
      for variant in product.variants
        if variant.id == selectedVariantId
          echo variant | json
        endif
      endfor
    -%},
    "selling_plans_by_id": {
     {%- for group in product.selling_plan_groups -%}
      {%- assign parentLoop = forloop -%}
       {%- for plan in group.selling_plans -%}
          {%- capture planJson -%}
            {
              "id": {{- plan.id | json-}},
              "name": {{plan.name | json}},
              "description": {{plan.description | json}},
              "options": {{plan.options | json}},
              "recurring_deliveries": {{plan.recurring_deliveries | json}},
              "price_adjustments": {{plan.price_adjustments | json}},
              "selling_plan_group_id": {{group.id | json}}
            }
          {%- endcapture -%}
          {%- if plan.id == selectedSellingPlanId -%}
            {%- assign selectedSellingPlan = planJson -%}
          {%- endif -%}
         "{{plan.id}}": {{planJson}}
         {%- unless forloop.last == true and parentLoop.last == true -%},{%- endunless -%}
       {%- endfor -%}
     {%- endfor -%}
    },
    "metafields": {{ product.metafields.bundle | json }},
    "selectedSellingPlanId": {{selectedSellingPlanId | json}},
    "selected_selling_plan": {%- if selectedSellingPlan -%}{{selectedSellingPlan}}{%- else -%}null{%- endif -%},
    "translations": {
      "subscription": "{{ 'awtomatic.plan_selector.subscription' | t }}",
      "save": "{{ 'awtomatic.plan_selector.save' | t }}",
      "extra": "{{ 'awtomatic.plan_selector.extra' | t }}",
      "off": "{{ 'awtomatic.plan_selector.off' | t }}",
      "customize_my_box": "{{ 'awtomatic.plan_selector.customize_my_box' | t }}",
      "from": "{{ 'awtomatic.plan_selector.from' | t }}",
      "delivery_suffix": "{{ 'awtomatic.plan_selector.delivery_suffix' | t }}"
    }
  }
</script>

<script>
    (function () {
      var product = {};
      product.id = {{ product.id | json }};
      product.title = {{ product.title | json }};
      product.selling_plan_groups = {{ product.selling_plan_groups | json }};
      product.variants = {{ product.variants | json }};
      product.selected_selling_plan = {{product.selected_selling_plan | json}};
      product.selected_variant = {{ variant | json }};
      product.translations = {
        subscription: "{{ 'awtomatic.plan_selector.subscription' | t }}",
        save: "{{ 'awtomatic.plan_selector.save' | t }}",
        extra: "{{ 'awtomatic.plan_selector.extra' | t }}",
        off: "{{ 'awtomatic.plan_selector.off' | t }}",
        customize_my_box: "{{ 'awtomatic.plan_selector.customize_my_box' | t }}",
        from: "{{ 'awtomatic.plan_selector.from' | t }}",
        delivery_suffix: "{{ 'awtomatic.plan_selector.delivery_suffix' | t }}",
        gift_first_name_placeholder: "{{ 'awtomatic.plan_selector.gift_first_name_placeholder' | t }}",
        gift_first_name_label: "{{ 'awtomatic.plan_selector.gift_first_name_label' | t }}",
        gift_last_name_placeholder: "{{ 'awtomatic.plan_selector.gift_last_name_placeholder' | t }}",
        gift_last_name_label: "{{ 'awtomatic.plan_selector.gift_last_name_label' | t }}",
        gift_email_placeholder: "{{ 'awtomatic.plan_selector.gift_email_placeholder' | t }}",
        gift_email_label: "{{ 'awtomatic.plan_selector.gift_email_label' | t }}",
        gift_email_warning: "{{ 'awtomatic.plan_selector.gift_email_warning' | t }}",
        gift_note_placeholder: "{{ 'awtomatic.plan_selector.gift_note_placeholder' | t }}",
        gift_note_label: "{{ 'awtomatic.plan_selector.gift_note_label' | t }}",
        gift_checkbox_label: "{{ 'awtomatic.plan_selector.gift_checkbox_label' | t }}",
        gift_recipient_info_title: "{{ 'awtomatic.plan_selector.gift_recipient_info_title' | t }}"
      }
      product.metafields = {{ product.metafields.bundle | json }};
      product.gift_selling_plans = {%- if shop.metafields.sellingPlans.gifts -%} {{ shop.metafields.sellingPlans.gifts }} {%- else -%}[]{%- endif -%};

      product.selling_plans_by_id = (function() {
        var ret = {};
        for (group of product.selling_plan_groups) {
          for (plan of group.selling_plans) {
            ret[plan.id] = JSON.parse(JSON.stringify(plan));
            ret[plan.id].selling_plan_group_id = group.id;
          }
        }
        return ret;
      })();

      document.addEventListener("bundleapp:ready", function(){
        if(window.bundleapp && window.bundleapp.BundleAppWidget) {
          var $selector = document.querySelector("[data-bundleapp-wrapper='{{uuid}}']");
          var widget = new window.bundleapp.BundleAppWidget($selector, product);
        }
      });
    })();
</script>

{% endif %}

awtomic-translations.liquid

{% comment %} Awtomic Subscriptions {% endcomment %}
<script>
  var TRANSLATIONS = {
    en: {
      translation: {
        titles: {
          return_to_account: "{{ 'awtomatic.customer_portal.titles.return_to_account' | t }}",
          subscription: "{{ 'awtomatic.customer_portal.titles.subscription' | t }}",
          subscriptions: "{{ 'awtomatic.customer_portal.titles.subscriptions' | t }}",
          loading: "{{ 'awtomatic.customer_portal.titles.loading' | t }}",
          cancel: "{{ 'awtomatic.customer_portal.titles.cancel' | t }}",
          save: "{{ 'awtomatic.customer_portal.titles.save' | t }}",
          continue: "{{ 'awtomatic.customer_portal.titles.continue' | t }}",
          pause: "{{ 'awtomatic.customer_portal.titles.pause' | t }}",
          edit: "{{ 'awtomatic.customer_portal.titles.edit' | t }}",
          my_subscriptions: "{{ 'awtomatic.customer_portal.titles.my_subscriptions' | t }}",
          frequency: "{{ 'awtomatic.customer_portal.titles.frequency' | t }}",
          next_order: "{{ 'awtomatic.customer_portal.titles.next_order' | t }}",
          confirm: "{{ 'awtomatic.customer_portal.titles.confirm' | t }}",
          remove: "{{ 'awtomatic.customer_portal.titles.remove' | t }}",
          description: "{{ 'awtomatic.customer_portal.titles.description' | t }}",
          add: "{{ 'awtomatic.customer_portal.titles.add' | t }}",
        },
        email_gate: {
          no_subs: "{{ 'awtomatic.customer_portal.email_gate.no_subs' | t }}",
          check_email: "{{ 'awtomatic.customer_portal.email_gate.check_email' | t }}",
          cta_access_link: "{{ 'awtomatic.customer_portal.email_gate.cta_access_link' | t }}",
        },
        subscriptions: {
          error: "{{ 'awtomatic.customer_portal.subscriptions.error' | t }}",
          no_subs: "{{ 'awtomatic.customer_portal.subscriptions.no_subs' | t }}",
          link_to_account: "{{ 'awtomatic.customer_portal.subscriptions.link_to_account' | t }}",
        },
        subscription: {
          fetch_error: "{{ 'awtomatic.customer_portal.subscription.fetch_error' | t }}",
          auth_error: "{{ 'awtomatic.customer_portal.subscription.auth_error' | t }}",
          plan: "{{ 'awtomatic.customer_portal.subscription.plan' | t }}",
          active: "{{ 'awtomatic.customer_portal.subscription.active' | t }}",
          activate: "{{ 'awtomatic.customer_portal.subscription.activate' | t }}",
          pause: "{{ 'awtomatic.customer_portal.subscription.pause' | t }}",
          paused: "{{ 'awtomatic.customer_portal.subscription.paused' | t }}",
          cancel: "{{ 'awtomatic.customer_portal.subscription.cancel' | t }}",
          cancelled: "{{ 'awtomatic.customer_portal.subscription.cancelled' | t }}",
          shipment_info: "{{ 'awtomatic.customer_portal.subscription.shipment_info' | t }}",
          update_shipping: "{{ 'awtomatic.customer_portal.subscription.update_shipping' | t }}",
          payment_method: "{{ 'awtomatic.customer_portal.subscription.payment_method' | t }}",
          pay_pal_payment_method: "{{ 'awtomatic.customer_portal.subscription.pay_pal_payment_method' | t }}",
          ending_in: "{{ 'awtomatic.customer_portal.subscription.ending_in' | t }}",
          expires: "{{ 'awtomatic.customer_portal.subscription.expires' | t }}",
          add_phone: "{{ 'awtomatic.customer_portal.subscription.add_phone' | t }}",
          add_name: "{{ 'awtomatic.customer_portal.subscription.add_name' | t }}",
          add_lastName: "{{ 'awtomatic.customer_portal.subscription.add_lastName' | t }}",
          billing_attepts: "{{ 'awtomatic.customer_portal.subscription.billing_attepts' | t }}",
          percentage_dynamic_discount: "{{ 'awtomatic.customer_portal.subscription.percentage_dynamic_discount' | t }}",
          fixed_amount_dynamic_discount:
            "{{ 'awtomatic.customer_portal.subscription.fixed_amount_dynamic_discount' | t }}",
          then_dynamic_discount: "{{ 'awtomatic.customer_portal.subscription.then_dynamic_discount' | t }}",
          orders_dynamic_discount: "{{ 'awtomatic.customer_portal.subscription.orders_dynamic_discount' | t }}",
          billing_attepts_empty: "{{ 'awtomatic.customer_portal.subscription.billing_attepts_empty' | t }}",
          billing_attepts_error: "{{ 'awtomatic.customer_portal.subscription.billing_attepts_error' | t }}",
          subs_details: "{{ 'awtomatic.customer_portal.subscription.subs_details' | t }}",
          update_payment_btn: "{{ 'awtomatic.customer_portal.subscription.update_payment_btn' | t }}",
          cancel_prompt_title: "{{ 'awtomatic.customer_portal.subscription.cancel_prompt_title' | t }}",
          cancel_error: "{{ 'awtomatic.customer_portal.subscription.cancel_error' | t }}",
          no_payment_method_error: "{{ 'awtomatic.customer_portal.subscription.no_payment_method_error' | t }}",
          no_payment_method_error_add: "{{ 'awtomatic.customer_portal.subscription.no_payment_method_error_add' | t }}",
          new_payment_method_success: "{{ 'awtomatic.customer_portal.subscription.new_payment_method_success' | t }}",
          new_payment_method_error: "{{ 'awtomatic.customer_portal.subscription.new_payment_method_error' | t }}",
          remove_line_error: "{{ 'awtomatic.customer_portal.subscription.remove_line_error' | t }}",
          remove_line_success: "{{ 'awtomatic.customer_portal.subscription.remove_line_success' | t }}",
          ships_to: "{{ 'awtomatic.customer_portal.subscription.ships_to' | t }}",
          update_payment_success: "{{ 'awtomatic.customer_portal.subscription.update_payment_success' | t }}",
          update_payment_success_dunning:
            "{{ 'awtomatic.customer_portal.subscription.update_payment_success_dunning' | t }}",
          update_payment_success_payment_error:
            "{{ 'awtomatic.customer_portal.subscription.update_payment_success_payment_error' | t }}",
          update_payment_error: "{{ 'awtomatic.customer_portal.subscription.update_payment_error' | t }}",
          sales_tax: "{{ 'awtomatic.customer_portal.subscription.sales_tax' | t }}",
          skip_billing_interval_prompt:
            "{{ 'awtomatic.customer_portal.subscription.skip_billing_interval_prompt' | t }}",
          skip_billing_interval_success:
            "{{ 'awtomatic.customer_portal.subscription.skip_billing_interval_success' | t }}",
          skip_billing_interval_error: "{{ 'awtomatic.customer_portal.subscription.skip_billing_interval_error' | t }}",
          skip_until: "{{ 'awtomatic.customer_portal.subscription.skip_until' | t }}",
          skip_next: "{{ 'awtomatic.customer_portal.subscription.skip_next' | t }}",
          order_now: "{{ 'awtomatic.customer_portal.subscription.order_now' | t }}",
          next_order_success: "{{ 'awtomatic.customer_portal.subscription.next_order_success' | t }}",
          next_order_error: "{{ 'awtomatic.customer_portal.subscription.next_order_error' | t }}",
          add_new_address: "{{ 'awtomatic.customer_portal.subscription.add_new_address' | t }}",
          address_update_success: "{{ 'awtomatic.customer_portal.subscription.address_update_success' | t }}",
          address_update_failed: "{{ 'awtomatic.customer_portal.subscription.address_update_failed' | t }}",
          pause_subscription: "{{ 'awtomatic.customer_portal.subscription.pause_subscription' | t }}",
          cancel_subscription: "{{ 'awtomatic.customer_portal.subscription.cancel_subscription' | t }}",
          pause_disclaimer_date: "{{ 'awtomatic.customer_portal.subscription.pause_disclaimer_date' | t }}",
          pause_disclaimer_indefinitely:
            "{{ 'awtomatic.customer_portal.subscription.pause_disclaimer_indefinitely' | t }}",
          pause_success: "{{ 'awtomatic.customer_portal.subscription.pause_success' | t }}",
          reactivate_btn: "{{ 'awtomatic.customer_portal.subscription.reactivate_btn' | t }}",
          reactivate: "{{ 'awtomatic.customer_portal.subscription.reactivate' | t }}",
          reactivate_success: "{{ 'awtomatic.customer_portal.subscription.reactivate_success' | t }}",
          reactivate_error: "{{ 'awtomatic.customer_portal.subscription.reactivate_error' | t }}",
          frequency_days: "{{ 'awtomatic.customer_portal.subscription.frequency_days' | t }}",
          frequency_weeks: "{{ 'awtomatic.customer_portal.subscription.frequency_weeks' | t }}",
          frequency_months: "{{ 'awtomatic.customer_portal.subscription.frequency_months' | t }}",
          order_now_modal_body: "{{ 'awtomatic.customer_portal.subscription.order_now_modal_body' | t }}",
          amount: "{{ 'awtomatic.customer_portal.subscription.amount' | t }}",
          frequency_update_success: "{{ 'awtomatic.customer_portal.subscription.frequency_update_success' | t }}",
          frequency_update_error: "{{ 'awtomatic.customer_portal.subscription.frequency_update_error' | t }}",
          customer_update_success: "{{ 'awtomatic.customer_portal.subscription.customer_update_success' | t }}",
          customer_update_error: "{{ 'awtomatic.customer_portal.subscription.customer_update_error' | t }}",
          customer_update_info: "{{ 'awtomatic.customer_portal.subscription.customer_update_info' | t }}",
          verified_phone: "{{ 'awtomatic.customer_portal.subscription.verified_phone' | t }}",
          not_verified_phone: "{{ 'awtomatic.customer_portal.subscription.not_verified_phone' | t }}",
          verify_phone: "{{ 'awtomatic.customer_portal.subscription.verify_phone' | t }}",
          enter_code: "{{ 'awtomatic.customer_portal.subscription.enter_code' | t }}",
          verify_code_error: "{{ 'awtomatic.customer_portal.subscription.verify_code_error' | t }}",
          verify_code_retry_error: "{{ 'awtomatic.customer_portal.subscription.verify_code_retry_error' | t }}",
          verify_code_success: "{{ 'awtomatic.customer_portal.subscription.verify_code_success' | t }}",
          code_received: "{{ 'awtomatic.customer_portal.subscription.code_received' | t }}",
          code_enter: "{{ 'awtomatic.customer_portal.subscription.code_enter' | t }}",
          code_send: "{{ 'awtomatic.customer_portal.subscription.code_send' | t }}",
          qty: "{{ 'awtomatic.customer_portal.subscription.qty' | t }}",
          manage: "{{ 'awtomatic.customer_portal.subscription.manage' | t }}",
          your_next_order: "{{ 'awtomatic.customer_portal.subscription.your_next_order' | t }}",
          swap_product: "{{ 'awtomatic.customer_portal.subscription.swap_product' | t }}",
          swap_product_cta: "{{ 'awtomatic.customer_portal.subscription.swap_product_cta' | t }}",
          or: "{{ 'awtomatic.customer_portal.subscription.or' | t }}",
          update_variant: "{{ 'awtomatic.customer_portal.subscription.update_variant' | t }}",
          update_bundle: "{{ 'awtomatic.customer_portal.subscription.update_bundle' | t }}",
          save: "{{ 'awtomatic.customer_portal.subscription.save' | t }}",
          failed_payment_message: "{{ 'awtomatic.customer_portal.subscription.failed_payment_message' | t }}",
          failed_payment_cta: "{{ 'awtomatic.customer_portal.subscription.failed_payment_cta' | t }}",
          order_now_success: "{{ 'awtomatic.customer_portal.subscription.order_now_success' | t }}",
          order_now_error: "{{ 'awtomatic.customer_portal.subscription.order_now_error' | t }}",
          update_current_payment_method:
            "{{ 'awtomatic.customer_portal.subscription.update_current_payment_method' | t }}",
          add_new_card: "{{ 'awtomatic.customer_portal.subscription.add_new_card' | t }}",
          delayed: "{{ 'awtomatic.customer_portal.subscription.delayed' | t }}",
          delayedNotification: "{{ 'awtomatic.customer_portal.subscription.delayedNotification' | t }}",
          update_success: "{{ 'awtomatic.customer_portal.subscription.update_success' | t }}",
          update_line_success: "{{ 'awtomatic.customer_portal.subscription.update_line_success' | t }}",
          update_error: "{{ 'awtomatic.customer_portal.subscription.update_error' | t }}",
        },
        new_payment_method: {
          title: "{{ 'awtomatic.customer_portal.new_payment_method.title' | t }}",
          payment_info: "{{ 'awtomatic.customer_portal.new_payment_method.payment_info' | t }}",
          card_number: "{{ 'awtomatic.customer_portal.new_payment_method.card_number' | t }}",
          exp_date: "{{ 'awtomatic.customer_portal.new_payment_method.exp_date' | t }}",
          security_code: "{{ 'awtomatic.customer_portal.new_payment_method.security_code' | t }}",
          first_name: "{{ 'awtomatic.customer_portal.new_payment_method.first_name' | t }}",
          last_name: "{{ 'awtomatic.customer_portal.new_payment_method.last_name' | t }}",
          billing_address: "{{ 'awtomatic.customer_portal.new_payment_method.billing_address' | t }}",
          address1: "{{ 'awtomatic.customer_portal.new_payment_method.address1' | t }}",
          address2: "{{ 'awtomatic.customer_portal.new_payment_method.address2' | t }}",
          city: "{{ 'awtomatic.customer_portal.new_payment_method.city' | t }}",
          country: "{{ 'awtomatic.customer_portal.new_payment_method.country' | t }}",
          state: "{{ 'awtomatic.customer_portal.new_payment_method.state' | t }}",
          zip: "{{ 'awtomatic.customer_portal.new_payment_method.zip' | t }}",
          phone: "{{ 'awtomatic.customer_portal.new_payment_method.phone' | t }}",
        },
        tables: {
          ID: "{{ 'awtomatic.customer_portal.tables.ID' | t }}",
          status: "{{ 'awtomatic.customer_portal.tables.status' | t }}",
          item: "{{ 'awtomatic.customer_portal.tables.item' | t }}",
          created: "{{ 'awtomatic.customer_portal.tables.created' | t }}",
          next_order: "{{ 'awtomatic.customer_portal.tables.next_order' | t }}",
          skip: "{{ 'awtomatic.customer_portal.tables.skip' | t }}",
          product: "{{ 'awtomatic.customer_portal.tables.product' | t }}",
          quantity: "{{ 'awtomatic.customer_portal.tables.quantity' | t }}",
          price: "{{ 'awtomatic.customer_portal.tables.price' | t }}",
          total: "{{ 'awtomatic.customer_portal.tables.total' | t }}",
          shipping: "{{ 'awtomatic.customer_portal.tables.shipping' | t }}",
          originated: "{{ 'awtomatic.customer_portal.tables.originated' | t }}",
          frequency: "{{ 'awtomatic.customer_portal.tables.frequency' | t }}",
          phone: "{{ 'awtomatic.customer_portal.tables.phone' | t }}",
          name: "{{ 'awtomatic.customer_portal.tables.name' | t }}",
          lastName: "{{ 'awtomatic.customer_portal.tables.lastName' | t }}",
          date: "{{ 'awtomatic.customer_portal.tables.date' | t }}",
          sold_out: "{{ 'awtomatic.customer_portal.tables.sold_out' | t }}",
          partial_inventory: "{{ 'awtomatic.customer_portal.tables.partial_inventory' | t }}",
          qty_sold_out: "{{ 'awtomatic.customer_portal.tables.qty_sold_out' | t }}",
          order_number: "{{ 'awtomatic.customer_portal.tables.order_number' | t }}",
          subtotal: "{{ 'awtomatic.customer_portal.tables.subtotal' | t }}",
          loading_fulfillments: "{{ 'awtomatic.customer_portal.tables.loading_fulfillments' | t }}",
          last_fulfillment: "{{ 'awtomatic.customer_portal.tables.last_fulfillment' | t }}",
          next_fulfillment: "{{ 'awtomatic.customer_portal.tables.next_fulfillment' | t }}",
          merchant_discount: "{{ 'awtomatic.customer_portal.tables.merchant_discount' | t }}",
          one_time_discount_label: "{{ 'awtomatic.customer_portal.tables.one_time_discount_label' | t }}",
          finite_discount_label: "{{ 'awtomatic.customer_portal.tables.finite_discount_label' | t }}",
          edit: "{{ 'awtomatic.customer_portal.tables.edit' | t }}",
          box_discount: {
            percentage: "{{ 'awtomatic.customer_portal.tables.box_discount.percentage' | t }}",
            amount: "{{ 'awtomatic.customer_portal.tables.box_discount.amount' | t }}",
          },
        },
        login: {
          start_intro: "{{ 'awtomatic.customer_portal.login.start_intro' | t }}",
          welcome: "{{ 'awtomatic.customer_portal.login.welcome' | t }}",
          send_link: "{{ 'awtomatic.customer_portal.login.send_link' | t }}",
          email_address: "{{ 'awtomatic.customer_portal.login.email_address' | t }}",
          continue: "{{ 'awtomatic.customer_portal.login.continue' | t }}",
          welcome_back: "{{ 'awtomatic.customer_portal.login.welcome_back' | t }}",
          choose_login: "{{ 'awtomatic.customer_portal.login.choose_login' | t }}",
          send_secure_link: "{{ 'awtomatic.customer_portal.login.send_secure_link' | t }}",
          login_password: "{{ 'awtomatic.customer_portal.login.login_password' | t }}",
          check_email: "{{ 'awtomatic.customer_portal.login.check_email' | t }}",
          secure_email_sent: "{{ 'awtomatic.customer_portal.login.secure_email_sent' | t }}",
          not_received: "{{ 'awtomatic.customer_portal.login.not_received' | t }}",
          new_link: "{{ 'awtomatic.customer_portal.login.new_link' | t }}",
          different_email: "{{ 'awtomatic.customer_portal.login.different_email' | t }}",
          no_subscriptions: "{{ 'awtomatic.customer_portal.login.no_subscriptions' | t }}",
          invalid_email: "{{ 'awtomatic.customer_portal.login.invalid_email' | t }}",
          no_subscriptions_message: "{{ 'awtomatic.customer_portal.login.no_subscriptions_message' | t }}",
        },
        product_swap: {
          title_select: "{{ 'awtomatic.customer_portal.product_swap.title_select' | t }}",
          title_confirm: "{{ 'awtomatic.customer_portal.product_swap.title_confirm' | t }}",
          sold_out: "{{ 'awtomatic.customer_portal.product_swap.sold_out' | t }}",
          choose: "{{ 'awtomatic.customer_portal.product_swap.choose' | t }}",
          back: "{{ 'awtomatic.customer_portal.product_swap.back' | t }}",
          confirm: "{{ 'awtomatic.customer_portal.product_swap.confirm' | t }}",
          save: "{{ 'awtomatic.customer_portal.product_swap.save' | t }}",
          update: "{{ 'awtomatic.customer_portal.product_swap.update' | t }}",
          original_item: "{{ 'awtomatic.customer_portal.product_swap.original_item' | t }}",
          replacement_item: "{{ 'awtomatic.customer_portal.product_swap.replacement_item' | t }}",
          update_success: "{{ 'awtomatic.customer_portal.product_swap.update_success' | t }}",
          update_error: "{{ 'awtomatic.customer_portal.product_swap.update_error' | t }}",
        },
        bundles: {
          build_box: "{{ 'awtomatic.customer_portal.bundles.build_box' | t }}",
          of: "{{ 'awtomatic.customer_portal.bundles.of' | t }}",
          back: "{{ 'awtomatic.customer_portal.bundles.back' | t }}",
          continue: "{{ 'awtomatic.customer_portal.bundles.continue' | t }}",
          add_cart: "{{ 'awtomatic.customer_portal.bundles.add_cart' | t }}",
          select_plan: "{{ 'awtomatic.customer_portal.bundles.select_plan' | t }}",
          build_your_box: "{{ 'awtomatic.customer_portal.bundles.build_your_box' | t }}",
          addons: "{{ 'awtomatic.customer_portal.bundles.addons' | t }}",
          checkout: "{{ 'awtomatic.customer_portal.bundles.checkout' | t }}",
          edit_my_box: "{{ 'awtomatic.customer_portal.bundles.edit_my_box' | t }}",
          box_size: "{{ 'awtomatic.customer_portal.bundles.box_size' | t }}",
          add_cart_error: "{{ 'awtomatic.customer_portal.bundles.add_cart_error' | t }}",
          update_price: "{{ 'awtomatic.customer_portal.bundles.update_price' | t }}",
          update_success: "{{ 'awtomatic.customer_portal.bundles.update_success' | t }}",
          update_error: "{{ 'awtomatic.customer_portal.bundles.update_error' | t }}",
          delivery_options: "{{ 'awtomatic.customer_portal.bundles.delivery_options' | t }}",
          one_time_delivery: "{{ 'awtomatic.customer_portal.bundles.one_time_delivery' | t }}",
          additional_products: "{{ 'awtomatic.customer_portal.bundles.additional_products' | t }}",
        },
        addons: {
          title: "{{ 'awtomatic.customer_portal.addons.title' | t }}",
          selection_unavailable: "{{ 'awtomatic.customer_portal.addons.selection_unavailable' | t }}",
          success_added: "{{ 'awtomatic.customer_portal.addons.success_added' | t }}",
          subtitle: "{{ 'awtomatic.customer_portal.addons.subtitle' | t }}",
          subscribe: "{{ 'awtomatic.customer_portal.addons.subscribe' | t }}",
          select: "{{ 'awtomatic.customer_portal.addons.select' | t }}",
          see_products: "{{ 'awtomatic.customer_portal.addons.see_products' | t }}",
          modal_title: "{{ 'awtomatic.customer_portal.addons.modal_title' | t }}",
          save: "{{ 'awtomatic.customer_portal.addons.save' | t }}",
          type: "{{ 'awtomatic.customer_portal.addons.type' | t }}",
        },
        sms: {
          title: "{{ 'awtomatic.customer_portal.sms.title' | t }}",
          enable: "{{ 'awtomatic.customer_portal.sms.enable' | t }}",
          edit_phone: "{{ 'awtomatic.customer_portal.sms.edit_phone' | t }}",
          enable_phone: "{{ 'awtomatic.customer_portal.sms.enable_phone' | t }}",
          phone_placeholder: "{{ 'awtomatic.customer_portal.sms.phone_placeholder' | t }}",
          enable_phone_text: "{{ 'awtomatic.customer_portal.sms.enable_phone_text' | t }}",
          phone: "{{ 'awtomatic.customer_portal.sms.phone' | t }}",
          invalid_phone: "{{ 'awtomatic.customer_portal.sms.invalid_phone' | t }}",
          invalid_country: "{{ 'awtomatic.customer_portal.sms.invalid_country' | t }}",
          duplicated_phone_error: "{{ 'awtomatic.customer_portal.sms.duplicated_phone_error' | t }}",
        },
        cancelModal: {
          header: "{{ 'awtomatic.customer_portal.cancelModal.header' | t }}",
          neverMind: "{{ 'awtomatic.customer_portal.cancelModal.neverMind' | t }}",
          back: "{{ 'awtomatic.customer_portal.cancelModal.back' | t }}",
          continue: "{{ 'awtomatic.customer_portal.cancelModal.continue' | t }}",
          continueWithCancellation: "{{ 'awtomatic.customer_portal.cancelModal.continueWithCancellation' | t }}",
          continueCancel: "{{ 'awtomatic.customer_portal.cancelModal.continueCancel' | t }}",
          confirmCancellation: "{{ 'awtomatic.customer_portal.cancelModal.confirmCancellation' | t }}",
          error: "{{ 'awtomatic.customer_portal.cancelModal.error' | t }}",
          tryAgain: "{{ 'awtomatic.customer_portal.cancelModal.tryAgain' | t }}",
          TOO_MUCH: "{{ 'awtomatic.customer_portal.cancelModal.TOO_MUCH' | t }}",
          MOVING: "{{ 'awtomatic.customer_portal.cancelModal.MOVING' | t }}",
          COMPETITOR: "{{ 'awtomatic.customer_portal.cancelModal.COMPETITOR' | t }}",
          BUDGET: "{{ 'awtomatic.customer_portal.cancelModal.BUDGET' | t }}",
          NOT_ENJOY: "{{ 'awtomatic.customer_portal.cancelModal.NOT_ENJOY' | t }}",
          NO_NEED: "{{ 'awtomatic.customer_portal.cancelModal.NO_NEED' | t }}",
          TRAVELLING: "{{ 'awtomatic.customer_portal.cancelModal.TRAVELLING' | t }}",
          OTHER: "{{ 'awtomatic.customer_portal.cancelModal.OTHER' | t }}",
          frequency: {
            modalTitle: "{{ 'awtomatic.customer_portal.cancelModal.frequency.modalTitle' | t }}",
            title: "{{ 'awtomatic.customer_portal.cancelModal.frequency.title' | t }}",
            subtitle: "{{ 'awtomatic.customer_portal.cancelModal.frequency.subtitle' | t }}",
            updateFrequency: "{{ 'awtomatic.customer_portal.cancelModal.frequency.updateFrequency' | t }}",
            formModalTitle: "{{ 'awtomatic.customer_portal.cancelModal.frequency.formModalTitle' | t }}",
            formTitle: "{{ 'awtomatic.customer_portal.cancelModal.frequency.formTitle' | t }}",
            formDelivery: "{{ 'awtomatic.customer_portal.cancelModal.frequency.formDelivery' | t }}",
            setFrequency: "{{ 'awtomatic.customer_portal.cancelModal.frequency.setFrequency' | t }}",
          },
          address: {
            modalPromptTitle: "{{ 'awtomatic.customer_portal.cancelModal.address.modalPromptTitle' | t }}",
            promptTitle: "{{ 'awtomatic.customer_portal.cancelModal.address.promptTitle' | t }}",
            promptSubtitle: "{{ 'awtomatic.customer_portal.cancelModal.address.promptSubtitle' | t }}",
            promptUpdateAddress: "{{ 'awtomatic.customer_portal.cancelModal.address.promptUpdateAddress' | t }}",
            modalFormTitle: "{{ 'awtomatic.customer_portal.cancelModal.address.modalFormTitle' | t }}",
            noShippingOptions: "{{ 'awtomatic.customer_portal.cancelModal.address.noShippingOptions' | t }}",
            confirmModalTitle: "{{ 'awtomatic.customer_portal.cancelModal.address.confirmModalTitle' | t }}",
            confirmTitle: "{{ 'awtomatic.customer_portal.cancelModal.address.confirmTitle' | t }}",
            confirmAcceptShipping: "{{ 'awtomatic.customer_portal.cancelModal.address.confirmAcceptShipping' | t }}",
            newAddress: "{{ 'awtomatic.customer_portal.cancelModal.address.newAddress' | t }}",
            oldAddress: "{{ 'awtomatic.customer_portal.cancelModal.address.oldAddress' | t }}",
          },
          pause: {
            header: "{{ 'awtomatic.customer_portal.cancelModal.pause.header' | t }}",
            title: "{{ 'awtomatic.customer_portal.cancelModal.pause.title' | t }}",
            description: "{{ 'awtomatic.customer_portal.cancelModal.pause.description' | t }}",
            cta: "{{ 'awtomatic.customer_portal.cancelModal.pause.cta' | t }}",
            success: "{{ 'awtomatic.customer_portal.cancelModal.pause.success' | t }}",
          },
          skip: {
            header: "{{ 'awtomatic.customer_portal.cancelModal.skip.header' | t }}",
            title: "{{ 'awtomatic.customer_portal.cancelModal.skip.title' | t }}",
            description: "{{ 'awtomatic.customer_portal.cancelModal.skip.description' | t }}",
            ctaReschedule: "{{ 'awtomatic.customer_portal.cancelModal.skip.ctaReschedule' | t }}",
            ctaSkip: "{{ 'awtomatic.customer_portal.cancelModal.skip.ctaSkip' | t }}",
            success: "{{ 'awtomatic.customer_portal.cancelModal.skip.success' | t }}",
          },
          reschedule: {
            header: "{{ 'awtomatic.customer_portal.cancelModal.reschedule.header' | t }}",
            confirmReschedule: "{{ 'awtomatic.customer_portal.cancelModal.reschedule.confirmReschedule' | t }}",
            dateFormat: "{{ 'awtomatic.customer_portal.cancelModal.reschedule.dateFormat' | t }}",
            inputLabel: "{{ 'awtomatic.customer_portal.cancelModal.reschedule.inputLabel' | t }}",
            description: "{{ 'awtomatic.customer_portal.cancelModal.reschedule.description' | t }}",
          },
          confirm: {
            header: "{{ 'awtomatic.customer_portal.cancelModal.confirm.header' | t }}",
            modalTitle: "{{ 'awtomatic.customer_portal.cancelModal.confirm.modalTitle' | t }}",
            title: "{{ 'awtomatic.customer_portal.cancelModal.confirm.title' | t }}",
            button: "{{ 'awtomatic.customer_portal.cancelModal.confirm.button' | t }}",
            success: "{{ 'awtomatic.customer_portal.cancelModal.confirm.success' | t }}",
          },
        },
        drawers: {
          updateAddress: {
            title: "{{ 'awtomatic.customer_portal.drawers.updateAddress.title' | t }}",
          },
        },
        babFilters: {
          filters: "{{ 'awtomatic.babFilters.filters' | t }}",
          reset: "{{ 'awtomatic.babFilters.reset' | t }}",
        },
        billingHistory: {
          title: "{{ 'awtomatic.customer_portal.billingHistory.title' | t }}",
          order: "{{ 'awtomatic.customer_portal.billingHistory.order' | t }}",
          date: "{{ 'awtomatic.customer_portal.billingHistory.date' | t }}",
          status: "{{ 'awtomatic.customer_portal.billingHistory.status' | t }}",
          submitted: "{{ 'awtomatic.customer_portal.billingHistory.submitted' | t }}",
          challenged: "{{ 'awtomatic.customer_portal.billingHistory.challenged' | t }}",
          failed: "{{ 'awtomatic.customer_portal.billingHistory.failed' | t }}",
          success: "{{ 'awtomatic.customer_portal.billingHistory.success' | t }}",
          loadMore: "{{ 'awtomatic.customer_portal.billingHistory.loadMore' | t }}",
          bankChallenge: "{{ 'awtomatic.customer_portal.billingHistory.bankChallenge' | t }}",
        },
        pauseModal: {
          delaySubscriptionTitle: "{{ 'awtomatic.customer_portal.pauseModal.delaySubscriptionTitle' | t }}",
          delaySubscriptionSubtitle: "{{ 'awtomatic.customer_portal.pauseModal.delaySubscriptionSubtitle' | t }}",
          delaySubscriptionBody: "{{ 'awtomatic.customer_portal.pauseModal.delaySubscriptionBody' | t }}",
          delaySubscriptionCta: "{{ 'awtomatic.customer_portal.pauseModal.delaySubscriptionCta' | t }}",
          pauseModalTitle: "{{ 'awtomatic.customer_portal.pauseModal.pauseModalTitle' | t }}",
          pauseModalLabel: "{{ 'awtomatic.customer_portal.pauseModal.pauseModalLabel' | t }}",
          pauseModalBody: "{{ 'awtomatic.customer_portal.pauseModal.pauseModalBody' | t }}",
          continueToPause: "{{ 'awtomatic.customer_portal.pauseModal.continueToPause' | t }}",
          neverMind: "{{ 'awtomatic.customer_portal.pauseModal.neverMind' | t }}",
          back: "{{ 'awtomatic.customer_portal.pauseModal.back' | t }}",
          save: "{{ 'awtomatic.customer_portal.pauseModal.save' | t }}",
          confirmPause: "{{ 'awtomatic.customer_portal.pauseModal.confirmPause' | t }}",
          delaySubscription: "{{ 'awtomatic.customer_portal.pauseModal.delaySubscription' | t }}",
          ONE_MONTH: "{{ 'awtomatic.customer_portal.pauseModal.ONE_MONTH' | t }}",
          TWO_MONTH: "{{ 'awtomatic.customer_portal.pauseModal.TWO_MONTH' | t }}",
          THREE_MONTH: "{{ 'awtomatic.customer_portal.pauseModal.THREE_MONTH' | t }}",
          CUSTOM: "{{ 'awtomatic.customer_portal.pauseModal.CUSTOM' | t }}",
        },
        discountCodeCard: {
          title: "{{ 'awtomatic.customer_portal.discountCodeCard.title' | t }}",
          addBtn: "{{ 'awtomatic.customer_portal.discountCodeCard.addBtn' | t }}",
          cancelBtn: "{{ 'awtomatic.customer_portal.discountCodeCard.cancelBtn' | t }}",
          inputPlaceholder: "{{ 'awtomatic.customer_portal.discountCodeCard.inputPlaceholder' | t }}",
          applyBtn: "{{ 'awtomatic.customer_portal.discountCodeCard.applyBtn' | t }}",
          successMsg: "{{ 'awtomatic.customer_portal.discountCodeCard.successMsg' | t }}",
          removeSuccessMsg: "{{ 'awtomatic.customer_portal.discountCodeCard.removeSuccessMsg' | t }}",
          loadingMsg: "{{ 'awtomatic.customer_portal.discountCodeCard.loadingMsg' | t }}",
          errorMsg: "{{ 'awtomatic.customer_portal.discountCodeCard.errorMsg' | t }}",
          boxDiscount: "{{ 'awtomatic.customer_portal.discountCodeCard.boxDiscount' | t }}",
        },
      },
    },
  };

  window.bundleapp = window.bundleapp || {};
  window.bundleapp.settings = {
    ...window.bundleapp.settings,
    translations: TRANSLATIONS,
  };
</script>

locale file json addition

"awtomatic": {
    "plan_selector": {
      "subscription": "SUBSCRIPTION",
      "save": "Save",
      "extra": "Extra",
      "off": "off",
      "customize_my_box": "Customize my box",
      "from": "Starting from",
      "delivery_suffix": "\/delivery",
      "one_time_purchase_label": "One-time purchase",
      "purchase_options_label": "Purchase options",
      "gift_first_name_placeholder":"First name",
      "gift_first_name_label":"First name",
      "gift_last_name_placeholder":"Last name",
      "gift_last_name_label":"Last name",
      "gift_email_placeholder":"Email address",
      "gift_email_label":"Email address",
      "gift_email_warning":"Important: Gift emails will be sent here",
      "gift_note_placeholder":"Note",
      "gift_note_label":"Note",
      "gift_checkbox_label":"This is a gift",
      "gift_recipient_info_title":"Recipient info"
    },
    "customer_portal": {
      "titles": {
        "return_to_account": "Return to account details",
        "subscription": "Subscription",
        "subscriptions": "Subscriptions",
        "loading": "Loading...",
        "cancel": "Cancel",
        "save": "Save",
        "continue": "Continue",
        "pause": "Pause",
        "edit": "Edit",
        "my_subscriptions": "My Subscriptions",
        "frequency": "Frequency",
        "next_order": "Next Order",
        "confirm": "Confirm",
        "remove": "Remove",
        "description": "Description",
        "add": "Add"
      },
      "email_gate": {
        "no_subs": "You do not have any subscriptions yet",
        "check_email": "Check your email to access your subscriptions, {{email}}",
        "cta_access_link": "Email me an access link"
      },
      "subscriptions": {
        "error": "There was an error loading your subscriptions",
        "no_subs": "You do not have any subscriptions yet",
        "link_to_account": "Return to Account Details"
      },
      "subscription": {
        "fetch_error": "There was an error fetching the detail subscription",
        "auth_error": "There was authorization error, please login again",
        "plan": "Plan",
        "active": "Active",
        "activate": "Activate",
        "pause": "Pause",
        "paused": "Paused",
        "cancel": "Cancel",
        "cancelled": "Cancelled",
        "shipment_info": "Shipment info",
        "update_shipping": "Update shipping",
        "payment_method": "Payment method",
        "pay_pal_payment_method": "PayPal",
        "ending_in": "ending in",
        "expires": "Expires",
        "add_phone": "Enter a phone number",
        "add_name": "Enter your name",
        "add_lastName": "Enter your last name",
        "billing_attepts": "Billing Attempts",
        "percentage_dynamic_discount": "{{discount}} % off",
        "fixed_amount_dynamic_discount": "{{discount}} off",
        "then_dynamic_discount": " then {{discount}}",
        "orders_dynamic_discount": " for {{orderQty}} orders,",
        "billing_attepts_empty": "There are no billing attempts",
        "billing_attepts_error": "There was an error loading the billing attempts",
        "subs_details": "Subscription Details",
        "update_payment_btn": "Update payment",
        "cancel_prompt_title": "Canceling subscription cannot be undone. If you want to resume shipments, you will need to create a new order in the store.",
        "cancel_error": "There was an error trying to cancel your subscription",
        "no_payment_method_error": "Payment method missing from subscripiton.",
        "no_payment_method_error_add": "Please add a new card.",
        "new_payment_method_success": "Succesfully updated the payment method.",
        "new_payment_method_error": "Unknown error adding your payment method. Please try again.",
        "remove_line_error": "There was an error trying to remove the product",
        "remove_line_success": "Succesfully removed the product",
        "ships_to": "Ships to",
        "update_payment_success": "An email was sent to {{email}} with a secure link to update payment information.",
        "update_payment_success_dunning": "An email was sent to {{email}} with a secure link to update payment information. After payment information is updated we will retry the order.",
        "update_payment_success_payment_error": "Unable to add payment method. An email was sent to {{email}} with a secure link to update payment.",
        "update_payment_error": "There was an error updating your payment information",
        "sales_tax": "Sales tax (if applicable) is not displayed because it is calculated with each new order.",
        "skip_billing_interval_prompt": "Are you sure you want to skip?",
        "skip_billing_interval_success": "Your next order has been rescheduled to {{date}}",
        "skip_billing_interval_error": "There was an error skipping your next order",
        "skip_until": "Skip until",
        "skip_next": "Skip next",
        "order_now": "Order now",
        "next_order_success": "Your next order has been rescheduled to {{date}}",
        "next_order_error": "There was an error setting the subscription's next order date.",
        "add_new_address": "Add new address",
        "address_update_success": "Address updated successfully",
        "address_update_failed": "We encountered an unknown error. Please try again.",
        "pause_subscription": "Pause subscription",
        "cancel_subscription": "Cancel subscription",
        "pause_disclaimer_date": "We will postpone your subscription. Your subscription will remain active, but you will not be charged until {{date}}. You can pause indefinitely or reschedule anytime.",
        "pause_disclaimer_indefinitely": "You will not be charged while your subscription is paused. Reactivate your subscription anytime in your account.",
        "pause_success": "Your subscription was paused successfully",
        "reactivate_btn": "Reactivate now",
        "reactivate": "Reactivate",
        "reactivate_success": "Your subscription has been successfully reactivated.",
        "reactivate_error": "Something went wrong while reactivating your subscription. Please try again",
        "frequency_days": "day(s)",
        "frequency_weeks": "week(s)",
        "frequency_months": "month(s)",
        "order_now_modal_body": "You will be charged {{amount}} and your shipment will go out as soon as possible.",
        "amount": "Amount",
        "frequency_update_success": "Delivery frequency updated to {{ frequency }}.",
        "frequency_update_error": "Unknown error. Delivery frequency could not be updated.",
        "customer_update_success": "Customer information has been updated",
        "customer_update_error": "Unknown error. Customer information could not be updated.",
        "customer_update_info": "Adding your phone number, you will receive free SMS with information about your next subscription, allowing you to skip it,or editing it through your phone",
        "verified_phone": "Phone verified",
        "not_verified_phone": "Phone not verified",
        "verify_phone": "Verify",
        "enter_code": "Enter the verification code",
        "verify_code_error": "There was an error verifying your phone number.",
        "verify_code_retry_error": "You have tried to verify your phone number too many times. Please, try it later.",
        "verify_code_success": "Phone number verified successfully",
        "code_received": "You must have received a confirmation code in the provided phone number.",
        "code_enter": "Please enter the code below to verify your phone number.",
        "code_send": "Send code",
        "qty": "Qty",
        "manage": "Manage",
        "your_next_order": "Your next order",
        "swap_product": "Swap products",
        "swap_product_cta": "Swap for another product...",
        "or": "Or",
        "update_variant": "Change selection",
        "update_bundle": "Update Box",
        "save": "Save {{percentage}}%",
        "failed_payment_message": "Failed payment with saved method. We will automatically retry payment.",
        "failed_payment_cta": "Update Payment method",
        "order_now_success": "Order placed successfully",
        "order_now_error": "Unknown error. Please try again.",
        "update_current_payment_method": "Update current payment method",
        "add_new_card": "Add new card",
        "delayed": "Delayed",
        "delayedNotification": "Subscription delayed due to inventory. Order will ship when item becomes available. To receive order more quickly, please update selection below.",
        "update_success": "Your subscription has been updated successfully.",
        "update_line_success": "Subscription updated. The order will ship out as soon as possible.",
        "update_error": "Something went wrong. Your subscription has not been changed."
      },
      "new_payment_method": {
        "title": "Enter payment method",
        "payment_info": "Payment information",
        "card_number": "Card number",
        "exp_date": "Exp date",
        "security_code": "CVV",
        "first_name": "First Name",
        "last_name": "Last Name",
        "billing_address": "Billing address",
        "address1": "Address",
        "address2": "Apartment, suite, etc. (optional)",
        "city": "City",
        "country": "Country\/Region",
        "state": "State\/Province",
        "zip": "Zip code",
        "phone": "Phone (optional)"
      },
      "tables": {
        "ID": "ID",
        "status": "Status",
        "item": "Item",
        "created": "Created",
        "next_order": "Next Order",
        "skip": "Skip",
        "product": "Product",
        "quantity": "Quantity",
        "price": "Price",
        "total": "Total",
        "shipping": "Shipping",
        "originated": "Originated",
        "frequency": "Frequency",
        "phone": "Phone",
        "name": "Name",
        "lastName": "Last name",
        "date": "Date",
        "sold_out": "Sold out",
        "partial_inventory": "Partial inventory",
        "qty_sold_out": " • {{quantity}} sold out",
        "order_number": "Order Number",
        "subtotal": "Subtotal",
        "loading_fulfillments": "Loading...",
        "last_fulfillment": "Last fulfillment",
        "next_fulfillment": "Next fulfillment",
        "merchant_discount": "Discount",
        "one_time_discount_label": "(One-time)",
        "finite_discount_label": "({{usageCount}} of {{recurringCycleLimit}})",
        "edit": "Edit",
        "box_discount": {
          "percentage": "Box discount ({{value}}%)",
          "amount": "Box discount ({{value}})"
        }
      },
      "login": {
        "start_intro": "Enter your email address to get started",
        "welcome": "Welcome",
        "send_link": "We'll email you a secure link to sign in.",
        "email_address": "Email address",
        "continue": "Continue",
        "welcome_back": "Welcome back",
        "choose_login": "Choose how to login for",
        "send_secure_link": "Send me secure link",
        "login_password": "Login with password",
        "check_email": "Check your email for login link",
        "secure_email_sent": "We've sent a secure email to {{email}}. The link expires in 24 hours.",
        "not_received": "Didn't receive it?",
        "new_link": "Send me a new link",
        "different_email": "Try different email",
        "no_subscriptions": "No subscriptions found",
        "invalid_email": "Invalid Email",
        "no_subscriptions_message": "We couldn't find any subscriptions associated with"
      },
      "product_swap": {
        "title_select": "Choose replacement item",
        "title_confirm": "Confirm",
        "sold_out": "Sold out",
        "choose": "Choose",
        "back": "Back",
        "confirm": "Confirm",
        "save": "Save",
        "update": "Update",
        "original_item": "Original item",
        "replacement_item": "Replacement item",
        "update_success": "Successfully swapped items for the next order.",
        "update_error": "Something went wrong. Your subscription has not been changed."
      },
      "bundles": {
        "build_box": "Build your box",
        "of": "of",
        "back": "Back",
        "continue": "Continue",
        "add_cart": "Add to cart",
        "select_plan": "Select plan",
        "build_your_box": "Build your box",
        "addons": "Add-ons",
        "checkout": "Checkout",
        "edit_my_box": "Edit my box",
        "box_size": "Box size",
        "add_cart_error": "There was an error updating your cart.",
        "update_price": "Cost of the box has changed from {{prevBasePrice}} to {{basePrice}}",
        "update_success": "Box successfully updated",
        "update_error": "Something went wrong trying to update the box",
        "delivery_options": "Delivery options",
        "one_time_delivery": "One time",
        "additional_products": "Additional products"
      },
      "addons": {
        "title": "Add Items",
        "selection_unavailable": "Selection unavailable",
        "success_added": "Successfully added items to your subscription.",
        "subtitle": "Add items to your upcoming order",
        "subscribe": "Subscribe",
        "select": "Add",
        "see_products": "See all products",
        "modal_title": "Add products to your next order",
        "save": "Save",
        "type": "Type"
      },
      "sms": {
        "title": "Text updates",
        "enable": "Enable",
        "edit_phone": "Edit phone number",
        "enable_phone": "Enable text updates",
        "phone_placeholder": "Enter phone number",
        "enable_phone_text": "Text messages allow you to update subscriptions on the go. Message and. data rates may apply.",
        "phone": "Phone number",
        "invalid_phone": "Invalid phone number",
        "invalid_country": "Only US and CA phone numbers are supported.",
        "duplicated_phone_error": "Phone number already in use"
      },
      "cancelModal": {
        "header": "Reason for cancelling",
        "neverMind": "Never mind",
        "back": "Back",
        "continue": "Continue",
        "continueWithCancellation": "Continue with cancellation",
        "continueCancel": "Continue cancel",
        "confirmCancellation": "Confirm cancellation",
        "error": "There was an unknown error",
        "tryAgain": "Try again.",
        "TOO_MUCH": "I have too much",
        "MOVING": "Moving to a new place",
        "COMPETITOR": "Switching to a competitor",
        "BUDGET": "Doesn’t fit my budget",
        "NOT_ENJOY": "I didn’t enjoy the product",
        "NO_NEED": "No longer need this",
        "TRAVELLING": "I’m traveling",
        "OTHER": "Other",
        "frequency": {
          "modalTitle": "Frequency update available",
          "title": "Update frequency instead of losing subscription",
          "subtitle": "By updating your delivery frequency, you can control how often you recieve shipments.",
          "updateFrequency": "Update frequency",
          "formModalTitle": "Edit frequency",
          "formTitle": "You control how often your receive deliveries. Upcoming orders will be delivered on the frequency selected below.",
          "formDelivery": "Delivery every",
          "setFrequency": "Set frequency"
        },
        "address": {
          "modalPromptTitle": "Address update available",
          "promptTitle": "Moving doesn’t have to mean cancellation",
          "promptSubtitle": "By updating your address, you have the option of keeping your subscription with you wherever you go!",
          "promptUpdateAddress": "Update address",
          "modalFormTitle": "Enter address",
          "noShippingOptions": "There are no shipping options available for that address.",
          "confirmModalTitle": "Shipping confirmation",
          "confirmTitle": "The price of shipping for your subscription will change from {{oldPrice}} to {{newPrice}} because your new address is in a different delivery zone.",
          "confirmAcceptShipping": "Accept shipping",
          "newAddress": "New address:",
          "oldAddress": "Old address:"
        },
        "pause": {
          "header": "Pause available",
          "title": "Did you know you can pause instead?",
          "description": "Instead of cancelling, pausing your subscription allows you to keep billing and shipping details saved when you’re ready to reactivate your subscription.",
          "cta": "Pause subscription",
          "success": "Your subscription was paused successfully"
        },
        "skip": {
          "header": "Skip available",
          "title": "You can skip or reschedule your next order",
          "description": "Keep your shipments coming once you’re back from your trip. Consider skipping or rescheduling instead of canceling.",
          "ctaReschedule": "Reschedule next order",
          "ctaSkip": "Skip next",
          "success": "Your next order has been rescheduled to {{date}}"
        },
        "reschedule": {
          "header": "Schedule next order",
          "confirmReschedule": "Reschedule",
          "dateFormat": "mm\/dd\/yyyy",
          "inputLabel": "Next order",
          "description": "Your subscription will remain active, but we will postpone your subscription until the date you select below."
        },
        "confirm": {
          "modalTitle": "Additional feedback",
          "title": "Please provide additional feedback (optional)",
          "button": "Confirm cancellation",
          "success": "Subscription cancelled"
        }
      },
      "drawers": {
        "updateAddress": {
          "title": "Enter address"
        }
      },
      "billingHistory": {
        "title": "Billing history",
        "order": "Order",
        "date": "Date",
        "status": "Status",
        "submitted": "Submitted",
        "challenged": "Challenged",
        "failed": "Failed",
        "success": "Success",
        "loadMore": "Load more",
        "bankChallenge": "Complete Challenge"
      },
      "pauseModal": {
        "delaySubscriptionTitle": "Delay subscription available",
        "delaySubscriptionSubtitle": "Consider delaying subscription instead",
        "delaySubscriptionBody": "By delaying your subscription, you can make sure orders start again without needing to remember to turn them back on.",
        "delaySubscriptionCta": "Delay subscription",
        "pauseModalTitle": "Pause subscription",
        "pauseModalLabel": "Pause subscription for",
        "pauseModalBody": "You will not be charged while your subscription is paused. Reactivate your subscription anytime in your account",
        "continueToPause": "Continue to Pause",
        "neverMind": "Never mind",
        "back": "Back",
        "save": "Save",
        "confirmPause": "Confirm",
        "delaySubscription": "Delay subscription",
        "ONE_MONTH": "1 month",
        "TWO_MONTH": "2 months",
        "THREE_MONTH": "3 months",
        "CUSTOM": "Custom"
      },
      "discountCodeCard": {
        "title": "Discount Code",
        "addBtn": "Add",
        "cancelBtn": "Cancel",
        "inputPlaceholder": "Enter code",
        "applyBtn": "Apply",
        "successMsg": "Discount applied to subscription",
        "removeSuccessMsg": "Discount removed from subscription",
        "loadingMsg": "Adding discount code...",
        "errorMsg": "Invalid code",
        "boxDiscount": "Box discount"
      },
    },
    "babFilters": {
      "filters": "Filters",
      "reset": "Reset"
    } 
  }