What code do I need to add to add superscript to a Product Price - I can't find the ID in inspector

I’m having trouble with
Adding superscript to the Product Price of a Product in Wix. The template does not allow it and I can’t find the ID of the Price either

Working in
e.g. Wix Studio Editor

Site link
If this is happening on a site, include a live or test site link

What I’m trying to do
I need to make all the cents/pennies of a Product Price superscript

What I’ve tried so far
I’ve tried googling the code to add to Velo and have tried multiple options. I’ve also added CSS to global CSS. Nothing has worked

Extra context
Anything else that might help - edge cases, screenshots, etc.

As far as I know, there’s no universal setting to control this within the Wix Stores widgets.

And since Wix App Widgets come “as is”, you generally can’t target specific parts via adding site code in the editor.


With that said, it seems it might be possible with some code added to the Head of your site (via the site dashboard> Settings> Custom code).

When looking at the site HTML, you can see a data-hook, which are considered stable properties of the page, allowing you to target and manipulate the inner content.

Something like the following (not fully tested), should target the price on the product page (only on the live site), and display it as you need it.

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const style = document.createElement('style');

    style.textContent = `
      [data-hook="formatted-primary-price"] {
        display: inline-flex !important;
        align-items: flex-start !important;
        gap: 0.02em !important;
      }

      [data-hook="formatted-primary-price"] .price-cents {
        font-size: 0.55em !important;
        line-height: 1 !important;
        margin-top: 0.15em !important;
      }
    `;

    document.head.appendChild(style);

    function formatPrice(priceEl) {
      if (!priceEl || priceEl.dataset.priceFormatted === 'true') return;

      const rawPrice =
        priceEl.getAttribute('data-wix-price') ||
        priceEl.textContent.trim();

      const match = rawPrice.match(/^([^0-9]*)(\d+)([.,](\d{2}))?$/);

      if (!match) return;

      const currency = match[1] || '';
      const pounds = match[2];
      const cents = match[4];

      priceEl.innerHTML = `
        <span class="price-currency">${currency}</span>
        <span class="price-main">${pounds}</span>
        ${cents ? `<sup class="price-cents">${cents}</sup>` : ''}
      `;

      priceEl.dataset.priceFormatted = 'true';
    }

    function formatAllPrices() {
      document
        .querySelectorAll('[data-hook="formatted-primary-price"]')
        .forEach(formatPrice);
    }

    formatAllPrices();

    const observer = new MutationObserver(formatAllPrices);

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  });
</script>

To be transparent, I haven’t checked how this impacts performance or SEO, although should be considered a pretty safe change. Hope this helps :slight_smile:

Hi Noah,

Thank you so much! I’ll test it now and let you know.

Thank you!

Annie

Hi Noah, sadly it hasn’t worked.

How did you set it to load? Load once, or on every page?

I forgot to mention that part :face_with_peeking_eye: - it should be set to on every page. You may need to refresh the page/open in a new tab to see it working

Hi Noah,
I have done what yo said and sadly it still has not changed.

Should I move it to the Body rather than the Heading?

Seems to be working now, right?

Hi Noah,

Yes - it’s working on that page! Thank you.

However not on the Home Page where I crreated a Catalgue Product Grid https://annie5344.wixstudio.com/my-site

Any thoughts on this?

Thanks for all your help.

Where it is working, it’s missing the ‘.’ between the 130 and the 00.

Could you help me with this too?

Thank you

Similar to the first, we take a look at the site HTML for that page and see a data-hook for product-item-price-to-pay

You can either add a second script:

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const style = document.createElement('style');

    style.textContent = `
      [data-hook="product-item-price-to-pay"] {
        display: inline-flex !important;
        align-items: flex-start !important;
        gap: 0.02em !important;
      }

      [data-hook="product-item-price-to-pay"] .price-cents {
        font-size: 0.55em !important;
        line-height: 1 !important;
        margin-top: 0.15em !important;
      }
    `;

    document.head.appendChild(style);

    function formatPrice(priceEl) {
      if (!priceEl || priceEl.dataset.priceFormatted === 'true') return;

      const rawPrice =
        priceEl.getAttribute('data-wix-price') ||
        priceEl.textContent.trim();

      const match = rawPrice.match(/^([^0-9]*)(\d+)([.,](\d{2}))?$/);

      if (!match) return;

      const currency = match[1] || '';
      const pounds = match[2];
      const cents = match[4];

      priceEl.innerHTML = `
        <span class="price-currency">${currency}</span>
        <span class="price-main">${pounds}</span>
        ${cents ? `<sup class="price-cents">${cents}</sup>` : ''}
      `;

      priceEl.dataset.priceFormatted = 'true';
    }

    function formatAllPrices() {
      document
        .querySelectorAll('[data-hook="product-item-price-to-pay"]')
        .forEach(formatPrice);
    }

    formatAllPrices();

    const observer = new MutationObserver(formatAllPrices);

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  });
</script>

Or replace the first one with a “combine script” that covers both places and adds the . back for you :slight_smile:

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const priceSelectors = [
      '[data-hook="formatted-primary-price"]',
      '[data-hook="product-item-price-to-pay"]'
    ];

    const style = document.createElement('style');

    style.textContent = `
      ${priceSelectors.join(', ')} {
        display: inline-flex !important;
        align-items: flex-start !important;
        gap: 0.02em !important;
      }

      ${priceSelectors.map((selector) => `${selector} .price-cents`).join(', ')} {
        font-size: 0.55em !important;
        line-height: 1 !important;
        margin-top: 0.15em !important;
      }
    `;

    document.head.appendChild(style);

    function formatPrice(priceEl) {
      if (!priceEl || priceEl.dataset.priceFormatted === 'true') return;

      const rawPrice =
        priceEl.getAttribute('data-wix-price') ||
        priceEl.textContent.trim();

      const match = rawPrice.match(/^([^0-9]*)(\d+)([.,](\d{2}))?$/);

      if (!match) return;

      const currency = match[1] || '';
      const mainPrice = match[2];
      const decimal = match[3]?.[0] || '.';
      const cents = match[4];

      priceEl.innerHTML = `
        <span class="price-currency">${currency}</span>
        <span class="price-main">${mainPrice}</span>
        ${cents ? `<sup class="price-cents">${decimal}${cents}</sup>` : ''}
      `;

      priceEl.dataset.priceFormatted = 'true';
    }

    function formatAllPrices() {
      document
        .querySelectorAll(priceSelectors.join(', '))
        .forEach(formatPrice);
    }

    formatAllPrices();

    const observer = new MutationObserver(formatAllPrices);

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  });
</script>

Thank you so much. I’m adding the combined html script now.

It works!! Thank you Noah!

Amazing! Glad we could help :flexed_biceps: