Проекти

Shopify EUR Цена: Динамично добавяне под BGN с фиксиран курс

29 юли 2025 г.

Накратко за проекта

Онлайн магазинът Vicious Intent искаше всички цени в лева да показват приблизителна цена в евро точно под тях. Валутният курс трябваше да бъде фиксиран на 1.95583 (BGN към EUR), а скриптът да работи на всички типове страници — продуктови, количка, бърз преглед.

Ключови подобрения

  • Фиксиран курс: Не се използва външен API при зареждане, за бързина и стабилност.
  • Мощен MutationObserver: Засича динамично добавяне на елементи и инжектира евро цена в реално време.
  • Мулти-селекторно покритие: Скриптът обхваща над 9 различни класа за цена, характерни за темата Kalles.
  • Автоматично позициониране: Евро цената се добавя точно до лева, без да се нарушава дизайна.
  • Минимална визуална намеса: Евро цената е с по-сив шрифт и с 5% по-малък размер, без да доминира визуално.

Използвани технологии

  • Vanilla JavaScript – за динамично откриване и вграждане на евро стойностите.
  • MutationObserver – за следене на DOM промени и автоматично вграждане в динамично заредени елементи.
  • Shopify Liquid + Kalles v2.7.0 – интеграция със съществуващата тема.

Предизвикателства

Темата Kalles използва JavaScript рендериране за части от съдържанието — включително някои ценови елементи, които се появяват само при действие от потребителя (напр. добавяне в количката, quick view). Това прави невъзможно еднократно вграждане на евро цената само при DOMContentLoaded.

Допълнително предизвикателство беше, че част от елементите се рендерират в сянка (Shadow DOM) или задействат повторно рендериране при mouseover или scroll. Някои елементи, като span.price.dib.mb__5, визуализираха промяната едва след отваряне на инспектора. Затова внедрихме MutationObserver с повторно валидиране.

Използван JavaScript код

Html
<script>
document.addEventListener("DOMContentLoaded", function () {
  const selectors = [
    'span.price.dib.mb__5',
    'p#price_ppr.price_range',
    'div.cart_price',
    'strong._19gi7yt0._19gi7yt12._19gi7yt1a._19gi7yt1l',
    'strong._19gi7yt0._19gi7ytk._19gi7ytj._1fragemp5._19gi7yt12._19gi7yt1a._19gi7yt1l.notranslate',
    'span._19gi7yt0._19gi7yt12._19gi7yt1a._19gi7yt1g.notranslate',
    '.cart_tot_price',
    '.totals__subtotal-value',
    '.cart__subtotal .money'
  ];

  const rate = 1.95583;

  function applyConversions() {
    const elements = document.querySelectorAll(selectors.join(','));
    elements.forEach((el) => {
      if (el.querySelector('.euro-price')) return;
      let prices = el.textContent.match(/[\d.,]+/g);
      let priceBGN = parseFloat((prices ? prices[prices.length - 1] : '0').replace(',', '.'));
      if (!isNaN(priceBGN)) {
        let priceEUR = (Math.round((priceBGN / rate) * 100) / 100).toFixed(2);
        el.insertAdjacentHTML('beforeend', ` <span class="euro-price" style="display:inline; font-size:0.85em; color:gray;">(${priceEUR} €)</span>`);
      }
    });
  }

  applyConversions();
  const observer = new MutationObserver(applyConversions);
  observer.observe(document.body, { childList: true, subtree: true });
});
</script>

Резултат

Всички визуализирани цени вече показват евро стойност в реално време – включително в количката, quick view и продуктовите страници. Дизайнът остана непроменен, а добавянето не влияе на скоростта на сайта.

Ограничения

Въпреки прецизната имплементация, трябва да се отбележи, че поради естеството на динамичното зареждане на съдържание в Shopify, не всички ценови елементи могат да бъдат обработени на 100%. Например, съдържание, заредено през iframe или в Shadow DOM, не подлежи на стандартна обработка. В такива случаи е възможно евро цената да не се покаже, ако елементът не бъде открит в DOM.

На финала

Благодарение на внимателно изградения JavaScript и адаптацията към темата Kalles, проектът на ViciousIntent постигна желаната функционалност: динамична, точна и визуално ненатрапчива евро цена до всяка стойност в лева. Решението може лесно да се прехвърли в други Shopify магазини с минимални корекции.