301 Moved Permanently, istenen kaynağın kalıcı olarak yeni bir URL'ye taşındığı anlamına gelir. Gelecekteki tüm istekler yeni adresi kullanmalıdır.
Tarayıcı kullanıcıyı otomatik olarak yeni adrese yönlendirecek ve arama motorları dizinlerini güncelleyecektir.
GET / HTTP/1.1 Host: taffy.com Accept: */* User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
<!doctype html> <html class="" lang="en"> <head> <link rel="preconnect dns-prefetch" href="https://api.config-security.com/" crossorigin> <link rel="preconnect dns-prefetch" href="https://conf.config-security.com/" crossorigin> <link rel="preconnect dns-prefetch" href="https://triplewhale-pixel.web.app/" crossorigin> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="theme-color" content="#807db6"> <link rel="canonical" href="https://taffy.com/"> <link rel="preconnect" href="https://cdn.shopify.com" crossorigin> <link rel="preconnect" href="https://fonts.shopifycdn.com" crossorigin><link rel="icon" type="image/png" href="//taffy.com/cdn/shop/files/badge_logo_taffy_1.png?crop=center&height=32&v=1712070168&width=32"><title> Taffy.com | 40+ Mouth-Watering Flavors | Authentic Saltwater Taffy </title> <meta name="description" content="Welcome to the home of the most authentic, hand-crafted salt water taffy. Using the same family recipe since 1948, we've curated 30+ gourmet flavors unlike any taffy you've ever tasted. Treat yourself to our Bundles or Sampler Packs, or grab an elegant Gift Box for your loved one - always delivered fast & fresh."> <meta property="og:site_name" content="Taffy.com"> <meta property="og:url" content="https://taffy.com/"> <meta property="og:title" content="Taffy.com | 40+ Mouth-Watering Flavors | Authentic Saltwater Taffy"> <meta property="og:type" content="website"> <meta property="og:description" content="Welcome to the home of the most authentic, hand-crafted salt water taffy. Using the same family recipe since 1948, we've curated 30+ gourmet flavors unlike any taffy you've ever tasted. Treat yourself to our Bundles or Sampler Packs, or grab an elegant Gift Box for your loved one - always delivered fast & fresh."><meta property="og:image" content="http://taffy.com/cdn/shop/files/Frame_889.png?v=1712337777"> <meta property="og:image:secure_url" content="https://taffy.com/cdn/shop/files/Frame_889.png?v=1712337777"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="628"><meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Taffy.com | 40+ Mouth-Watering Flavors | Authentic Saltwater Taffy"> <meta name="twitter:description" content="Welcome to the home of the most authentic, hand-crafted salt water taffy. Using the same family recipe since 1948, we've curated 30+ gourmet flavors unlike any taffy you've ever tasted. Treat yourself to our Bundles or Sampler Packs, or grab an elegant Gift Box for your loved one - always delivered fast & fresh."> <!-- RR GTM --> <script>!function(){"use strict";function l(e){for(var t=e,r=0,n=document.cookie.split(";");r<n.length;r++){var o=n[r].split("=");if(o[0].trim()===t)return o[1]}}function s(e){return localStorage.getItem(e)}function u(e){return window[e]}function d(e,t){e=document.querySelector(e);return t?null==e?void 0:e.getAttribute(t):null==e?void 0:e.textContent}var e=window,t=document,r="script",n="dataLayer",o="TTZRC24",a="https://ss.taffy.com",i="",c="pqbftcll",E="cookie",I=["_y", "_shopify_y"],v="",g=!1;try{var g=!!E&&(m=navigator.userAgent,!!(m=new RegExp("Version/([0-9._]+)(.*Mobile)?.*Safari.*").exec(m)))&&16.4<=parseFloat(m[1]),A="stapeUserId"===E,f=g&&!A?function(e,t,r){void 0===t&&(t="");var n={cookie:l,localStorage:s,jsVariable:u,cssSelector:d},t=Array.isArray(t)?t:[t];if(e&&n[e])for(var o=n[e],a=0,i=t;a<i.length;a++){var c=i[a],c=r?o(c,r):o(c);if(c)return c}else console.warn("invalid uid source",e)}(E,I,v):void 0;g=g&&(!!f||A)}catch(e){console.error(e)}var m=e,E=(m[n]=m[n]||[],m[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"}),t.getElementsByTagName(r)[0]),I="dataLayer"===n?"":"&l="+n,v=f?"&bi="+encodeURIComponent(f):"",A=t.createElement(r),e=g?"kp"+c:c,n=!g&&i?i:a;A.async=!0,A.src=n+"/"+e+".js?st="+o+I+v,null!=(f=E.parentNode)&&f.insertBefore(A,E)}();</script> <!-- RR GTM --> <script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script><meta name="facebook-domain-verification" content="ppjpwzrf22scajbfecmv3zccj2tmh1"> <meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/55788601438/digital_wallets/dialog"> <meta name="shopify-checkout-api-token" content="fcc49c68cd33ed19c357039fdb284480"> <meta id="in-context-paypal-metadata" data-shop-id="55788601438" data-venmo-supported="true" data-environment="production" data-locale="en_US" data-paypal-v4="true" data-currency="USD"> <script async="async" src="/checkouts/internal/preloads.js?locale=en-US"></script> <link rel="preconnect" href="https://shop.app" crossorigin="anonymous"> <script async="async" src="https://shop.app/checkouts/internal/preloads.js?locale=en-US&shop_id=55788601438" crossorigin="anonymous"></script> <script id="apple-pay-shop-capabilities" type="application/json">{"shopId":55788601438,"countryCode":"US","currencyCode":"USD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/55788601438","merchantName":"Taffy.com","requiredBillingContactFields":["postalAddress","email"],"requiredShippingContactFields":["postalAddress","email"],"shippingType":"shipping","supportedNetworks":["visa","masterCard","amex","discover","elo","jcb"],"total":{"type":"pending","label":"Taffy.com","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script> <script id="shopify-features" type="application/json">{"accessToken":"fcc49c68cd33ed19c357039fdb284480","betas":["rich-media-storefront-analytics"],"domain":"taffy.com","predictiveSearch":true,"shopId":55788601438,"locale":"en"}</script> <script>var Shopify = Shopify || {}; Shopify.shop = "taffy-goat-shop.myshopify.com"; Shopify.locale = "en"; Shopify.currency = {"active":"USD","rate":"1.0"}; Shopify.country = "US"; Shopify.theme = {"name":"taffy\/main","id":127505694814,"schema_name":"caramels_custom","schema_version":"1.0.0","theme_store_id":null,"role":"main"}; Shopify.theme.handle = "null"; Shopify.theme.style = {"id":null,"handle":null}; Shopify.cdnHost = "taffy.com/cdn"; Shopify.routes = Shopify.routes || {}; Shopify.routes.root = "/";</script> <script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script> <script>!function(o){function n(){var o=[];function n(){o.push(Array.prototype.slice.apply(arguments))}return n.q=o,n}var t=o.Shopify=o.Shopify||{};t.loadFeatures=n(),t.autoloadFeatures=n()}(window);</script> <script>window.ShopifyPay = window.ShopifyPay || {}; window.ShopifyPay.apiHost = "shop.app\/pay";</script> <script id="shop-js-analytics" type="application/json">{"pageType":"index"}</script> <script> window.Shopify = window.Shopify || {}; if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; window.Shopify.featureAssets['shop-js'] = {"init-fed-cm":["modules/v2/client.init-fed-cm_D_UxnkVb.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"init-windoid":["modules/v2/client.init-windoid_Cc-qVL2z.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"shop-button":["modules/v2/client.shop-button_Cls8fA5R.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"init-shop-email-lookup-coordinator":["modules/v2/client.init-shop-email-lookup-coordinator_B2bcHbF0.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"pay-button":["modules/v2/client.pay-button_DWJZkEJ7.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"shop-toast-manager":["modules/v2/client.shop-toast-manager_C97RHVS7.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js"],"avatar":["modules/v2/client.avatar_BTnouDA3.en.esm.js"],"init-shop-for-new-customer-accounts":["modules/v2/client.init-shop-for-new-customer-accounts_N-W60_Qf.en.esm.js","modules/v2/client.shop-login-button_tQyWXqsV.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"shop-login-button":["modules/v2/client.shop-login-button_tQyWXqsV.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"shop-cash-offers":["modules/v2/client.shop-cash-offers_-zS8l3L2.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"checkout-modal":["modules/v2/client.checkout-modal_B3vUumcK.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"init-customer-accounts-sign-up":["modules/v2/client.init-customer-accounts-sign-up_CEaN7ODi.en.esm.js","modules/v2/client.shop-login-button_tQyWXqsV.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"init-customer-accounts":["modules/v2/client.init-customer-accounts_DXe3zqOZ.en.esm.js","modules/v2/client.shop-login-button_tQyWXqsV.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"shop-follow-button":["modules/v2/client.shop-follow-button_CtVAwMQo.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"lead-capture":["modules/v2/client.lead-capture_CR6ElJGq.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"],"payment-terms":["modules/v2/client.payment-terms_CCB9cVzN.en.esm.js","modules/v2/chunk.common_DX4hvK5k.esm.js","modules/v2/chunk.modal_XXU5RCt-.esm.js"]}; </script> <script>(function() { function asyncLoad() { var urls = ["https:\/\/config.gorgias.chat\/bundle-loader\/01HTD17YDT5FCTRBZQBDWD20AA?source=shopify1click\u0026shop=taffy-goat-shop.myshopify.com","https:\/\/bundle.dyn-rev.app\/loader.js?g_cvt_id=67c051f3-7ac8-4573-8c77-d41352bea083\u0026shop=taffy-goat-shop.myshopify.com","https:\/\/cdn.attn.tv\/taffy\/dtag.js?shop=taffy-goat-shop.myshopify.com","https:\/\/api.socialsnowball.io\/js\/referral.js?shop=taffy-goat-shop.myshopify.com","https:\/\/cdn.rebuyengine.com\/onsite\/js\/rebuy.js?shop=taffy-goat-shop.myshopify.com"]; for (var i = 0; i < urls.length; i++) { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = urls[i]; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); } }; if(window.attachEvent) { window.attachEvent('onload', asyncLoad); } else { window.addEventListener('load', asyncLoad, false); } })();</script> <script id="__st">var __st={"a":55788601438,"offset":-14400,"reqid":"60ed604a-27ad-43aa-a2df-0955d261fb46-1747945624","pageurl":"taffy.com\/","u":"9d30e32459f2","p":"home"};</script> <script>window.ShopifyPaypalV4VisibilityTracking = true;</script> <script id="captcha-bootstrap">!function(){'use strict';const t='contact',e='account',n='new_comment',o=[[t,t],['blogs',n],['comments',n],[t,'customer']],c=[[e,'customer_login'],[e,'guest_login'],[e,'recover_customer_password'],[e,'create_customer']],r=t=>t.map((([t,e])=>`form[action*='/${t}']:not([data-nocaptcha='true']) input[name='form_type'][value='${e}']`)).join(','),a=t=>()=>t?[...document.querySelectorAll(t)].map((t=>t.form)):[];function s(){const t=[...o],e=r(t);return a(e)}const i='password',u='form_key',d=['recaptcha-v3-token','g-recaptcha-response','h-captcha-response',i],f=()=>{try{return window.sessionStorage}catch{return}},m='__shopify_v',_=t=>t.elements[u];function p(t,e,n=!1){try{const o=window.sessionStorage,c=JSON.parse(o.getItem(e)),{data:r}=function(t){const{data:e,action:n}=t;return t[m]||n?{data:e,action:n}:{data:t,action:n}}(c);for(const[e,n]of Object.entries(r))t.elements[e]&&(t.elements[e].value=n);n&&o.removeItem(e)}catch(o){console.error('form repopulation failed',{error:o})}}const l='form_type',E='cptcha';function T(t){t.dataset[E]=!0}const w=window,h=w.document,L='Shopify',v='ce_forms',y='captcha';let A=!1;((t,e)=>{const n=(g='f06e6c50-85a8-45c8-87d0-21a2b65856fe',I='https://cdn.shopify.com/shopifycloud/storefront-forms-hcaptcha/ce_storefront_forms_captcha_hcaptcha.v1.5.2.iife.js',D={infoText:'Protected by hCaptcha',privacyText:'Privacy',termsText:'Terms'},(t,e,n)=>{const o=w[L][v],c=o.bindForm;if(c)return c(t,g,e,D).then(n);var r;o.q.push([[t,g,e,D],n]),r=I,A||(h.body.append(Object.assign(h.createElement('script'),{id:'captcha-provider',async:!0,src:r})),A=!0)});var g,I,D;w[L]=w[L]||{},w[L][v]=w[L][v]||{},w[L][v].q=[],w[L][y]=w[L][y]||{},w[L][y].protect=function(t,e){n(t,void 0,e),T(t)},Object.freeze(w[L][y]),function(t,e,n,w,h,L){const[v,y,A,g]=function(t,e,n){const i=e?o:[],u=t?c:[],d=[...i,...u],f=r(d),m=r(i),_=r(d.filter((([t,e])=>n.includes(e))));return[a(f),a(m),a(_),s()]}(w,h,L),I=t=>{const e=t.target;return e instanceof HTMLFormElement?e:e&&e.form},D=t=>v().includes(t);t.addEventListener('submit',(t=>{const e=I(t);if(!e)return;const n=D(e)&&!e.dataset.hcaptchaBound&&!e.dataset.recaptchaBound,o=_(e),c=g().includes(e)&&(!o||!o.value);(n||c)&&t.preventDefault(),c&&!n&&(function(t){try{if(!f())return;!function(t){const e=f();if(!e)return;const n=_(t);if(!n)return;const o=n.value;o&&e.removeItem(o)}(t);const e=Array.from(Array(32),(()=>Math.random().toString(36)[2])).join('');!function(t,e){_(t)||t.append(Object.assign(document.createElement('input'),{type:'hidden',name:u})),t.elements[u].value=e}(t,e),function(t,e){const n=f();if(!n)return;const o=[...t.querySelectorAll(`input[type='${i}']`)].map((({name:t})=>t)),c=[...d,...o],r={};for(const[a,s]of new FormData(t).entries())c.includes(a)||(r[a]=s);n.setItem(e,JSON.stringify({[m]:1,action:t.action,data:r}))}(t,e)}catch(e){console.error('failed to persist form',e)}}(e),e.submit())}));const S=(t,e)=>{t&&!t.dataset[E]&&(n(t,e.some((e=>e===t))),T(t))};for(const o of['focusin','change'])t.addEventListener(o,(t=>{const e=I(t);D(e)&&S(e,y())}));const B=e.get('form_key'),M=e.get(l),P=B&&M;t.addEventListener('DOMContentLoaded',(()=>{const t=y();if(P)for(const e of t)e.elements[l].value===M&&p(e,B);[...new Set([...A(),...v().filter((t=>'true'===t.dataset.shopifyCaptcha))])].forEach((e=>S(e,t)))}))}(h,new URLSearchParams(w.location.search),n,t,e,['guest_login'])})(!0,!0)}();</script> <script integrity="sha256-w1TMG8bx+vw+BuOfT7Dh2avfdjByyjlNYGyp9vJB5oo=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//taffy.com/cdn/shopifycloud/shopify/assets/storefront/load_feature-c354cc1bc6f1fafc3e06e39f4fb0e1d9abdf763072ca394d606ca9f6f241e68a.js" crossorigin="anonymous"></script> <script crossorigin="anonymous" defer="defer" src="//taffy.com/cdn/shopifycloud/shopify/assets/shopify_pay/storefront-80e528be853eac23af2454534897ca9536b1d3d04aa043b042f34879a3c111c8.js?v=20220906"></script> <script data-source-attribution="shopify.dynamic_checkout.dynamic.init">var Shopify=Shopify||{};Shopify.PaymentButton=Shopify.PaymentButton||{isStorefrontPortableWallets:!0,init:function(){window.Shopify.PaymentButton.init=function(){};var t=document.createElement("script");t.src="https://taffy.com/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}}; </script> <script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> function portableWalletsHideBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.add("hidden"),t.setAttribute("aria-hidden","true"),n.removeEventListener("click",e))}function portableWalletsShowBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.remove("hidden"),t.removeAttribute("aria-hidden"),n.addEventListener("click",e))}window.Shopify?.PaymentButton&&(window.Shopify.PaymentButton.hideBuyerConsent=portableWalletsHideBuyerConsent,window.Shopify.PaymentButton.showBuyerConsent=portableWalletsShowBuyerConsent); </script> <script data-source-attribution="shopify.dynamic_checkout.cart.bootstrap">document.addEventListener("DOMContentLoaded",(function(){function t(){return document.querySelector("shopify-accelerated-checkout-cart, shopify-accelerated-checkout")}if(t())Shopify.PaymentButton.init();else{new MutationObserver((function(e,n){t()&&(Shopify.PaymentButton.init(),n.disconnect())})).observe(document.body,{childList:!0,subtree:!0})}})); </script> <link rel="stylesheet" media="screen" href="https://taffy.com/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous"> <style id="shopify-accelerated-checkout-cart"> #shopify-buyer-consent { margin-top: 1em; display: inline-block; width: 100%; } #shopify-buyer-consent.hidden { display: none; } #shopify-subscription-policy-button { background: none; border: none; padding: 0; text-decoration: underline; font-size: inherit; cursor: pointer; } #shopify-subscription-policy-button::before { box-shadow: none; } </style> <script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script> <link rel="stylesheet" href="https://use.typekit.net/gzc2zho.css"> <link href="//taffy.com/cdn/shop/t/40/assets/vendor-bootstrap.min.css?v=35469434068056780111727379882" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/vendor-splide.min.css?v=44329677166622589231727379880" rel="stylesheet" media="print" onload="this.media='all'"> <link href="//taffy.com/cdn/shop/t/40/assets/vendor-animate.min.css?v=117445339244174673761727379882" rel="stylesheet" media="print" onload="this.media='all'"> <link href="//taffy.com/cdn/shop/t/40/assets/vendor-air-datepicker-min.css?v=65215714605950174361741296956" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/variables.css?v=156474454255748562551741296961" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/base.css?v=18974300421427404701745517619" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/general.css?v=151531408879544247171732221939" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/sections.css?v=178496526557316423401744135046" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/collection.css?v=131685195195290293891741296955" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/product.css?v=70837668728224017991734716881" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/cart.css?v=112980650948708545301741980747" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/tight-grid-v3.css?v=147157646760116505381743618730" rel="stylesheet"> <link href="//taffy.com/cdn/shop/t/40/assets/bfcm-product-card.css?v=146908376144841378131744381758" rel="stylesheet"> <script type="text/javascript"> (function e(){var e=document.createElement("script");e.type="text/javascript",e.async=true,e.src="//staticw2.yotpo.com/lmfoJ3PoGKFS6XRnodUe6Un3QwFBErn3pUebqVTi/widget.js";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})(); </script> <script> Shopify.money_format = "${{amount}}" window.theme = { product: { addToCart: 'ADD TO CART', addedToCart: '✓ ADDED', soldOut: 'Sold out', unavailable: 'Unavailable', priceRegular: 'Regular price', priceFrom: 'From', priceSale: 'Sale price', save: 'Save', } } </script> <link rel="stylesheet" href="https://use.typekit.net/nms7ndm.css"> <script src="//taffy.com/cdn/shop/t/40/assets/vendor-bootstrap.bundle.min.js?v=63956723121591917741727379881" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/vendor-splide.min.js?v=73338738898036601811727379882" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/vendor-splide-scroll.min.js?v=157408630528621081061727379882" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/vendor-simpleParallax.min.js?v=130929562465468186701727379882" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/vendor-air-datepicker-min.js?v=117484864137537845791727379881" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/discounts.js?v=70579789089605924831743524212" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/base.js?v=69385079650765685361727379881" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/general.js?v=80627125051987163441743524209" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/search.js?v=113183301928034813311742572434" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/sections.js?v=132877995405652298781727379881" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/collection.js?v=85023640591249271791727379882" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/product.js?v=51387566512800352461743524209" defer></script> <script src="//taffy.com/cdn/shop/t/40/assets/cart.js?v=77180269474297432071742828338" defer></script> <meta name="google-site-verification" content="weoeZbcDaOBjzoJVgYquZiRwOKnMv2jxH1I-YyNyytM"> <meta name="facebook-domain-verification" content="wgft1ealkcwszq99m40abt3v3epyfw"> <script type="text/javascript"> (function(c,l,a,r,i,t,y){ c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); })(window, document, "clarity", "script", "ltkeuqrzqk"); </script> <!-- intelligems script start --> <script type='text/javascript'> var script = document.createElement('script'); script.src = 'https://xp2023-pix.s3.amazonaws.com/px_XWBiZ.js'; document.getElementsByTagName('head')[0].appendChild(script); </script> <script> window.Shopify = window.Shopify || {theme: {id: 127505694814, role: 'main' } }; window._template = { directory: "", name: "index", suffix: "" }; </script> <script type="module" blocking="render" fetchpriority="high" src="https://cdn.intelligems.io/esm/93775c7bd98c/bundle.js"></script> <!-- intelligems script end --> <!-- heatmap.com snippet --> <script> (function() { var _heatmap_paq = window._heatmap_paq || []; var heatUrl = window.heatUrl = "https://dashboard.heatmap.com/"; window.heatClientId = "3253"; function heatLoader(url, item) { if(typeof handleSinglePagedWebsite !== 'undefined' && item == 'prep') return true; var s = document.createElement("script"); s.type = "text/javascript"; s.src = url; s.async = false; s.defer = true; document.head.appendChild(s); } heatLoader(heatUrl+"preprocessor.min.js?sid=3253", "prep"); setTimeout(function() { if(typeof _heatmap_paq !== "object" || _heatmap_paq.length == 0) { _heatmap_paq.push(["setTrackerUrl", heatUrl+"heatmap.php"]); heatLoader(heatUrl+"heatmap-light.min.js?sid=3253", "heat"); } }, 1000); })(); </script> <!-- End heatmap.com snippet Code --> <!-- BEGIN app block: shopify://apps/klaviyo-email-marketing-sms/blocks/klaviyo-onsite-embed/2632fe16-c075-4321-a88b-50b567f42507 --> <script async src="https://static.klaviyo.com/onsite/js/RAncp5/klaviyo.js?company_id=RAncp5"></script> <script>!function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}();</script> <script> window.klaviyoReviewsProductDesignMode = false </script> <!-- END app block --><!-- BEGIN app block: shopify://apps/yotpo-product-photo-reviews/blocks/settings/eb7dfd7d-db44-4334-bc49-c893b51b36cf --> <script type="text/javascript" src="https://cdn-widgetsrepository.yotpo.com/v1/loader/lmfoJ3PoGKFS6XRnodUe6Un3QwFBErn3pUebqVTi?languageCode=en" async></script> <!-- END app block --><!-- BEGIN app block: shopify://apps/triplewhale/blocks/triple_pixel_snippet/483d496b-3f1a-4609-aea7-8eee3b6b7a2a --><link rel='preconnect dns-prefetch' href='https://api.config-security.com/' crossorigin /> <link rel='preconnect dns-prefetch' href='https://conf.config-security.com/' crossorigin /> <script> /* >> TriplePixel :: start*/ window.TriplePixelData={TripleName:"taffy-goat-shop.myshopify.com",ver:"2.16",plat:"SHOPIFY",isHeadless:false,src:'SHOPIFY_EXT',product:{id:"",name:``,price:"",variant:""},search:"",collection:"",cart:"",template:"index"},function(W,H,A,L,E,_,B,N){function O(U,T,P,H,R){void 0===R&&(R=!1),H=new XMLHttpRequest,P?(H.open("POST",U,!0),H.setRequestHeader("Content-Type","text/plain")):H.open("GET",U,!0),H.send(JSON.stringify(P||{})),H.onreadystatechange=function(){4===H.readyState&&200===H.status?(R=H.responseText,U.includes("/first")?eval(R):P||(N[B]=R)):(299<H.status||H.status<200)&&T&&!R&&(R=!0,O(U,T-1,P))}}if(N=window,!N[H+"sn"]){N[H+"sn"]=1,L=function(){return Date.now().toString(36)+"_"+Math.random().toString(36)};try{A.setItem(H,1+(0|A.getItem(H)||0)),(E=JSON.parse(A.getItem(H+"U")||"[]")).push({u:location.href,r:document.referrer,t:Date.now(),id:L()}),A.setItem(H+"U",JSON.stringify(E))}catch(e){}var i,m,p;A.getItem('"!nC`')||(_=A,A=N,A[H]||(E=A[H]=function(t,e,i){return void 0===i&&(i=[]),"State"==t?E.s:(W=L(),(E._q=E._q||[]).push([W,t,e].concat(i)),W)},E.s="Installed",E._q=[],E.ch=W,B="configSecurityConfModel",N[B]=1,O("https://conf.config-security.com/model",5),i=L(),m=A[atob("c2NyZWVu")],_.setItem("di_pmt_wt",i),p={id:i,action:"profile",avatar:_.getItem("auth-security_rand_salt_"),time:m[atob("d2lkdGg=")]+":"+m[atob("aGVpZ2h0")],host:A.TriplePixelData.TripleName,plat:A.TriplePixelData.plat,url:window.location.href.slice(0,500),ref:document.referrer,ver:A.TriplePixelData.ver},O("https://api.config-security.com/event",5,p),O("https://api.config-security.com/first?host=".concat(p.host,"&plat=").concat(p.plat),5)))}}("","TriplePixel",localStorage); /* << TriplePixel :: end*/ </script> <!-- END app block --><!-- BEGIN app block: shopify://apps/attentive/blocks/attn-tag/8df62c72-8fe4-407e-a5b3-72132be30a0d --><script type="text/javascript" src="https://cdn.attn.tv/taffy/dtag.js?source=app-embed" defer="defer"></script> <!-- END app block --><link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch"> <script>(function(){if ("sendBeacon" in navigator && "performance" in window) {var session_token = document.cookie.match(/_shopify_s=([^;]*)/);function handle_abandonment_event(e) {var entries = performance.getEntries().filter(function(entry) {return /monorail-edge.shopifysvc.com/.test(entry.name);});if (!window.abandonment_tracked && entries.length === 0) {window.abandonment_tracked = true;var currentMs = Date.now();var navigation_start = performance.timing.navigationStart;var payload = {shop_id: 55788601438,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token: session_token && session_token.length === 2 ? session_token[1] : "",page_type: "index"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script> <script id="web-pixels-manager-setup">(function e(e,d,r,n,o,i){if(void 0===i&&(i={}),!Boolean(null===(t=null===(a=window.Shopify)||void 0===a?void 0:a.analytics)||void 0===t?void 0:t.replayQueue)){var a,t;window.Shopify=window.Shopify||{};var s=window.Shopify;s.analytics=s.analytics||{};var l=s.analytics;l.replayQueue=[],l.publish=function(e,d,r){return l.replayQueue.push([e,d,r]),!0};try{self.performance.mark("wpm:start")}catch(e){}var u=function(){var e={modern:/Edge?\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(9{2}|\d{3,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(15\.\d+|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9{2}|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]\d+|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](13[1-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Android.+Firefox\/(13[2-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(13[1-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/([2-9]\d|\d{3,})\.\d+/,legacy:/Edge?\/(1[6-9]|[2-9]\d|\d{3,})\.\d+(\.\d+|)|Firefox\/(5[4-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)|Chrom(ium|e)\/(5[1-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)([\d.]+$|.*Safari\/(?![\d.]+ Edge\/[\d.]+$))|(Maci|X1{2}).+ Version\/(10\.\d+|(1[1-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(3[89]|[4-9]\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(10[._]\d+|(1[1-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](13[1-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(13[2-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(13[1-9]|1[4-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(15\.([5-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(5\.\d+|([6-9]|\d{2,})\.\d+)|Android.+MQ{2}Browser\/(14(\.(9|\d{2,})|)|(1[5-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/},d=e.modern,r=e.legacy,n=navigator.userAgent;return n.match(d)?"modern":n.match(r)?"legacy":"unknown"}(),c="modern"===u?"modern":"legacy",f=(null!=o?o:{modern:"",legacy:""})[c],m=function(e){return[e.baseUrl,"/wpm","/b",e.hashVersion,"modern"===e.buildTarget?"m":"l",".js"].join("")}({baseUrl:r,hashVersion:n,buildTarget:c}),p=function(e){var d=e.version,r=e.bundleTarget,n=e.surface,o=e.pageUrl,i=e.monorailEndpoint;return{emit:function(e){var a=e.status,t=e.errorMsg,s=(new Date).getTime(),l=JSON.stringify({metadata:{event_sent_at_ms:s},events:[{schema_id:"web_pixels_manager_load/3.1",payload:{version:d,bundle_target:r,page_url:o,status:a,surface:n,error_msg:t},metadata:{event_created_at_ms:s}}]});if(!i)return console&&console.warn&&console.warn("[Web Pixels Manager] No Monorail endpoint provided, skipping logging."),!1;try{return self.navigator.sendBeacon.bind(self.navigator)(i,l)}catch(e){}var u=new XMLHttpRequest;try{return u.open("POST",i,!0),u.setRequestHeader("Content-Type","text/plain"),u.send(l),!0}catch(e){return console&&console.warn&&console.warn("[Web Pixels Manager] Got an unhandled error while logging to Monorail."),!1}}}}({version:n,bundleTarget:u,surface:e.surface,pageUrl:self.location.href,monorailEndpoint:e.monorailEndpoint});try{i.browserTarget=u,function(e){var d=e.src,r=e.async,n=void 0===r||r,o=e.onload,i=e.onerror,a=e.sri,t=e.scriptDataAttributes,s=void 0===t?{}:t,l=document.createElement("script"),u=document.querySelector("head"),c=document.querySelector("body");if(l.async=n,l.src=d,a&&(l.integrity=a,l.crossOrigin="anonymous"),s)for(var f in s)if(Object.prototype.hasOwnProperty.call(s,f))try{l.dataset[f]=s[f]}catch(e){}if(o&&l.addEventListener("load",o),i&&l.addEventListener("error",i),u)u.appendChild(l);else{if(!c)throw new Error("Did not find a head or body element to append the script");c.appendChild(l)}}({src:m,async:!0,onload:function(){if(!function(){var e,d;return Boolean(null===(d=null===(e=window.Shopify)||void 0===e?void 0:e.analytics)||void 0===d?void 0:d.initialized)}()){var r=window.webPixelsManager.init(e)||void 0;if(r){d(r);var n=window.Shopify.analytics;n.replayQueue.forEach((function(e){var d=e[0],n=e[1],o=e[2];r.publishCustomEvent(d,n,o)})),n.replayQueue=[],n.publish=r.publishCustomEvent,n.visitor=r.visitor,n.initialized=!0}}},onerror:function(){return p.emit({status:"failed",errorMsg:"".concat(m," has failed to load")})},sri:function(e){var d=/^sha384-[A-Za-z0-9+/=]+$/;return"string"==typeof e&&d.test(e)}(f)?f:"",scriptDataAttributes:i}),p.emit({status:"loading"})}catch(e){p.emit({status:"failed",errorMsg:(null==e?void 0:e.message)||"Unknown error"})}}})({shopId: 55788601438,storefrontBaseUrl: "https://taffy.com",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://monorail-edge.shopifysvc.com/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: [],webPixelsConfigList: [{"id":"402292830","configuration":"{\"campaignID\":\"27816\",\"externalExecutionURL\":\"https://engine.saasler.com/api/v1/webhook_executions/e94e13e54fd65d51caaeb6feb906ec64\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"3b8e58a07075037c1919061bd3bc7989","type":"APP","apiClientId":3546795,"privacyPurposes":[]},{"id":"322666590","configuration":"{\"myshopifyDomain\":\"taffy-goat-shop.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"23b97d18e2aa74363140dc29c9284e87","type":"APP","apiClientId":2775569,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"]},{"id":"176685150","configuration":"{\"pixel_id\":\"25132242646422186\",\"pixel_type\":\"facebook_pixel\",\"metaapp_system_user_token\":\"-\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"8d894c63179843e74a9691414b5ad83d","type":"APP","apiClientId":2329312,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"]},{"id":"62292062","configuration":"{\"shopId\":\"taffy-goat-shop.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c450aafa71fd8ebee479d56f323c88c7","type":"APP","apiClientId":4845829,"privacyPurposes":["ANALYTICS"]},{"id":"59310174","configuration":"{\"shopId\":\"taffy-goat-shop.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"5f2d219fe6f30dc82b1d95f56fd436a9","type":"APP","apiClientId":2753413,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"]},{"id":"59244638","configuration":"{\"env\":\"prod\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"be81bfba2c4424cd7509042615c13479","type":"APP","apiClientId":3977633,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"]},{"id":"13959262","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"2","type":"CUSTOM","privacyPurposes":["SALE_OF_DATA"],"name":"RevenueRoll"},{"id":"16613470","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Canella Media Pixel [06.05.24]"},{"id":"62685278","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Heatmap.com"},{"id":"106791006","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"3","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"PCG | Shopify Customer Events"},{"id":"shopify-app-pixel","configuration":"{}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"0411","apiClientId":"shopify-pixel","type":"APP","privacyPurposes":["ANALYTICS","MARKETING"]},{"id":"shopify-custom-pixel","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"0411","apiClientId":"shopify-pixel","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"]}],isMerchantRequest: false,effectiveTopLevelDomain: "com",initData: {"shop":{"name":"Taffy.com","paymentSettings":{"currencyCode":"USD"},"myshopifyDomain":"taffy-goat-shop.myshopify.com","countryCode":"US","storefrontUrl":"https://taffy.com"},"customer":null,"cart":null,"checkout":null,"productVariants":[],"purchasingCompany":null},},function pageEvents(webPixelsManagerAPI) {webPixelsManagerAPI.publish("page_viewed", {});},"https://taffy.com/cdn","230b189fw3875b864p642644e6m74838f3a",{"modern":"","legacy":""},{"shopId":"55788601438","storefrontBaseUrl":"https://taffy.com","extensionBaseUrl":"https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[]","isMerchantRequest":"false","hashVersion":"230b189fw3875b864p642644e6m74838f3a"});</script><script> window.ShopifyAnalytics = window.ShopifyAnalytics || {}; window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; window.ShopifyAnalytics.meta.currency = 'USD'; var meta = {"page":{"pageType":"home"}}; for (var attr in meta) { window.ShopifyAnalytics.meta[attr] = meta[attr]; } </script> <script class="analytics"> (function () { var customDocumentWrite = function(content) { var jquery = null; if (window.jQuery) { jquery = window.jQuery; } else if (window.Checkout && window.Checkout.$) { jquery = window.Checkout.$; } if (jquery) { jquery('body').append(content); } }; var hasLoggedConversion = function(token) { if (token) { return document.cookie.indexOf('loggedConversion=' + token) !== -1; } return false; } var setCookieIfConversion = function(token) { if (token) { var twoMonthsFromNow = new Date(Date.now()); twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; } } var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; if (trekkie.integrations) { return; } trekkie.methods = [ 'identify', 'page', 'ready', 'track', 'trackForm', 'trackLink' ]; trekkie.factory = function(method) { return function() { var args = Array.prototype.slice.call(arguments); args.unshift(method); trekkie.push(args); return trekkie; }; }; for (var i = 0; i < trekkie.methods.length; i++) { var key = trekkie.methods[i]; trekkie[key] = trekkie.factory(key); } trekkie.load = function(config) { trekkie.config = config || {}; trekkie.config.initialDocumentCookie = document.cookie; var first = document.getElementsByTagName('script')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.onerror = function(e) { var scriptFallback = document.createElement('script'); scriptFallback.type = 'text/javascript'; scriptFallback.onerror = function(error) { var Monorail = { produce: function produce(monorailDomain, schemaId, payload) { var currentMs = new Date().getTime(); var event = { schema_id: schemaId, payload: payload, metadata: { event_created_at_ms: currentMs, event_sent_at_ms: currentMs } }; return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); }, sendRequest: function sendRequest(endpointUrl, payload) { // Try the sendBeacon API if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { var blobData = new window.Blob([payload], { type: 'text/plain' }); if (window.navigator.sendBeacon(endpointUrl, blobData)) { return true; } // sendBeacon was not successful } // XHR beacon var xhr = new XMLHttpRequest(); try { xhr.open('POST', endpointUrl); xhr.setRequestHeader('Content-Type', 'text/plain'); xhr.send(payload); } catch (e) { console.log(e); } return false; }, isIos12: function isIos12() { return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; } }; Monorail.produce('monorail-edge.shopifysvc.com', 'trekkie_storefront_load_errors/1.1', {shop_id: 55788601438, theme_id: 127505694814, app_name: "storefront", context_url: window.location.href, source_url: "//taffy.com/cdn/s/trekkie.storefront.fc89087661a0619ee61984dff12e5581bfee89c0.min.js"}); }; scriptFallback.async = true; scriptFallback.src = '//taffy.com/cdn/s/trekkie.storefront.fc89087661a0619ee61984dff12e5581bfee89c0.min.js'; first.parentNode.insertBefore(scriptFallback, first); }; script.async = true; script.src = '//taffy.com/cdn/s/trekkie.storefront.fc89087661a0619ee61984dff12e5581bfee89c0.min.js'; first.parentNode.insertBefore(script, first); }; trekkie.load( {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":55788601438,"isMerchantRequest":null,"themeId":127505694814,"themeCityHash":"7526539008192384398","contentLanguage":"en","currency":"USD"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain"},"Session Attribution":{},"S2S":{"facebookCapiEnabled":true,"source":"trekkie-storefront-renderer","apiClientId":580111}} ); var loaded = false; trekkie.ready(function() { if (loaded) return; loaded = true; window.ShopifyAnalytics.lib = window.trekkie; var originalDocumentWrite = document.write; document.write = customDocumentWrite; try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; document.write = originalDocumentWrite; window.ShopifyAnalytics.lib.page(null,{"pageType":"home","shopifyEmitted":true}); var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) var token = match? match[1]: undefined; if (!hasLoggedConversion(token)) { setCookieIfConversion(token); } }); var eventsListenerScript = document.createElement('script'); eventsListenerScript.async = true; eventsListenerScript.src = "//taffy.com/cdn/shopifycloud/shopify/assets/shop_events_listener-f55dd2979ec32029c7d9e0b454ab8b33f79c01ca039d17a6f5c9b95647564b19.js"; document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); })();</script> <script defer src="https://taffy.com/cdn/shopifycloud/perf-kit/shopify-perf-kit-1.6.2.min.js" data-application="storefront-renderer" data-shop-id="55788601438" data-render-region="gcp-europe-west1" data-page-type="index" data-theme-instance-id="127505694814" data-theme-name="caramels_custom" data-theme-version="1.0.0" data-monorail-region="shop_domain" data-resource-timing-sampling-rate="10" data-shs="true" ></script> </head> <body class="page-type-index template-suffix-"> <a class="visually-hidden-focusable" href="#main"> Skip to content </a> <div id="header-group" class="sticky-top"> <!-- BEGIN sections: header-group --> <div id="shopify-section-sections--15646727831646__marquee_KXgN8E" class="shopify-section shopify-section-group-header-group"> <style data-shopify> .marquee-link { text-decoration: none; } .marquee-link:hover { text-decoration: underline; } .goat-marquee__outer-container { display: flex; } .goat-shopping { width: 20%; display: flex; justify-content: center; align-items: center; position: relative; max-width: 300px; min-width: 250px; background-color: #FFFFFF; } .dropdown-content { display: none; position: absolute; top: 115%; right: -55%; background-color: white; border: 1px solid #000; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); z-index: 1000; width: 350px; border-radius: 6px; overflow: hidden; } .dropdown-item { display: flex; align-items: center; padding: 10px; text-decoration: none; color: black; font-size: 14px; border-bottom: 1px solid #eee; transition: background-color 0.3s ease; justify-content: space-between; cursor: pointer; } .dropdown-item:last-child { border-bottom: none; } .dropdown-item:hover { background-color: #f9f9f9; } .dropdown-logo { width: 150px; height: auto; } .goat-stores__dropdown-title { font-size: 14px; font-weight: bold; display: flex; justify-content: space-between; align-items: center; width: 80%; border: 0 !important; background-color: #FFFFFF; color: #7F7DB2; font-family: "Apparat"; } .dropdown-arrow { position: absolute; top: -10px; right: 20px; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-bottom: 10px solid white; z-index: 1; filter: drop-shadow(0px -1px 1px rgba(0, 0, 0, 0.1)); } .shop-link { border-radius: 100px; padding: 5px 10px; color: #FFFFFF; } @media only screen and (max-width: 749px) { .goat-shopping { display: none !important; } } </style> <script> document.addEventListener('DOMContentLoaded', () => { const sectionId = 'sections--15646727831646__marquee_KXgN8E'; const dropdownButton = document.querySelector(`#goat-shopping--${sectionId} .dropdown-button`); const dropdownContent = document.querySelector(`#goat-shopping--${sectionId} .dropdown-content`); if (dropdownButton && dropdownContent) { dropdownButton.addEventListener('click', () => { const isHidden = dropdownContent.style.display === 'none' || window.getComputedStyle(dropdownContent).display === 'none'; dropdownContent.style.display = isHidden ? 'block' : 'none'; }); document.addEventListener('click', (event) => { if (!dropdownButton.contains(event.target) && !dropdownContent.contains(event.target)) { dropdownContent.style.display = 'none'; } }); } }); </script> <div class="goat-marquee__outer-container"> <section id="goat-shopping--sections--15646727831646__marquee_KXgN8E" class="goat-shopping"> <button for="goat-stores__dropdown" class="goat-stores__dropdown-title dropdown-button"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" height="22" width="22"> <path fill="#7F7DB2" d="M10.5834 21.5867C16.4245 21.5867 21.1581 16.8468 21.1561 10.9999C21.1541 5.15296 16.4174 0.413086 10.5763 0.413086C4.73516 0.413086 0.00158896 5.15296 0.00354904 10.9999C0.00550913 16.8468 4.74226 21.5867 10.5834 21.5867Z"></path> <path fill="white" d="M14.7601 15.3969L15.8055 14.3526V7.07324H14.7601V15.3969Z"></path> <path fill="white" d="M10.5408 15.1322L12.0434 13.6327V13.2926L11.9664 13.2178L10.576 11.8267L9.18339 13.2178L9.11679 13.2843V13.7104L10.5408 15.1322Z"></path> <path fill="white" d="M11.7686 11.8402L11.9781 12.0279L12.8671 11.1428H12.8776H13.9229V10.8311V10.0469V8.94507H11.9384V10.4648L11.1647 11.237L11.7686 11.8402Z"></path> <path fill="white" d="M12.8784 4.52031V5.19832H11.1019V3.57544H10.0566V5.19832H8.28157V4.52031H7.23618V5.19832V6.24261H8.28157H12.8784H13.9238V5.19832V4.52031H12.8784Z"></path> <path fill="white" d="M5.35413 7.07324V14.3526L6.39951 15.3969V7.07324H5.35413Z"></path> <path fill="white" d="M13.9238 7.07324H7.23618V8.11529H10.0566V10.1314L10.5759 10.6457L11.1019 10.1202V8.11529H13.9238V7.07324Z"></path> <path fill="white" d="M8.28156 11.1428L9.18103 12.0391L9.98322 11.237L9.22069 10.4648V8.94507H7.23618V11.1428H8.28156Z"></path> <path fill="white" d="M9.11679 14.8916V18.0604L10.136 19.1286H10.1622V15.9359L9.11679 14.8916Z"></path> <path fill="white" d="M10.9977 15.859V19.1287H11.0239L12.0431 18.1106V14.814L10.9977 15.859Z"></path> <path fill="white" d="M12.8775 12.3104V17.2762L13.9229 16.2319V11.9792H13.209L12.8775 12.3104Z"></path> <path fill="white" d="M7.93884 11.9792H7.23618V16.2319L8.28156 17.2762V12.3216L7.93884 11.9792Z"></path> </svg> SHOP OUR STORES <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 10" height="10" width="16"> <path fill="#7F7DB2" d="M7.84119 9.37875C7.56585 9.37875 7.29055 9.27362 7.08063 9.0638L0.474829 2.45794C0.0546142 2.03772 0.0546142 1.35642 0.474829 0.936372C0.894874 0.516327 1.57604 0.516327 1.99629 0.936372L7.84119 6.78161L13.6861 0.936576C14.1063 0.516531 14.7874 0.516531 15.2074 0.936576C15.6279 1.35662 15.6279 2.03793 15.2074 2.45814L8.60175 9.06401C8.39173 9.27386 8.11643 9.37875 7.84119 9.37875Z"></path> </svg> </button> <div class="dropdown-content" > <div class="dropdown-arrow"></div> <a href="https://licorice.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_26cdc7c3-0ec0-4d72-b94d-48090df5651c.png?v=1733496615" alt="Licorice" class="dropdown-logo" /> <span class="shop-link" style="background-color: #EB3223">CLICK TO SHOP</span> </a> <a href="https://caramels.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_2.png?v=1733496615" alt="Caramels" class="dropdown-logo" /> <span class="shop-link" style="background-color: #73593C">CLICK TO SHOP</span> </a> <a href="https://pretzels.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_1.png?v=1733496615" alt="Pretzels" class="dropdown-logo" /> <span class="shop-link" style="background-color: #F6AA31">CLICK TO SHOP</span> </a> <a href="https://chocolate.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_3.png?v=1733496615" alt="Chocolate" class="dropdown-logo" /> <span class="shop-link" style="background-color: #FD6418">CLICK TO SHOP</span> </a> <a href="https://taffy.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_4.png?v=1733496615" alt="Taffy" class="dropdown-logo" /> <span class="shop-link" style="background-color: #807DB6">CLICK TO SHOP</span> </a> <a href="https://truffles.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_6.png?v=1733496615" alt="Truffles" class="dropdown-logo" /> <span class="shop-link" style="background-color: #DFA245">CLICK TO SHOP</span> </a> <a href="https://cupcakes.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_5.png?v=1733496615" alt="Cupcakes" class="dropdown-logo" /> <span class="shop-link" style="background-color: #8A2BE2">CLICK TO SHOP</span> </a> <a href="https://cookies.com?utm_source=cross_sell&utm_medium=taffy" target="_blank" class="dropdown-item"> <img src="https://cdn.shopify.com/s/files/1/0275/6984/8381/files/Licorice_7.png?v=1733496615" alt="Cookies" class="dropdown-logo" /> <span class="shop-link" style="background-color: #442107">CLICK TO SHOP</span> </a> </div> </section> <section id="marquee-sections--15646727831646__marquee_KXgN8E" class="marquee overflow-hidden bg-secondary text-white pt-4 pb-4 mt-0 mb-0" style="width: 100%; font-family: 'Apparat';"> <ul class="list-unstyled align-items-center mb-0 fs-6 text-capitalize" data-animation-duration="20" data-marquee-direction="left" data-section-id="sections--15646727831646__marquee_KXgN8E" aria-label="Promotional Features"> <li class="px-6" > Fast & Fresh via FedEx </li> <li class="px-6" > Choose Any Delivery Date </li> <li class="px-6" > 40+ Flavors to Choose From </li> <li class="px-6" > FREE Shipping on Orders $65+ </li> </ul> </section> </div> </div><div id="shopify-section-sections--15646727831646__navbar" class="shopify-section shopify-section-group-header-group"> <style data-shopify> #topbar { background: #7F7DB2; font-family: "Apparat"; } a.nav-link { color: #FFFFFF; } .bottom-nav__desktop { flex: 0 0 auto; width: 100%; } .topbar__desktop-nav { justify-content: space-evenly; } ul.topbar__desktop-nav li.nav-item a.nav-link { color: #7F7DB2; } .mega-menu__nav-links { max-width: 85%; margin: 0 auto; justify-content: space-around; } #topbar .col-lg-3 { width: 33.333% !important; } li.nav-item::marker { content: none; } .search-text__placeholder { width: 90%; background-color: transparent; border: 0px; padding: 5px 15px; } .search-text__placeholder::placeholder { color: #FFFFFF; opacity: 1; } .desktop-logo__img { margin: 5px 0; } .cart-icon { flex-direction: column; } @media only screen and (max-width: 749px) { .top-nav__desktop { display: none !important; } nav#navbar-mobile.bg-white { background-color: #7F7DB2 !important; } #topbar .nav-link { color: #FFFFFF !important; max-width: 55px; } a.navbar-brand.mx-auto { margin-left: 10px !important; } } .search-box-wrapper { position: relative; display: inline-block; width: 100%; } .search-box { display: flex; align-items: center; background-color: #9997C1; border: 1px solid #fff; border-radius: 20px; padding: 5px 10px; color: #fff; max-width: 400px; margin: 0 auto; } .search-box .form-control { border: none; background: transparent; color: #fff; width: 100%; font-size: 14px; outline: none; padding-left: 8px !important; padding: 0; } .search-box .form-control:focus { outline: none; box-shadow: none; } .search-box .form-control::placeholder { color: #fff; opacity: 1; } .icon-search { stroke: #fff; flex-shrink: 0; } .search-box:hover { border-color: #fff; } .search-container { position: absolute; top: 100%; left: 0; right: 0; background: white; border: 1px solid #ddd; border-radius: 4px; z-index: 1000; max-height: 500px; overflow-y: auto; display: none; } .search-container.visible { display: block; } .clear-search { background: none; border: none; color: #ccc; font-size: 16px; cursor: pointer; margin-left: 8px; display: none; } .clear-search:focus { outline: none; } .search-box .form-control:not(:placeholder-shown) ~ .clear-search { display: block; } .product-item { display: flex; align-items: center; padding: 10px; border-bottom: 1px solid #f0f0f0; cursor: pointer; } .product-item:hover .product-title { color: #666; } .product-item:last-child { border-bottom: none; } #topbar .product-item img { border-radius: 4px; width: 75px; height: 75px; margin-right: 10px; } .product-item .product-details { display: flex; flex-direction: column; } .product-item .product-title { font-size: 20px; font-weight: bold; color: #000000; } .product-item .product-price-final { font-size: 18px; color: #000000; } .collection-item { padding: 10px; border-bottom: 1px solid #f0f0f0; cursor: pointer; } .collection-item:last-child { border-bottom: none; } .collection-item a { text-decoration: none; } .collection-item:hover .collection-title { color: #666; } .collection-item .collection-title { font-size: 20px; font-weight: bold; color: #000000; } .search-container .yotpo-reviews-star-ratings-widget { justify-content: flex-start !important; } .topbar__side-nav { display: flex; align-items: center; margin-top: 1px; } .search-container .yotpo-reviews-star-ratings-widget { justify-content: flex-start !important; } predictive-search .predictive-search-results-title { font-size: 1rem; margin-bottom:.75rem; margin: 25px 0 15px 25px; margin-left:0; font-weight: bold; text-decoration: underline; } predictive-search .product-item-title { font-size:1rem; min-height:unset; justify-content: flex-start!important; } #offcanvas-search .product-item-title { justify-content: flex-start!important; font-size:1rem; min-height:unset; } /* desktop */ #predictive-search-navbar .predictive-search-results-title{ padding-left:10px; font-size:1.2rem; } #predictive-search-navbar .align-items-center{ width:100%!important; gap:13px; } #predictive-search-navbar .product-item-title, #offcanvas-search .product-item-title{ font-size:1.2rem; } #predictive-search-navbar .product-item img{ width:90px; height:90px; } #predictive-search-navbar .col-4.px-3{ padding-right:0!important; width:90px; height:90px; } /* text content container */ #predictive-search-navbar .product-item .col-8.px-3{ padding-left:0!important; } #predictive-search-navbar .collection-list, #predictive-search-navbar .articles-list, #predictive-search-navbar .page-list{ padding:10px; } #predictive-search-navbar .collection-item a, #predictive-search-navbar .page-list a{ background-color:var(--bs-secondary); color:#ffffff; } #predictive-search-navbar .collection-item a:hover, #predictive-search-navbar .page-list a:hover{ filter:brightness(95%); } </style> <div id="topbar"> <!-- <div class="w-full py-3 text-center" style="background: #B1AFE4"> <style> .cart-goal { background: #b1afe4; } .cart-goal-marker { position: absolute; top: 50%; border-radius: 6px; border: 1px solid #FFFFFF; background: #FFFFFF; width: 42px; height: 32px; transform: translate(-50%,-50%); overflow: hidden; display: flex; align-items: center; justify-content: center; color: #7F7DB2; text-align: center; font-family: "apparat"; font-size: 14.4px; font-style: normal; line-height: 93%; /* 13.392px */ font-weight: 700; font-style: normal; padding-top: 3px; } .cart-goal-marker.active { color: #fff; border: 1px solid #FFF; background: #E12953; } .cart-goal-description { display: flex; align-items: center; justify-content: center; text-transform: uppercase; gap: 5px; margin-top: 5px; color: #FFF; text-align: center; font-family: "Apparat"; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; } .cart-goal-description p { margin: 0; } .unlock-badge { color: #FFF; text-align: center; font-family: "apparat"; font-size: 10px; font-style: normal; font-weight: 800; line-height: normal; text-transform: uppercase; border-radius: 30px; padding: 5px 10px; height: fit-content; background: var(--color-secondary1, #B53446); } .progress-wrapper-parent { display: flex; align-items: center; justify-content: center; gap: 40px; } .progress-wrapper { display: flex; align-items: center; justify-content: center; height: 32px; width: fit-content; padding: 5px 0; } .progress { width: 300px; background: rgba(255, 223, 223, 0.58); border: 1px solid #FFFFFF; } .progress-bar { background:#E12953; } .confetti-particle { position: absolute; width: 6px; height: 6px; border-radius: 50%; pointer-events: none; z-index: 2; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 167, 57, 0.7); } 100% { box-shadow: 0 0 0 20px rgba(255, 167, 57, 0); } } @media (max-width: 768px) { .cart-goal-description { display: flex; flex-direction: column; } .progress-wrapper-parent { flex-direction: column; padding: 8px; padding-top: 0; gap: 5px; } .offcanvas .cart-goal.mx-n5 { margin-left: 0 !important; margin-right: 0 !important; } } .offcanvas .progress-wrapper-parent { flex-direction: column; background: inherit; } .offcanvas .cart-goal { max-width: 100%; } .offcanvas .progress-wrapper-parent { gap: 5px; margin: 5px auto; padding-bottom: 5px; } </style> </div> --> <div class="container-fluid"> <div class="row align-items-center top-nav__desktop"> <div class="row align-items-center flex-grow-1"> <div class="col-lg-3"> <a class="navbar-brand me-auto py-0" href="/"> <img class="img-fluid desktop-logo__img" src="//taffy.com/cdn/shop/files/Vector_2.svg?height=96&v=1736188839" alt="Taffy.com" width="204" height="48" loading="lazy"> </a> </div> <div class="search-box-wrapper col-lg-3"> <predictive-search> <form action="/search" method="get" role="search"> <div class="search-box"> <svg xmlns="http://www.w3.org/2000/svg" class="icon-search" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> <input id="navbar-search-input" class="form-control" type="search" name="q" value="" aria-describedby="predictive-search-alert-navbar" aria-label="Start typing to see results..." placeholder="Search for Taffy here" data-search-collections="true" data-search-pages="true" data-search-articles="true" autocomplete="off"> </div> <input type="hidden" name="type" value="product"> </form> <div id="search-container" class="search-container"> <div id="predictive-search-navbar" tabindex="-1"></div> </div> <p id="predictive-search-alert-navbar" class="visually-hidden" role="status" data-text-result-found="1 result found" data-text-results-found="[count] results found" data-text-no-results="No results found"> </p> </predictive-search> </div> <div class="col-lg-3"> <div class="d-none d-lg-block"> <ul class="nav nav-icons justify-content-end" aria-label="Utilities menu"> <div class="topbar__side-nav"> <ul class="nav nav-side-menu nav-links"> <li class="nav-item"> <a class="nav-link rounded " href="https://taffy-goat-shop.myshopify.com/products/paid-membership" aria-current=""> MEMBERSHIP </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="https://taffy-goat-shop.myshopify.com/pages/faq" aria-current=""> FAQ </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="https://taffy.gorgias.help/en-US" aria-current=""> HELP </a> </li> </ul> </div> <!-- <li class="nav-item pe-4"> <a class="nav-link" href=""> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" class="me-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path> </svg> </a> </li> --> <li class="nav-item"> <a class="cart-icon nav-link link-dark" href="#offcanvas-cart" data-bs-toggle="offcanvas" role="button" aria-label="Cart 0"> <svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18.3594 17.9688H8.90332C8.5374 17.9687 8.18311 17.8402 7.90221 17.6057C7.62131 17.3712 7.43162 17.0456 7.36621 16.6855L4.75879 2.34375H2.34375" stroke="white" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.98438 21.875C10.0631 21.875 10.9375 21.0006 10.9375 19.9219C10.9375 18.8432 10.0631 17.9688 8.98438 17.9688C7.90569 17.9688 7.03125 18.8432 7.03125 19.9219C7.03125 21.0006 7.90569 21.875 8.98438 21.875Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/> <path d="M18.3594 21.875C19.4381 21.875 20.3125 21.0006 20.3125 19.9219C20.3125 18.8432 19.4381 17.9688 18.3594 17.9688C17.2807 17.9688 16.4062 18.8432 16.4062 19.9219C16.4062 21.0006 17.2807 21.875 18.3594 21.875Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.88965 14.0625H19.1504C19.5163 14.0624 19.8706 13.934 20.1515 13.6995C20.4324 13.465 20.6221 13.1393 20.6875 12.7793L21.875 6.25H5.46875" stroke="white" stroke-linecap="round" stroke-linejoin="round"/> </svg> <span class="cart-count-badge badge text-white cart-count" hidden> 0 </span> </a> </li> </ul> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const menuToggle = document.getElementById('mobile-menu-toggle'); const menuIcon = document.getElementById('menu-icon'); const menuText = document.getElementById('menu-toggle-text'); const mobileMenu = document.getElementById('mobile-menu'); const openText = "CLOSE"; const closeText = "SHOP"; menuToggle.addEventListener('click', () => { if (mobileMenu.classList.contains('active')) { mobileMenu.classList.remove('active'); document.body.classList.remove('menu-open'); menuIcon.innerHTML = ` <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="18" x2="21" y2="18"></line>`; menuText.textContent = closeText; } else { mobileMenu.classList.add('active'); document.body.classList.add('menu-open'); menuIcon.innerHTML = ` <line x1="4" y1="4" x2="20" y2="20"></line> <line x1="4" y1="20" x2="20" y2="4"></line>`; menuText.textContent = openText; } }); }); </script> <script type="text/javascript"> (function() { var script = document.createElement('script'); script.async = true; script.src = '//staticw2.yotpo.com/7pysJMKE22Kw3SnGlc8PBZrd8rzByjodfnKxkBPi/widget.js'; var firstScript = document.getElementsByTagName('script')[0]; firstScript.parentNode.insertBefore(script, firstScript); })(); </script> <nav id="navbar-mobile" class="navbar d-lg-none bg-white text-dark shadow-sm pt-3 pb-3"> <div class="container"> <a class="nav-link px-3 ms-n2 nav-link-hamburger" role="button" id="mobile-menu-toggle" aria-label="Menu"> <svg xmlns="http://www.w3.org/2000/svg" width="18.8" height="18.8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="menu-icon"> <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="18" x2="21" y2="18"></line> </svg> <span class="navbar-mobile__menu-text" id="menu-toggle-text"> SHOP </span> </a> <a class="nav-link px-3 nav-link-hamburger" href="#offcanvas-search" data-bs-toggle="offcanvas" aria-controls="offcanvas-search" role="button" aria-label="Search"> <svg xmlns="http://www.w3.org/2000/svg" width="18.8" height="18.8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> <span class="navbar-mobile__menu-text"> SEARCH </span> </a> <a class="navbar-brand mx-auto py-0" href="/"> <img class="img-fluid" src="//taffy.com/cdn/shop/files/Vector_2.svg?height=80&v=1736188839" alt="Taffy.com" width="170" height="40" loading="lazy"> </a> <a class="cart-icon nav-link px-3 me-n2" href="#offcanvas-cart" data-bs-toggle="offcanvas" role="button" aria-label="Cart 0"> <svg xmlns="http://www.w3.org/2000/svg" width="18.8" height="18.8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="10" cy="20.5" r="1"/><circle cx="18" cy="20.5" r="1"/><path d="M2.5 2.5h3l2.7 12.4a2 2 0 0 0 2 1.6h7.7a2 2 0 0 0 2-1.6l1.6-8.4H7.1"/> </svg> <span class="cart-count-badge badge cart-count bg-primary" hidden> 0 </span> <span class="navbar-mobile__menu-text"> CART </span> </a> </div> </nav> <nav id="navbar-desktop" class="navbar d-none d-lg-block bg-white text-dark shadow-sm menu-desktop-hover pt-3 pb-3"> <div class="container-fluid position-relative"> <div class="bottom-nav__desktop"> <ul class="nav nav-links topbar__desktop-nav align-items-center"> <li class="nav-item"> <a class="nav-link rounded " href="/collections/all" aria-current=""> All Flavors </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="/collections/gifts" aria-current=""> Gifts </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="/collections/sampler-packs" aria-current=""> Samplers </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="/collections/bundles" aria-current=""> Bundle & Save </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="/collections/the-greatest-of-all-time" aria-current=""> Shop Our Brands </a> </li> <li class="nav-item"> <a class="nav-link rounded " href="/pages/corporate-gifting" aria-current=""> Corporate Gifts </a> </li> </ul> </div> </div> </div> </nav> <div class="taffy-stripe-bar"> </div> <style data-shopify> #mobile-menu { position: fixed; left: 0; top: var(--header-height); width: 100%; height: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; background: #fff; z-index: 9999; transform: translateX(-100%); opacity: 0; transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; font-family: "Apparat"; } #mobile-menu.active { transform: translateX(0); opacity: 1; } body.menu-open { overflow: hidden; } :root { --header-height: 95px; } .mobile-menu__list { list-style-type: none; background-color: #F4F4F4; padding-left: 0; margin: 0; padding: 15px 0; } .mobile-menu__list-item { margin: 10px; background-color: #FFFFFF; border-bottom: 1px solid #ddd; position: relative; } .mobile-menu__list-item a { text-decoration: none; padding: 10px; color: #000000; font-weight: 700; font-family: 'Apparat'; font-size: 18px; display: flex; justify-content: flex-start; align-items: center; } .mobile-menu__list-item svg { position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); } .badge { padding: 6px; font-size: 12px; display: inline-block; margin-left: 8px; font-family: 'Apparat'; border-radius: 4px; } .mobile-nav-banner { display: flex; align-items: center; justify-content: space-between; background-color: #FFFFFF; border-bottom: 1px solid #ddd; } .mobile-nav-banner-container { padding: 10px; padding-bottom: 0px; background-color: #F4F4F4; } .mobile-nav-banner .banner-content { flex: 1; padding: 1.5rem; } .mobile-nav-banner .banner-text { font-size: 22px; font-weight: bold; margin-bottom: 0.5rem; color: #ffffff; font-family: "Apparat"; } .mobile-nav-banner .btn { text-transform: uppercase; font-size: 16px; padding: 0.5rem 1rem; text-decoration: none; font-family: "Apparat"; font-weight: 700; color: #fff; border-radius: 4px; } .mobile-nav-banner .btn:hover { background-color: #F0B46D; color: #fff; } .banner-image { max-width: 35%; } .mobile-nav-banner .banner-image img { max-width: 100%; height: auto; } .menu-mobile { list-style: none; padding: 0; margin: 0; background-color: #FFFFFF; padding-bottom: 150px; } .menu-mobile li a { display: block; padding: 0.75rem 1rem; color: #000000; text-decoration: none; font-size: 14px; } .menu-mobile li a:hover { background-color: #f0f0f0; color: #000000; } </style> <div id="mobile-menu" class="mobile-menu"> <div class="mobile-nav-banner-container"> <div class="mobile-nav-banner d-flex align-items-center"> <div class="banner-content" style="background-color: #7f7db2;"> <h2 class="banner-text">Create A Gift Box For Any Occasion</h2> <a href="/collections/create-your-gift-box" class="btn" style="background-color: #fbb15f; color: #ffffff;"> Get Started </a> </div> <div class="banner-image"> <img src="//taffy.com/cdn/shop/files/DSC2468.jpg?v=1736793012&width=200" alt="Create A Gift Box For Any Occasion" class="img-fluid" /> </div> </div> </div> <ul class="mobile-menu__list"> <li class="mobile-menu__list-item"> <a href="/collections/all"> ALL FLAVORS <span class="badge" style="background-color: #d16b87; color: #fff;"> 40+ FLAVORS </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> <li class="mobile-menu__list-item"> <a href="/collections/gifts"> GIFTS <span class="badge" style="background-color: #d16b87; color: #fff;"> 50+ OPTIONS </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> <li class="mobile-menu__list-item"> <a href="/collections/sampler-packs"> SAMPLERS <span class="badge" style="background-color: #24a10f; color: #fff;"> MOST POPULAR </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> <li class="mobile-menu__list-item"> <a href="/collections/bundles"> BUNDLES <span class="badge" style="background-color: #d16b87; color: #fff;"> BUY MORE, SAVE MORE </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> <li class="mobile-menu__list-item"> <a href="/collections/the-greatest-of-all-time"> SHOP OUR BRANDS <span class="badge" style="background-color: #d16b87; color: #fff;"> NOW AVAILABLE </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> <li class="mobile-menu__list-item"> <a href="https://taffy-goat-shop.myshopify.com/products/paid-membership"> BECOME A MEMBER <span class="badge" style="background-color: #ff8b27; color: #fff;"> VIP </span> </a> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" class="bi bi-chevron-right" viewBox="0 0 16 16"> <path d="M6 2l5 6-5 6"/> </svg> </li> </ul> <ul class="menu-mobile mt-3"> <li> <a href="https://taffy.com/pages/membership-login"> MEMBERSHIP LOGIN </a> </li> <li> <a href="https://taffy-goat-shop.myshopify.com/pages/corporate-gifting"> CORPORATE GIFTS & EVENTS </a> </li> <li> <a href="https://faire.com/direct/licorice"> WHOLESALE </a> </li> <li> <a href="https://taffy-goat-shop.myshopify.com/pages/tracking"> TRACK ORDER </a> </li> <li> <a href="https://taffy.gorgias.help/en-US"> HELP </a> </li> </ul> </div> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "Organization", "name": "Taffy.com", "logo": "https:\/\/taffy.com\/cdn\/shop\/files\/Vector_2.svg?v=1736188839\u0026width=500", "sameAs": [ "https:\/\/www.facebook.com\/taffydotcom", "", "https:\/\/www.instagram.com\/taffydotcom", "", "", "", "", "", "" ], "url": "https:\/\/taffy.com" } </script> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "WebSite", "name": "Taffy.com", "potentialAction": { "@type": "SearchAction", "target": "https:\/\/taffy.com\/search?q={search_term_string}", "query-input": "required name=search_term_string" }, "url": "https:\/\/taffy.com" } </script><style data-shopify> .nav-link-hamburger { flex-direction: column; } .navbar-mobile__menu-text { font-size: 12px; text-transform: none; } #navbar-mobile .container { --bs-gutter-x: 1rem !important; } </style> </div> <!-- END sections: header-group --> </div> <main id="main"> <div id="shopify-section-template--15646729404510__holiday_splash_YWrEzh" class="shopify-section"><link href="//taffy.com/cdn/shop/t/40/assets/holiday-splash.css?v=98510562226457060081744060130" rel="stylesheet"> <section class="holiday-splash"> <img src="//taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=2000" alt="" srcset="//taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=352 352w, //taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=832 832w, //taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=1200 1200w, //taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=1920 1920w, //taffy.com/cdn/shop/files/taffy65desktop_2.png?v=1746818272&width=2000 2000w" width="2000" height="707" loading="lazy" class="holiday-splash__background holiday-splash__background--desktop" sizes="100vw"> <img src="//taffy.com/cdn/shop/files/taffy65mobile_1_1.png?v=1746818273&width=1000" alt="" srcset="//taffy.com/cdn/shop/files/taffy65mobile_1_1.png?v=1746818273&width=352 352w, //taffy.com/cdn/shop/files/taffy65mobile_1_1.png?v=1746818273&width=832 832w, //taffy.com/cdn/shop/files/taffy65mobile_1_1.png?v=1746818273&width=1000 1000w" width="1000" height="1578" loading="lazy" class="holiday-splash__background holiday-splash__background--mobile" sizes="100vw"> <div class="holiday-splash__container page-width"> <div class="holiday-splash__content-wrapper holiday-splash__content-wrapper--center-right holiday-splash__content-wrapper--mobile-top"> <div class="holiday-splash__content" style="max-width: 600px;" > <div class="holiday-splash__caption" style=" color: #807db6; --block-width: 650px; margin-top: 0px; margin-bottom: 4px; " > <div class="holiday-splash__stars"> <svg width="120" height="22" viewBox="0 0 120 22" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M10.9091 0.104858L13.3583 7.63322H21.2843L14.8721 12.286L17.3213 19.8144L10.9091 15.1616L4.49689 19.8144L6.94613 12.286L0.533929 7.63322H8.45985L10.9091 0.104858Z" fill="#f0b46d"/> <path d="M35.4545 0.104858L37.9038 7.63322H45.8297L39.4175 12.286L41.8667 19.8144L35.4545 15.1616L29.0423 19.8144L31.4916 12.286L25.0794 7.63322H33.0053L35.4545 0.104858Z" fill="#f0b46d"/> <path d="M60 0.104858L62.4492 7.63322H70.3752L63.963 12.286L66.4122 19.8144L60 15.1616L53.5878 19.8144L56.037 12.286L49.6248 7.63322H57.5508L60 0.104858Z" fill="#f0b46d"/> <path d="M84.5454 0.104858L86.9947 7.63322H94.9206L88.5084 12.286L90.9576 19.8144L84.5454 15.1616L78.1332 19.8144L80.5825 12.286L74.1703 7.63322H82.0962L84.5454 0.104858Z" fill="#f0b46d"/> <path d="M109.091 0.104858L111.54 7.63322H119.466L113.054 12.286L115.503 19.8144L109.091 15.1616L102.679 19.8144L105.128 12.286L98.7158 7.63322H106.642L109.091 0.104858Z" fill="#f0b46d"/> </svg> </div> <span>1 MILLION+ SATISFIED CUSTOMERS</span> </div> <h2 class="holiday-splash__title" style=" color: #807db6; --block-width: 650px; margin-top: 0px; margin-bottom: 4px; font-weight: 700; " > Vacation in Every Bite. </h2> <div class="holiday-splash__text" style=" color: #807db6; --block-width: 350px; margin-top: 0px; margin-bottom: 0px; " > <p>The World’s Best Taffy.</p><p>Packaged to Perfection.</p> </div> <div class="holiday-splash__buttons" style=" --block-width: 400px; margin-top: 0px; margin-bottom: 0px; " > <a href="/collections/all" class="holiday-splash__button" > SHOP FLAVORS </a> <a href="/collections/sampler-packs" class="holiday-splash__button" > SHOP SAMPLERS </a> </div> </div> </div> </div> </section> </div><div id="shopify-section-template--15646729404510__grid_of_collections_cDgtyg" class="shopify-section"> <style> .grid-of-collections { margin: 0 auto; max-width: 1400px; padding: 0 1.5rem; } .grid-of-collections__container { border: 1px solid #D4D4D4; background: #F9F9F9; padding: 2rem; } .grid-of-collections__title { margin-bottom: 2rem; text-align: center; font-size: 2rem; font-weight: bold; text-transform: uppercase; } .grid-of-collections__grid { display: grid; gap: 2rem; } .grid-of-collections__item { text-decoration: none; color: inherit; display: block; } .grid-of-collections__image-wrapper { aspect-ratio: 1; overflow: hidden; margin-bottom: 1rem; background: white; /* Add white background for images */ } .grid-of-collections__image { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; } .grid-of-collections__item:hover .grid-of-collections__image { transform: scale(1.05); } .grid-of-collections__collection-title { margin: 0; font-size: 1.2rem; text-transform: uppercase; text-align: center; font-weight: bold; } @media screen and (max-width: 749px) { .grid-of-collections__grid { grid-template-columns: repeat(2, 1fr); } .grid-of-collections__container { padding: 1rem; } } @media screen and (min-width: 750px) { .grid-of-collections__grid { grid-template-columns: repeat(4, 1fr); } } </style> <section class="grid-of-collections" style="padding-top: 36px; padding-bottom: 36px;"> <div class="grid-of-collections__container"> <h2 class="grid-of-collections__title">Shop by Category</h2> <div class="grid-of-collections__grid"> <a href="/collections/classics" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/010f31c4288602266c9cfc7752f2417b.png?v=1732641343&width=500" alt="Classics" srcset="//taffy.com/cdn/shop/collections/010f31c4288602266c9cfc7752f2417b.png?v=1732641343&width=352 352w, //taffy.com/cdn/shop/collections/010f31c4288602266c9cfc7752f2417b.png?v=1732641343&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Classics</h3> </a> <a href="/collections/tropical" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/image_2.jpg?v=1732641408&width=500" alt="Tropical" srcset="//taffy.com/cdn/shop/collections/image_2.jpg?v=1732641408&width=352 352w, //taffy.com/cdn/shop/collections/image_2.jpg?v=1732641408&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Tropical</h3> </a> <a href="/collections/fruity" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/image_3.jpg?v=1732641458&width=500" alt="Fruity" srcset="//taffy.com/cdn/shop/collections/image_3.jpg?v=1732641458&width=352 352w, //taffy.com/cdn/shop/collections/image_3.jpg?v=1732641458&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Fruity</h3> </a> <a href="/collections/sweets" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/image_52.png?v=1732641482&width=500" alt="Sweets" srcset="//taffy.com/cdn/shop/collections/image_52.png?v=1732641482&width=352 352w, //taffy.com/cdn/shop/collections/image_52.png?v=1732641482&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Sweets</h3> </a> <a href="/collections/gifts" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/b43710be52284a3d34ee896692b42b39_2e8b8a20-4ef5-473f-9507-baac41b2ad82.jpg?v=1733248925&width=500" alt="Gifts" srcset="//taffy.com/cdn/shop/collections/b43710be52284a3d34ee896692b42b39_2e8b8a20-4ef5-473f-9507-baac41b2ad82.jpg?v=1733248925&width=352 352w, //taffy.com/cdn/shop/collections/b43710be52284a3d34ee896692b42b39_2e8b8a20-4ef5-473f-9507-baac41b2ad82.jpg?v=1733248925&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Gifts</h3> </a> <a href="/collections/sampler-packs" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/c7d798d51c15d5500326da1e9ef54300.png?v=1732641544&width=500" alt="Sampler Packs" srcset="//taffy.com/cdn/shop/collections/c7d798d51c15d5500326da1e9ef54300.png?v=1732641544&width=352 352w, //taffy.com/cdn/shop/collections/c7d798d51c15d5500326da1e9ef54300.png?v=1732641544&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Sampler Packs</h3> </a> <a href="/collections/bundles" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/c9256c6dc88910c369d0a31164f43d03.png?v=1732641576&width=500" alt="Bundles" srcset="//taffy.com/cdn/shop/collections/c9256c6dc88910c369d0a31164f43d03.png?v=1732641576&width=352 352w, //taffy.com/cdn/shop/collections/c9256c6dc88910c369d0a31164f43d03.png?v=1732641576&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">Bundles</h3> </a> <a href="/collections/new" class="grid-of-collections__item"> <div class="grid-of-collections__image-wrapper"><img src="//taffy.com/cdn/shop/collections/image_75.png?v=1744992879&width=500" alt="New" srcset="//taffy.com/cdn/shop/collections/image_75.png?v=1744992879&width=352 352w, //taffy.com/cdn/shop/collections/image_75.png?v=1744992879&width=500 500w" width="500" height="500" loading="lazy" class="grid-of-collections__image"> </div> <h3 class="grid-of-collections__collection-title">New</h3> </a> </div> </div> </section><style> #shopify-section-template--15646729404510__grid_of_collections_cDgtyg .grid-of-collections__collection-title {color: #7f7db2; text-transform: capitalize; font-family: "Apparat";} #shopify-section-template--15646729404510__grid_of_collections_cDgtyg .grid-of-collections__title {color: #7f7db2; text-transform: capitalize; font-family: "Apparat";} </style></div><div id="shopify-section-template--15646729404510__featured_products_xBhGjE" class="shopify-section"> <style data-shopify> /* Featured Products Cards Breakpoints */ #featured-products-template--15646729404510__featured_products_xBhGjE .product-list { display: grid; width: calc(100% - 15px); margin: 0 auto !important; grid-template-columns: repeat(2, min(calc((100% / 2) - 10px), 310px)); } #featured-products-template--15646729404510__featured_products_xBhGjE .product-list .bfcm-product-card, #featured-products-template--15646729404510__featured_products_xBhGjE .product-list .product-item-promo-card { width: 100%; max-width: unset; } @media (min-width: 1050px) { #featured-products-template--15646729404510__featured_products_xBhGjE .product-list { display: grid; grid-template-columns: repeat(4, min(calc((100% / 4) - 10px), 310px)); } } /* --- */ </style> <style data-shopify> #featured-products-template--15646729404510__featured_products_xBhGjE .splide__slide .badge { display: none; } #featured-products-template--15646729404510__featured_products_xBhGjE .splide__slide p.subtitle.mb-3{ text-wrap-style: pretty; } #featured-products-template--15646729404510__featured_products_xBhGjE .product-item.splide__slide{ border:none; padding:0!important; margin-bottom:0!important; height:100%; } #featured-products-template--15646729404510__featured_products_xBhGjE .product-item.splide__slide > div{ flex-direction:column; display:flex; } #featured-products-template--15646729404510__featured_products_xBhGjE .product-item.splide__slide .btn{ margin-top:auto; } @media screen and (max-width: 992px) { #featured-products-template--15646729404510__featured_products_xBhGjE .splide__slide p.subtitle.mb-3, #featured-products-template--15646729404510__featured_products_xBhGjE .splide__slide .btn { font-size:.8rem; } #featured-products-template--15646729404510__featured_products_xBhGjE .product-item.splide__slide .btn{ margin-top:unset; } #featured-products-template--15646729404510__featured_products_xBhGjE .product-item.splide__slide > div{ justify-content:center; } } </style> <section id="featured-products-template--15646729404510__featured_products_xBhGjE" class="featured-products text-center pt-9 pb-9 mt-0 mb-0 d-md-block d-lg-block " style="background-color: #fdf8f2"> <div class=""> <div class="featured-products__title-container"> <h2 class="title mb-4 h2" style="color: #807db6" > Best Selling Flavors </h2> <h4 class="caption px-8 px-lg-0 mb-4 h4" > </h4> </div> <ul class="product-list list-unstyled row mx-n3 mx-lg-n4 mb-0"> <div class="bfcm-product-card"> <span class="bfcm-product-card__badge badge-best-seller"> Best Seller </span> <a href="/products/banana-bonanza" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Banana_Bonanza_f2ad1b5b-abbd-4201-81d8-266b6b2ad0fe_500x.jpg?v=1744996584" alt="Banana Bonanza" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/banana-bonanza"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938040303710" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/banana-bonanza">Banana Bonanza</a></h3> <a class="product-card-link-item" href="/products/banana-bonanza"><div class="bfcm-product-card__pricing product-price" data-original-price="1200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $12 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/banana-bonanza" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40476505342046"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <span class="bfcm-product-card__badge badge-best-seller"> Best Seller </span> <a href="/products/orange-creamsicle" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Orange_Drumsicles_500x.jpg?v=1744996674" alt="Orange Dreamsicle" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/orange-creamsicle"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="7077234081886" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/orange-creamsicle">Orange Dreamsicle</a></h3> <a class="product-card-link-item" href="/products/orange-creamsicle"><div class="bfcm-product-card__pricing product-price" data-original-price="1200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $12 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/orange-creamsicle" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40820898070622"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <span class="bfcm-product-card__badge badge-best-seller"> Best Seller </span> <a href="/products/juicy-watermelon" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Juicy_Watermelon_def55c81-8fd3-4589-9ebb-6722dec70140_500x.jpg?v=1744996693" alt="Juicy Watermelon" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/juicy-watermelon"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938049216606" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/juicy-watermelon">Juicy Watermelon</a></h3> <a class="product-card-link-item" href="/products/juicy-watermelon"><div class="bfcm-product-card__pricing product-price" data-original-price="1200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $12 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/juicy-watermelon" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40476540502110"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <span class="bfcm-product-card__badge badge-best-seller"> Best Seller </span> <a href="/products/peppermint-perfection" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Peppermint_Perfection_02b7a886-efce-44da-940f-aa79f58f2d39_500x.jpg?v=1744996710" alt="Peppermint Perfection" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/peppermint-perfection"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938047447134" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/peppermint-perfection">Peppermint Perfection</a></h3> <a class="product-card-link-item" href="/products/peppermint-perfection"><div class="bfcm-product-card__pricing product-price" data-original-price="1200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $12 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/peppermint-perfection" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40476532572254"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> </ul> <a class="btn px-8 px-lg-15 mt-6 mb-0 font-family-headings fs-5 btn-primary" href="/collections/all"> Shop All Flavors </a> </div> </section> <script> document.addEventListener("DOMContentLoaded", function() { let elements = [...document.querySelectorAll(".subtitle.test.text-muted.small.mt-3.mb-n1")]; elements.forEach((el) => { if (el.innerText == '4 Tubes | $56') { el.innerHTML = "4 Tubes | <strike>$56</strike> | $52 | ($13 Each)" } }); }); </script> </div><div id="shopify-section-template--15646729404510__holiday_cards_3pHgnF" class="shopify-section"> <style> .holiday-cards--template--15646729404510__holiday_cards_3pHgnF { padding: 28px 0 0px; } .holiday-cards__button { font-family: "apparat-light"; font-weight: 800; } .holiday-cards__container { max-width: 1200px; margin: 0 auto; } .holiday-cards__grid { display: grid; gap: 20px; grid-template-columns: 1fr; } @media screen and (min-width: 768px) { .holiday-cards__grid { grid-template-columns: 1fr 1fr; } } .holiday-cards__card { position: relative; background-color: #F9F9F9; border-radius: 8px; overflow: hidden; border: 1px solid #D4D4D4; } .holiday-cards__image-wrapper { position: relative; padding-bottom: 56.25%; /* 16:9 aspect ratio */ overflow: hidden; } .holiday-cards__image { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; } .holiday-cards__content { padding: 20px; text-align: left; } .holiday-cards__heading { font-size: 24px; font-weight: 700; margin-bottom: 10px; text-transform: uppercase; width: fit-content; font-family: Apparat; color: #7F7DB2; } .holiday-cards__subheading { font-size: 16px; margin-bottom: 20px; width: fit-content; font-family: Apparat; color: #7F7DB2; } .holiday-cards__button { display: inline-block; padding: 12px 24px; background-color: #fff; color: #ffffff; text-transform: uppercase; font-weight: 600; text-decoration: none; color: black; border: 2px solid #000000; transition: all 0.3s ease; } .holiday-cards__button:hover { color: #ffffff; background-color: #000000; } </style> <section class="holiday-cards holiday-cards--template--15646729404510__holiday_cards_3pHgnF"> <div class="holiday-cards__container"> <div class="holiday-cards__grid"> <div class="holiday-cards__card" > <div class="holiday-cards__image-wrapper"> <img src="//taffy.com/cdn/shop/files/b43710be52284a3d34ee896692b42b39_800x.jpg?v=1732641511" alt="Create Your Own Gift Box" class="holiday-cards__image" loading="lazy" width="2000" height="2000" > </div> <div class="holiday-cards__content"> <h3 class="holiday-cards__heading">Create Your Own Gift Box</h3> <p class="holiday-cards__subheading">Choose from our 40+ flavors of taffy to create your own custom gift box! Available in 3, 6 or 12 tubes.</p> <a href="/collections/create-your-gift-box" class="holiday-cards__button"> GET STARTED </a> </div> </div> <div class="holiday-cards__card" > <div class="holiday-cards__image-wrapper"> <img src="//taffy.com/cdn/shop/files/ae663c7c2c3685592b553ffda71a3a78_800x.jpg?v=1732638258" alt="Classic & Unique flavors" class="holiday-cards__image" loading="lazy" width="2000" height="1333" > </div> <div class="holiday-cards__content"> <h3 class="holiday-cards__heading">Classic & Unique flavors</h3> <p class="holiday-cards__subheading">Choose from one of our 40+ flavors of delicious, hand-crafted saltwater taffy.</p> <a href="/collections/all" class="holiday-cards__button"> Shop All Flavors </a> </div> </div> </div> </div> </section></div><div id="shopify-section-template--15646729404510__featured_products_VCQ4FJ" class="shopify-section"> <style data-shopify> /* Featured Products Cards Breakpoints */ #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-list { display: grid; width: calc(100% - 15px); margin: 0 auto !important; grid-template-columns: repeat(2, min(calc((100% / 2) - 10px), 310px)); } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-list .bfcm-product-card, #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-list .product-item-promo-card { width: 100%; max-width: unset; } @media (min-width: 1050px) { #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-list { display: grid; grid-template-columns: repeat(4, min(calc((100% / 4) - 10px), 310px)); } } /* --- */ </style> <style data-shopify> #featured-products-template--15646729404510__featured_products_VCQ4FJ .splide__slide .badge { display: none; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .splide__slide p.subtitle.mb-3{ text-wrap-style: pretty; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-item.splide__slide{ border:none; padding:0!important; margin-bottom:0!important; height:100%; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-item.splide__slide > div{ flex-direction:column; display:flex; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-item.splide__slide .btn{ margin-top:auto; } @media screen and (max-width: 992px) { #featured-products-template--15646729404510__featured_products_VCQ4FJ .splide__slide p.subtitle.mb-3, #featured-products-template--15646729404510__featured_products_VCQ4FJ .splide__slide .btn { font-size:.8rem; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-item.splide__slide .btn{ margin-top:unset; } #featured-products-template--15646729404510__featured_products_VCQ4FJ .product-item.splide__slide > div{ justify-content:center; } } </style> <section id="featured-products-template--15646729404510__featured_products_VCQ4FJ" class="featured-products text-center pt-9 pb-9 mt-0 mb-0 d-md-block d-lg-block " style="background-color: #fdf8f2"> <div class=""> <div class="featured-products__title-container"> <h2 class="title mb-4 h2" style="color: #807db6" > Best Selling Sampler Packs </h2> <h4 class="caption px-8 px-lg-0 mb-4 h4" > </h4> </div> <ul class="product-list list-unstyled row mx-n3 mx-lg-n4 mb-0"> <div class="bfcm-product-card"> <a href="/products/old-fashioned-banana-split-sampler-pack" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Old_Fashioned_Banana_Split_Sampler_Pack-2445_500x.jpg?v=1741297166" alt="Old Fashioned Banana Split Sampler Pack" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6955901386846" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack">Old Fashioned Banana Split Sampler Pack</a></h3> <a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack"><div class="bfcm-product-card__pricing product-price" data-original-price="4200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $42 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/old-fashioned-banana-split-sampler-pack" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40534922494046"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <a href="/products/tropical-storm-sampler-pack" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Tropical_Storm_Sampler_Pack-2442_500x.jpg?v=1741297203" alt="Tropical Storm Sampler Pack" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/tropical-storm-sampler-pack"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6955901976670" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/tropical-storm-sampler-pack">Tropical Storm Sampler Pack</a></h3> <a class="product-card-link-item" href="/products/tropical-storm-sampler-pack"><div class="bfcm-product-card__pricing product-price" data-original-price="4200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $42 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/tropical-storm-sampler-pack" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40534924886110"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <a href="/products/island-favorites-sampler-pack" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Island_Favorites_Sampler_Pack-2443_500x.jpg?v=1741297226" alt="Island Favorites Sampler Pack" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/island-favorites-sampler-pack"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="7184204398686" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/island-favorites-sampler-pack">Island Favorites Sampler Pack</a></h3> <a class="product-card-link-item" href="/products/island-favorites-sampler-pack"><div class="bfcm-product-card__pricing product-price" data-original-price="4200" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $42 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/island-favorites-sampler-pack" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="41098550214750"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> </ul> <a class="btn px-8 px-lg-15 mt-6 mb-0 font-family-headings fs-5 btn-primary" href="/collections/sampler-packs"> Shop All Sampler Packs </a> </div> </section> <script> document.addEventListener("DOMContentLoaded", function() { let elements = [...document.querySelectorAll(".subtitle.test.text-muted.small.mt-3.mb-n1")]; elements.forEach((el) => { if (el.innerText == '4 Tubes | $56') { el.innerHTML = "4 Tubes | <strike>$56</strike> | $52 | ($13 Each)" } }); }); </script> </div><div id="shopify-section-template--15646729404510__mp4_video_jYC9em" class="shopify-section"> <section id="mp4-video-template--15646729404510__mp4_video_jYC9em" class="mp4-video pt-5 pb-5 mt-0 mb-0"> <div class="container"> <div class="mx-auto" style="max-width: 1400px"> <div class="ratio ratio-16x9"> <video playsinline="playsinline" class="shadow-sm rounded bg-black" autoplay="autoplay" loop="loop" muted="muted" preload="metadata"><source src="//taffy.com/cdn/shop/videos/c/vp/8955eda00eeb4574aaef18750dcfd7ec/8955eda00eeb4574aaef18750dcfd7ec.HD-1080p-7.2Mbps-26803668.mp4?v=0" type="video/mp4"><img src="//taffy.com/cdn/shop/files/preview_images/8955eda00eeb4574aaef18750dcfd7ec.thumbnail.0000000000_1200x.jpg?v=1712335516"></video> </div> </div> </div> </section> </div><div id="shopify-section-template--15646729404510__featured_products_UzBcKF" class="shopify-section"> <style data-shopify> /* Featured Products Cards Breakpoints */ #featured-products-template--15646729404510__featured_products_UzBcKF .product-list { display: grid; width: calc(100% - 15px); margin: 0 auto !important; grid-template-columns: repeat(2, min(calc((100% / 2) - 10px), 310px)); } #featured-products-template--15646729404510__featured_products_UzBcKF .product-list .bfcm-product-card, #featured-products-template--15646729404510__featured_products_UzBcKF .product-list .product-item-promo-card { width: 100%; max-width: unset; } @media (min-width: 1050px) { #featured-products-template--15646729404510__featured_products_UzBcKF .product-list { display: grid; grid-template-columns: repeat(4, min(calc((100% / 4) - 10px), 310px)); } } /* --- */ </style> <style data-shopify> #featured-products-template--15646729404510__featured_products_UzBcKF .splide__slide .badge { display: none; } #featured-products-template--15646729404510__featured_products_UzBcKF .splide__slide p.subtitle.mb-3{ text-wrap-style: pretty; } #featured-products-template--15646729404510__featured_products_UzBcKF .product-item.splide__slide{ border:none; padding:0!important; margin-bottom:0!important; height:100%; } #featured-products-template--15646729404510__featured_products_UzBcKF .product-item.splide__slide > div{ flex-direction:column; display:flex; } #featured-products-template--15646729404510__featured_products_UzBcKF .product-item.splide__slide .btn{ margin-top:auto; } @media screen and (max-width: 992px) { #featured-products-template--15646729404510__featured_products_UzBcKF .splide__slide p.subtitle.mb-3, #featured-products-template--15646729404510__featured_products_UzBcKF .splide__slide .btn { font-size:.8rem; } #featured-products-template--15646729404510__featured_products_UzBcKF .product-item.splide__slide .btn{ margin-top:unset; } #featured-products-template--15646729404510__featured_products_UzBcKF .product-item.splide__slide > div{ justify-content:center; } } </style> <section id="featured-products-template--15646729404510__featured_products_UzBcKF" class="featured-products text-center pt-12 pb-9 mt-0 mb-0 d-md-block d-lg-block " style="background-color: #fdf8f2"> <div class=""> <div class="featured-products__title-container"> <h2 class="title mb-4 h2" style="color: #807db6" > Trending Gift Boxes </h2> <h4 class="caption px-8 px-lg-0 mb-4 h4" > </h4> </div> <ul class="product-list list-unstyled row mx-n3 mx-lg-n4 mb-0"> <div class="bfcm-product-card"> <a href="/products/ice-cream-parlor-gift-box" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Ice_Cream_Parlor_Gift_Box-549_500x.jpg?v=1732465264" alt="Ice Cream Parlor Gift Box" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/ice-cream-parlor-gift-box"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6955936940126" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/ice-cream-parlor-gift-box">Ice Cream Parlor Gift Box</a></h3> <a class="product-card-link-item" href="/products/ice-cream-parlor-gift-box"><div class="bfcm-product-card__pricing product-price" data-original-price="4100" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $41 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/ice-cream-parlor-gift-box" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40535055761502"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <a href="/products/burst-of-flavors-gift-box" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Burst_of_Flavor_Gift_Box-542_500x.jpg?v=1744312028" alt="Burst of Flavor Gift Box" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/burst-of-flavors-gift-box"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6955937202270" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/burst-of-flavors-gift-box">Burst of Flavor Gift Box</a></h3> <a class="product-card-link-item" href="/products/burst-of-flavors-gift-box"><div class="bfcm-product-card__pricing product-price" data-original-price="4100" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $41 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/burst-of-flavors-gift-box" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40535056482398"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <a href="/products/atlantic-city-classics-gift-box" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Atlantic_City_Classics_Gift_Box-603_500x.jpg?v=1732484651" alt="Atlantic City Classics Gift Box" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/atlantic-city-classics-gift-box"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6975612289118" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/atlantic-city-classics-gift-box">Atlantic City Classics Gift Box</a></h3> <a class="product-card-link-item" href="/products/atlantic-city-classics-gift-box"><div class="bfcm-product-card__pricing product-price" data-original-price="6500" data-current-discount="0.1"> <span data-qty-update-compare-price class="bfcm-product-card__compare-price"> $77 </span> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $65 </span> <span class="discount-dollar-badge bfcm-product-card__discount d-none"> SAVE $12 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/atlantic-city-classics-gift-box" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40587678613598"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> <div class="bfcm-product-card"> <a href="/products/old-fashioned-banana-split-sampler-pack-gift-box" class="bfcm-product-card__image-wrapper"> <img draggable="false" src="//taffy.com/cdn/shop/files/Old_Fashioned_Banana_Split_Sampler_Gift_Box-594_500x.jpg?v=1732479899" alt="Old Fashioned Banana Split Sampler Gift Box" class="bfcm-product-card__image" loading="lazy" > </a> <div class="bfcm-product-card__reviews"> <a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack-gift-box"><style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered sm-review-badge "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6955909677150" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script></a> </div> <h3 class="bfcm-product-card__title"><a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack-gift-box">Old Fashioned Banana Split Sampler Gift Box</a></h3> <a class="product-card-link-item" href="/products/old-fashioned-banana-split-sampler-pack-gift-box"><div class="bfcm-product-card__pricing product-price" data-original-price="4700" data-current-discount="0.1"> <span data-qty-update-current-price style="color:black;font-family:Apparat;font-weight:700;font-size: 18px;"> $47 </span> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Function to update the discount dollar badge based on the discount percentage function updateDiscountDollarBadge() { // Get all product cards on the page const productCards = document.querySelectorAll('.bfcm-product-card__pricing'); productCards.forEach(card => { const discountTag = card.querySelector('.bfcm-product-card__discount'); const discountDollarBadge = card.querySelector('.discount-dollar-badge'); // Only proceed if both elements exist if (discountTag && discountDollarBadge) { // Get the discount percentage from the discount tag const discountAmountEl = discountTag.querySelector('.discount-amount'); if (discountAmountEl) { const discountPercentage = parseFloat(discountAmountEl.textContent); // Get the original price let originalPrice = 0; const originalPriceEl = card.querySelector('.bfcm-product-card__compare-price'); if (originalPriceEl) { // Extract the numeric value from the price string (e.g., "$100.00" -> 100.00) originalPrice = parseFloat(originalPriceEl.textContent.replace(/[^0-9.]/g, '')); } else { // If no compare price element, use the data attribute originalPrice = parseFloat(card.getAttribute('data-original-price') || 0); } // Calculate the savings amount const savingsAmount = (originalPrice * discountPercentage / 100).toFixed(2); // Update the discount dollar badge discountDollarBadge.textContent = 'SAVE $' + savingsAmount; } } }); } // Set up a MutationObserver to watch for changes to the discount amount const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' || mutation.type === 'characterData') { updateDiscountDollarBadge(); } }); }); // Observe all discount amount elements const discountAmounts = document.querySelectorAll('.discount-amount'); discountAmounts.forEach(el => { observer.observe(el, { childList: true, characterData: true, subtree: true }); }); // Initial update updateDiscountDollarBadge(); }); </script></a> <div class="bfcm-product-card__controls"> <div class="bfcm-product-card__buttons"> <a href="/products/old-fashioned-banana-split-sampler-pack-gift-box" class="bfcm-product-card__view-btn"> VIEW </a> <form method="post" action="/cart/add" class="bfcm-product-card__add-form" onsubmit="return onSubmitAtcForm(this, event)"> <input type="hidden" name="id" value="40534949462110"> <button type="submit" class="btn-atc bfcm-product-card__add-btn " > ADD TO CART </button> </form> </div> </div> </div> <script> function updateVariantDetails(selectElement, productId) { const selectedOption = selectElement.options[selectElement.selectedIndex]; const newVariantId = selectedOption.value; const form = selectElement.closest('.bfcm-product-card').querySelector('.bfcm-product-card__add-form'); const hiddenInput = form.querySelector('input[name="id"]'); hiddenInput.value = newVariantId; const priceElement = document.getElementById(`price-${productId}`); const comparePriceElement = document.getElementById(`compare-price-${productId}`); const newPrice = selectedOption.getAttribute('data-price'); const newComparePrice = selectedOption.getAttribute('data-compare-price'); if (priceElement) { priceElement.textContent = newPrice; } if (comparePriceElement) { if (newComparePrice && newComparePrice !== 'null') { comparePriceElement.textContent = newComparePrice; comparePriceElement.style.display = 'inline'; } else { comparePriceElement.style.display = 'none'; } } } function onSubmitAtcForm(form, event) { const variantId = form.querySelector('input[name="id"]').value; if (!variantId) { event.preventDefault(); alert('Please select a valid variant.'); return false; } return true; } </script> </ul> <a class="btn px-8 px-lg-15 mt-6 mb-0 font-family-headings fs-5 btn-primary" href="/collections/gifts"> Shop All Gifts </a> </div> </section> <script> document.addEventListener("DOMContentLoaded", function() { let elements = [...document.querySelectorAll(".subtitle.test.text-muted.small.mt-3.mb-n1")]; elements.forEach((el) => { if (el.innerText == '4 Tubes | $56') { el.innerHTML = "4 Tubes | <strike>$56</strike> | $52 | ($13 Each)" } }); }); </script> <style> #shopify-section-template--15646729404510__featured_products_UzBcKF .row-cols-xxl-4 > * {width: 100%;} #shopify-section-template--15646729404510__featured_products_UzBcKF .row-cols-xxl-3 > * {width: 100%;} #shopify-section-template--15646729404510__featured_products_UzBcKF .carousel-controls {display: none;} #shopify-section-template--15646729404510__featured_products_UzBcKF .product-item-title {text-align: center;} #shopify-section-template--15646729404510__featured_products_UzBcKF .badge {display: none;} </style></div> </main> <!-- BEGIN sections: footer-group --> <div id="shopify-section-sections--15646727864414__footer" class="shopify-section shopify-section-group-footer-group"> <footer id="footer" class="pt-10 pb-0" style="background-color: #fffff4;"> <div class="container"> <div id="footer-blocks" class="row position-relative"> <div class="footer-block col-lg mb-10" > <h3 class="title mb-5 h4"> Shop </h3> <div class=""> <ul class="nav flex-column mb-0"> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/collections/all" > All Flavors </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/collections/sampler-packs" > Samplers </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/collections/bundles" > Bundles </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/collections/gifts" > Gifts </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/products/g-o-a-t-foods-gift-card" > Gift Cards </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/corporate-gifting" > Corporate Gifts & Events </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/collections/the-greatest-of-all-time" > Shop Our Brands </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/products/paid-membership" > Membership </a> </li> </ul> </div> </div> <div class="footer-block col-lg mb-10" > <h3 class="title mb-5 h4"> Help & Info </h3> <div class=""> <ul class="nav flex-column mb-0"> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/faq" > FAQ </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/tracking" > Track Order </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/shipping-policy" > Shipping Policy </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/returns-and-refund-policy" > Returns & Refunds Policy </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://taffy.gorgias.help/en-US" > Help Center </a> </li> </ul> </div> </div> <div class="footer-block col-lg mb-10" > <h3 class="title mb-5 h4"> Our Stores </h3> <div class=""> <ul class="nav flex-column mb-0"> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://licorice.com" > Licorice.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://pretzels.com" > Pretzels.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://caramels.com" > Caramels.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://chocolate.com" > Chocolate.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://cupcakes.com" > Cupcakes.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://Truffles.com" > Truffles.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://cookies.com" > Cookies.com </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://cashews.com" > Cashews.com </a> </li> </ul> </div> </div> <div class="footer-block col-lg mb-10" > <h3 class="title mb-5 h4"> Our Company </h3> <div class=""> <ul class="nav flex-column mb-0"> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/about" > About Us </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/terms-conditions" > Terms & Conditions </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="/pages/privacy-policy" > Privacy Policy </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="https://faire.com/direct/licorice" > Wholesale </a> </li> <li class="nav-item"> <a class="nav-link px-0 py-3" href="tel:5614755908" > 561-475-5908 </a> </li> </ul> </div> </div> </div> <div class="social-icons-wrapper mt-n2 mb-8"> <ul class="social-icons nav d-inline-flex mb-0" aria-label="Social media links"> <li class="nav-item p-2"> <a class="nav-link" href="https://www.facebook.com/taffydotcom" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Facebook" aria-label="Facebook"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="icon-social-facebook " viewBox="0 0 24 24" fill="currentColor"> <path d="M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.32l-.53 3.5h-2.8V24C19.62 23.1 24 18.1 24 12.07"/> </svg> </a> </li> <li class="nav-item p-2"> <a class="nav-link" href="https://www.instagram.com/taffydotcom" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Instagram" aria-label="Instagram"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="icon-social-instagram " viewBox="0 0 24 24" fill="currentColor"> <path d="M16.98 0a6.9 6.9 0 0 1 5.08 1.98A6.94 6.94 0 0 1 24 7.02v9.96c0 2.08-.68 3.87-1.98 5.13A7.14 7.14 0 0 1 16.94 24H7.06a7.06 7.06 0 0 1-5.03-1.89A6.96 6.96 0 0 1 0 16.94V7.02C0 2.8 2.8 0 7.02 0h9.96zm.05 2.23H7.06c-1.45 0-2.7.43-3.53 1.25a4.82 4.82 0 0 0-1.3 3.54v9.92c0 1.5.43 2.7 1.3 3.58a5 5 0 0 0 3.53 1.25h9.88a5 5 0 0 0 3.53-1.25 4.73 4.73 0 0 0 1.4-3.54V7.02a5 5 0 0 0-1.3-3.49 4.82 4.82 0 0 0-3.54-1.3zM12 5.76c3.39 0 6.2 2.8 6.2 6.2a6.2 6.2 0 0 1-12.4 0 6.2 6.2 0 0 1 6.2-6.2zm0 2.22a3.99 3.99 0 0 0-3.97 3.97A3.99 3.99 0 0 0 12 15.92a3.99 3.99 0 0 0 3.97-3.97A3.99 3.99 0 0 0 12 7.98zm6.44-3.77a1.4 1.4 0 1 1 0 2.8 1.4 1.4 0 0 1 0-2.8z"/> </svg> </a> </li> <li class="nav-item p-2"> <a class="nav-link" href="mailto:[email protected]?subject=I%20have%20a%20question!" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Email" aria-label="Email"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="icon-social-email " viewBox="0 0 16 16" fill="currentColor"> <path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z"/> </svg> </a> </li> </ul> </div> </div> <div id="footer-copyright" class="bg-primary text-white py-6"> <div class="container"> <p class="mb-0"> © 2025 Taffy.com. All rights reserved. </p> </div> </div> </footer> </div> <!-- END sections: footer-group --> <style data-shopify> .skinny-banner { text-align: center; padding: 7px 6px 8px 6px; display: flex; align-items: center; justify-content: center; vertical-align: middle; font-family: "Apparat"; font-weight: 700; } .continue-checkout-container { display: flex; gap: 10px; } .continue-checkout-container .btn-continue { width: 110px !important; text-align: center; font-family: "apparat"; font-size: 12px; font-style: normal; font-weight: 700; background: white; text-decoration: none !important; text-transform: uppercase; color: #7F7DB6; line-height: 14px; } .btn-continue-no-items { background: white; color: black; margin-top: 15px; text-transform: uppercase; } .btn-continue-no-items:hover { background: #ea0000; } .continue-checkout-container .btn-continue span:last-child { font-size: 18px; } #offcanvas-cart-subtotal span { font-size: 22px; font-family: "Besley"; } .shipping-info-container { margin: 0; width: 100%; display: flex; align-items: center; justify-content: space-between; color: #FFF; font-family: "Besley"; font-size: 13px; font-style: normal; font-weight: 700; line-height: normal; text-transform: uppercase; margin-top: 5px; margin-bottom: 10px; } #offcanvas-cart .btn-close { display: flex; align-items: center; justify-content: center; } #offcanvas-cart .btn-checkout-shop-pay { display: flex; align-items: center; justify-content: center; color: var(--White, #FFF); font-family: "Apparat"; font-size: 12px; font-style: normal; font-weight: 400; line-height: 16px; padding: 11px !important; } #offcanvas-cart .btn-checkout[type=submit] { padding: 10px !important; text-transform: uppercase; color: #FFF; font-family: "Apparat"; font-size: 24px; font-weight: 700; } #offcanvas-cart .btn-checkout[type=submit] svg { margin-right: 10px; } #offcanvas-cart .btn-checkout-shop-pay span { margin-right: -1rem; } @media (max-width: 768px) { #offcanvas-cart .product-item-img { width: 75px; height: 75px; } } @media (max-width: 400px) { #offcanvas-cart .btn-checkout[type=submit] { padding: 5px !important; } #offcanvas-cart .product-list .product-item .row { display: flex; } } .offcanvas.offcanvas-end { width: 100%; } #offcanvas-search.offcanvas.offcanvas-end{ width:auto; max-width:550px; } #offcanvas-cart .offcanvas-header, #offcanvas-cart .offcanvas-body { background: white; } #offcanvas-cart .offcanvas-footer { background: #484764; color: white; } #offcanvas-cart { border-radius: 0; margin: 0; background: transparent; display: flex; align-items: center; justify-content: center; flex-direction: row; } .offcanvas-cart-content { position: relative; display: flex; flex-direction: column; height: 100%; width: 450px; max-width: 100%; overflow: hidden; background: #E66285; } .offcanvas-cart__countdown-timer-container { flex-grow: 1; text-align: center; height: 100%; display: flex; align-items: center; justify-content: center; padding: 20px; } @media (max-width: 768px) { .offcanvas-cart__countdown-timer-container { display: none; } .offcanvas-cart-content { position: absolute; right: 0; } } .offcanvas-cart__countdown-timer h2, .offcanvas-cart__countdown-timer h3, .offcanvas-cart__countdown-timer h4 { color: #FFF; text-align: center; font-family: Besley; font-size: 48px; font-style: normal; font-weight: 800; } .offcanvas-cart__countdown-timer h4 { font-size: 24px; } /* text-transform: uppercase; */ .offcanvas-cart__countdown-timer { width: fit-content; } .offcanvas-header { /* flex-direction: column; */ } #offcanvas-cart .product-item-img { width: 100px; height: 100px; border-radius: 4px; border: 1px solid #EEE; } .product-item-price-compare { opacity: .35; } </style> <div id="offcanvas-cart" class="offcanvas offcanvas-end offcanvas-mobile-full " tabindex="-1" aria-labelledby="offcanvas-cart-label"> <div class="offcanvas-cart__countdown-timer-container"> </div> <div class="offcanvas-cart-content"> <div id="free-shipping-bar-" class="free-shipping-bar-container " data-threshold="65"> <div class="free-shipping-bar-wrapper"> <div class="free-shipping-message"> <span id="free-shipping-text-" class="free-shipping-text" data-cart-total="0.0"> <span class="free-shipping-progress"> Add <span class="free-shipping-remaining">$65.00</span> more to unlock <strong>FREE SHIPPING</strong> </span> </span> </div> <div class="progress-bar-container"> <div id="progress-bar-" class="progress-bar" style="width: 0%"> <div class="shipping-icon"> <div class="pulse"></div> <div class="pulse"></div> <div class="pulse"></div> <svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000" preserveAspectRatio="xMidYMid meet"> <g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none"> <path d="M913 3614 c-29 -15 -63 -65 -63 -94 0 -7 7 -27 16 -45 32 -69 -50 -65 1298 -65 1021 0 1216 -2 1216 -14 0 -7 -30 -141 -66 -297 -36 -156 -142 -619 -235 -1029 -93 -410 -171 -755 -174 -767 l-5 -23 -284 0 -284 0 -6 34 c-12 66 -74 171 -136 233 -105 105 -232 157 -380 156 -97 0 -149 -12 -236 -55 -121 -59 -221 -175 -265 -305 l-21 -63 -174 0 c-199 0 -225 -7 -250 -67 -19 -43 -5 -93 33 -123 24 -18 40 -20 209 -20 l183 0 15 -53 c52 -178 225 -331 414 -368 172 -33 376 37 491 167 43 49 99 149 116 208 l12 41 650 2 649 3 18 -60 c66 -221 303 -383 536 -367 219 15 416 166 476 367 l18 60 97 0 c112 0 141 10 163 54 9 17 52 229 97 471 70 382 80 449 75 510 -36 410 -319 744 -724 852 -95 26 -105 27 -490 31 l-394 4 7 26 c47 188 114 509 109 527 -3 12 -19 36 -35 51 l-30 29 -1307 2 c-1172 2 -1310 1 -1339 -13z m3410 -860 c93 -20 236 -90 312 -151 142 -116 238 -282 266 -465 11 -69 9 -84 -62 -465 l-74 -393 -41 0 c-39 0 -41 1 -54 43 -49 166 -186 306 -349 358 -91 29 -231 29 -322 0 -163 -52 -300 -192 -349 -358 l-13 -43 -258 0 -257 0 9 38 c146 646 319 1405 324 1425 l7 27 395 0 c323 0 407 -3 466 -16z m-2368 -1296 c60 -31 114 -86 146 -148 20 -37 24 -60 24 -135 0 -75 -4 -98 -24 -139 -76 -154 -261 -224 -411 -155 -79 37 -125 81 -161 155 -84 170 -3 370 179 439 60 23 185 14 247 -17z m2343 3 c65 -33 118 -87 149 -149 24 -48 28 -69 28 -137 -1 -105 -27 -167 -101 -234 -125 -114 -303 -114 -428 0 -154 140 -136 380 38 497 66 44 97 52 191 48 59 -2 91 -8 123 -25z"/> <path d="M478 3183 c-56 -35 -66 -117 -19 -164 l29 -29 472 0 472 0 29 29 c48 49 34 142 -26 169 -19 9 -148 12 -478 12 -403 -1 -455 -2 -479 -17z"/> <path d="M264 2541 c-44 -27 -60 -77 -41 -124 30 -70 -2 -67 635 -67 l574 0 29 29 c48 49 34 142 -26 169 -19 9 -172 12 -583 12 -532 0 -558 -1 -588 -19z"/> <path d="M70 1913 c-81 -30 -90 -157 -14 -192 18 -8 224 -11 700 -11 l676 0 29 29 c48 49 34 142 -26 169 -19 9 -195 12 -688 11 -364 0 -669 -3 -677 -6z"/> </g> </svg> <div class="shipping-icon-background"></div> </div> </div> </div> </div> <!-- Confetti Container --> <div id="confetti-container-" class="confetti-container "></div> </div> <style> .free-shipping-bar-container { background-color: #f8f9fa; width: 100%; padding: 10px 20px; box-sizing: border-box; position: sticky; top: 0; z-index: 100; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; transition: box-shadow 0.5s ease; } /* No box shadow on the container - removed */ .free-shipping-bar-wrapper { max-width: 600px; margin: 0 auto; padding: 0 30px; } .free-shipping-message { text-align: center; margin-bottom: 8px; font-size: 18px; display: flex; align-items: center; justify-content: center; gap: 8px; } .free-shipping-success { color: #28a745; font-weight: bold; } .free-shipping-progress { color: #212529; } .free-shipping-progress strong { display: inline-block; font-weight: 700; } .free-shipping-remaining { font-weight: bold; color: #dc3545; } .progress-bar-container { height: 20px; background-color: #e9ecef; border-radius: 15px; margin: 15px 0 10px 0; position: relative; /* border: 2px solid #222; */ /* animation: smallglow 2s ease-in-out infinite; */ box-shadow: 0 0 2px #fff, 0 0 4px #FF0404; transition: box-shadow 0.5s ease; } /* Change progress bar container box shadow when shipping goal is reached */ .shipping-goal-reached .progress-bar-container { box-shadow: 0 0 10px rgba(40, 167, 69, 0.5), 0 0 20px rgba(40, 167, 69, 0.3); } .progress-bar { height: 100%; background: linear-gradient(90deg, #b1afe4, #7f7db2); border-radius: 15px; transition: width 0.5s ease-in-out, background 0.5s ease-in-out; position: relative; overflow: visible; } :root { --size: 40px; --pulse-max-size: 60px; } .shipping-icon { padding: 4px; position: absolute; width: var(--size); height: var(--size); top: 50%; right: calc(-1 * var(--size)); transform: translate(-50%,-50%); background: white; /* This becomes the border color */ z-index: 3; user-select: none; border: 2px solid #ddd; border-radius: 100%; display: flex; align-items: center; justify-content: center; /* animation: glow 2s ease-in-out infinite; */ } .shipping-icon svg { z-index: 3; margin-bottom: 4px; height: fit-content; } .shipping-icon-background { /* display: none; */ position: absolute; left: 0; right: 0; top: 0; bottom: 0; width: 100%; height: 100%; background-color: white; border-radius: 100%; } .progress-bar::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient( 45deg, rgba(177, 175, 228, 0.6) 25%, rgba(127, 125, 178, 0.3) 25%, rgba(127, 125, 178, 0.3) 50%, rgba(177, 175, 228, 0.6) 50%, rgba(177, 175, 228, 0.6) 75%, rgba(127, 125, 178, 0.3) 75% ); background-size: 20px 20px; border-radius: 15px; animation: move 1s linear infinite; z-index: 1; } /* Change the progress bar background and animation when shipping goal is reached */ .shipping-goal-reached .progress-bar { background: linear-gradient(90deg, #28a745, #20c997); } .shipping-goal-reached .progress-bar::after { background: linear-gradient( 45deg, rgba(40, 167, 69, 0.4) 25%, rgba(32, 201, 151, 0.2) 25%, rgba(32, 201, 151, 0.2) 50%, rgba(40, 167, 69, 0.4) 50%, rgba(40, 167, 69, 0.4) 75%, rgba(32, 201, 151, 0.2) 75% ); background-size: 20px 20px; } @keyframes move { 0% { background-position: 0 0; } 100% { background-position: 20px 0; } } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-5px); } 60% { transform: translateY(-3px); } } @keyframes smallglow { 0%, 100% { box-shadow: 0 0 1px #fff, 0 0 2px #eb3425; } 50% { box-shadow: 0 0 2px #fff, 0 0 4px #FF0404; } } @keyframes glow { 0%, 100% { box-shadow: 0 0 2px #fff, 0 0 4px #eb3425; } 50% { box-shadow: 0 0 4px #fff, 0 0 8px #FF0404; } } .pulse { position: absolute; z-index: -1; border-radius: 50%; background-color: rgba(234,0,0, 0.6); opacity: 0; animation: pulse-out 4.5s infinite; } .pulse:nth-of-type(2) { animation-delay: 1.5s; } .pulse:nth-of-type(3) { animation-delay: 3s; } /* Change pulse color for success state */ .shipping-goal-reached .pulse { background-color: rgba(40, 167, 69, 0.6); } @keyframes pulse-out { 0% { width: 0; height: 0; opacity: 0.8; } 100% { width: var(--pulse-max-size); height: var(--pulse-max-size); opacity: 0; animation-timing-function: ease-out; } } /* Make the glow effect change when free shipping is achieved */ .free-shipping-success ~ .progress-bar-container .shipping-icon, .shipping-goal-reached .shipping-icon { animation: glow-success 2s ease-in-out infinite; } @keyframes glow-success { 0%, 100% { box-shadow: 0 0 3px #fff, 0 0 6px #20c997; } 50% { box-shadow: 0 0 5px #fff, 0 0 10px #28a745; } } /* Confetti Container */ .confetti-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: hidden; z-index: 1; opacity: 0; } .confetti-container.active { opacity: 1; } /* Confetti Pieces */ .confetti { position: absolute; width: 8px; height: 16px; background-color: #28a745; opacity: 0.8; transform-origin: center; animation: confetti-fall linear forwards; } @keyframes confetti-fall { 0% { transform: translateY(-100px) rotate(0deg); opacity: 1; } 100% { transform: translateY(calc(100vh)) rotate(720deg); opacity: 0; } } </style> <script> (function() { // Get the section ID once when the script loads const sectionId = ''; // Initialize the free shipping bar using Liquid values function initFreeShippingBar() { // Use the exact event handling approach as provided window.addEventListener('updated.ecomify.cart', async () => { try { const res = await fetch('/cart.json'); const data = await res.json(); updateFreeShippingBar(data.total_price / 100.0); } catch (error) { console.error('Error updating free shipping bar:', error); } }); // Add a fallback for redundancy document.addEventListener('cart:updated', async () => { try { const res = await fetch('/cart.json'); const data = await res.json(); updateFreeShippingBar(data.total_price / 100.0); } catch (error) { console.error('Error updating free shipping bar:', error); } }); } // Create confetti animation function createConfetti() { const container = document.getElementById('confetti-container-' + sectionId); if (!container) return; // Clear any existing confetti container.innerHTML = ''; // Create confetti pieces const colors = ['#28a745', '#20c997', '#17a2b8', '#ffc107', '#e83e8c']; const totalConfetti = 100; for (let i = 0; i < totalConfetti; i++) { const confetti = document.createElement('div'); confetti.className = 'confetti'; // Random position const left = Math.random() * 100; // Random color const color = colors[Math.floor(Math.random() * colors.length)]; // Random size const size = (Math.random() * 0.5 + 0.5); // Random rotation const rotation = Math.random() * 360; // Random shape (make some squares) const isSquare = Math.random() > 0.5; // Random animation duration const duration = Math.random() * 3 + 2; // Apply styles confetti.style.left = `${left}%`; confetti.style.backgroundColor = color; confetti.style.width = `${isSquare ? 8 * size : 8 * size}px`; confetti.style.height = `${isSquare ? 8 * size : 16 * size}px`; confetti.style.transform = `rotate(${rotation}deg)`; confetti.style.animationDuration = `${duration}s`; confetti.style.animationDelay = `${Math.random() * 0.5}s`; // Add to container container.appendChild(confetti); } } // Update the free shipping bar based on cart total function updateFreeShippingBar(cartTotalDollars) { const container = document.getElementById('free-shipping-bar-' + sectionId); if (!container) { console.error('Free shipping container not found with ID:', 'free-shipping-bar-' + sectionId); return; } const thresholdDollars = parseFloat(container.dataset.threshold); const thresholdCents = thresholdDollars * 100; const cartTotalCents = Math.round(cartTotalDollars * 100); // Ensure we're using integers for comparison const textElement = document.getElementById('free-shipping-text-' + sectionId); const progressBar = document.getElementById('progress-bar-' + sectionId); const confettiContainer = document.getElementById('confetti-container-' + sectionId); if (!textElement || !progressBar) { console.error('Free shipping elements not found'); return; } // Calculate remaining amount const remainingCents = thresholdCents - cartTotalCents; const remainingDollars = remainingCents / 100; // Update progress bar width - ensure correct calculation let progressPercentage = 0; if (cartTotalCents > 0) { progressPercentage = Math.min((cartTotalCents / thresholdCents) * 100, 100); } progressBar.style.width = progressPercentage + '%'; // Determine if shipping is unlocked based on progress percentage const hasItems = cartTotalCents > 0; const isShippingUnlocked = progressPercentage >= 100 && hasItems; // Check if we just reached 100% const wasShippingUnlocked = container.classList.contains('shipping-goal-reached'); // Log values for debugging (can be removed in production) console.log('Cart Total (cents):', cartTotalCents); console.log('Threshold (cents):', thresholdCents); console.log('Progress %:', progressPercentage); console.log('Is Shipping Unlocked:', isShippingUnlocked); // Update message text and styles if (cartTotalCents <= 0) { // Empty cart case textElement.innerHTML = `<span class="free-shipping-progress">Add <span class="free-shipping-remaining">$${thresholdDollars.toFixed(2)}</span> to unlock <strong>FREE SHIPPING</strong></span>`; container.classList.remove('shipping-goal-reached'); confettiContainer.classList.remove('active'); } else if (isShippingUnlocked) { // Free shipping unlocked case textElement.innerHTML = '<span class="free-shipping-success">🎉 You\'ve unlocked <strong>FREE SHIPPING</strong>!</span>'; container.classList.add('shipping-goal-reached'); // If this is a new unlock, create confetti if (!wasShippingUnlocked) { confettiContainer.classList.add('active'); createConfetti(); // Remove confetti after animation completes setTimeout(() => { confettiContainer.classList.remove('active'); }, 5000); } } else { // Progress towards free shipping case textElement.innerHTML = `<span class="free-shipping-progress">Add <span class="free-shipping-remaining">$${remainingDollars.toFixed(2)}</span> more to unlock <strong>FREE SHIPPING</strong></span>`; container.classList.remove('shipping-goal-reached'); confettiContainer.classList.remove('active'); } // Update data attribute textElement.setAttribute('data-cart-total', cartTotalDollars); } // Initialize when DOM is loaded if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initFreeShippingBar); } else { initFreeShippingBar(); } })(); </script> <div class="offcanvas-header py-4 "> <h2 id="offcanvas-cart-label" class="offcanvas-title h5"> Your Cart </h2> <button class="btn-close " type="button" data-bs-dismiss="offcanvas" aria-label="Close"> </button> </div> <div class="offcanvas-body"> <div id="offcanvas-cart-alert-error" class="offcanvas-cart-alert alert alert-danger fw-500 lh-sm py-3 mb-4" role="alert" hidden> <div class="d-flex align-items-center"> <svg xmlns="http://www.w3.org/2000/svg" class="me-3 flex-shrink-0" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line> </svg> <span> </span> </div> </div> <div id="offcanvas-cart-alert-updated" class="offcanvas-cart-alert alert alert-primary fw-500 py-3 mb-4 d-none" role="alert" hidden> <div class="d-flex align-items-center"> <svg xmlns="http://www.w3.org/2000/svg" class="me-3 flex-shrink-0" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> Cart was successfully updated </div> </div> <div id="offcanvas-cart-empty" class=""> <svg xmlns="http://www.w3.org/2000/svg" class="mb-3" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <circle cx="10" cy="20.5" r="1"/><circle cx="18" cy="20.5" r="1"/><path d="M2.5 2.5h3l2.7 12.4a2 2 0 0 0 2 1.6h7.7a2 2 0 0 0 2-1.6l1.6-8.4H7.1"/> </svg> <p>Your cart is currently empty</p> </div> </div> <style data-shopify> .cart-upsell { font-family: var(--bs-body-font-family); color: #FFFFFF; padding: 17px 17px 0 17px; background: #484764; } .cart-upsell-text-container { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; gap: 0 10px; flex-wrap: wrap; } .cart-upsell-header { margin-bottom: 5px; color: #FFF; font-family: var(--bs-body-font-family); font-size: 16px; font-style: normal; font-weight: 700; line-height: normal; } .cart-upsell-subheader { color: white; font-family: var(--bs-body-font-family); font-size: 12px; font-weight: 500; } .cart-upsell-product { background: #FFFFFF; display: flex; align-items: center; padding: 0 10px; min-height: 83px; } .cart-upsell-product-image { width: 70px; height: 70px; object-fit: cover; margin-right: 10px; } .cart-upsell-product-details { width: fit-content; } .cart-upsell-product-title { color: #000; font-family: var(--bs-body-font-family); font-size: 15px; font-weight: 700; margin: 0; text-transform: uppercase; } .cart-upsell-product-price { color: black; font-family: var(--bs-body-font-family); font-size: 18px; font-weight: 500; margin: 0; } .cart-upsell-product-original-price { color: #888888; text-decoration: line-through; margin-left: 5px; } .cart-upsell-add-button { min-width: 81px; padding: 10px 20px; cursor: pointer; border: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; color: #000; font-family: var(--bs-body-font-family); font-size: 18px; font-weight: 700; background: white; width: 90px; } .cart-upsell-add-button:hover .add-button-circle { background: black; } .cart-upsell-add-button:disabled { opacity: 0.5; cursor: not-allowed; } .spinner { border: 4px solid #f3f3f3; border-top: 4px solid #000000; border-radius: 50%; width: 20px; height: 20px; animation: spin 1s linear infinite; display: none; margin-right: 10px; } .add-button-circle { width: 32px; height: 32px; border: 2px solid black; border-radius: 100%; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @media (max-width: 400px) { .cart-upsell-product-title { font-size: 15px; } .cart-upsell-add-button { margin: 0; padding: 10px; font-size: 16px; } .cart-upsell-subheader { display: none; } .cart-upsell-product-image { width: 50px; height: 50px; } .add-button-circle { width: 25px; height: 25px; padding: 0; } .cart-upsell-product { min-height: unset; } .cart-upsell-header { font-size: 16px; } } .cart-upsell-discount-tag{ background: #25b125; border-radius: 3px; padding: 1px 7px 1px 4px !important; display: inline-flex; align-items: center; justify-content: center; color: white; width: fit-content!important; gap: 5px; font-size:14px; margin-left:6px; } .cart-upsell-product-price{ display: flex; align-items: center; } .cart-upsell-discount-tag svg{ height:16px; width:16px; } </style> <div class="cart-upsell" id="singleProductUpsell" style="display: none;"> <div class="cart-upsell-text-container"> <div class="cart-upsell-header">TODAY ONLY!</div> <div class="cart-upsell-subheader">30% OFF Best Sellers From Our Other Brands</div> </div> <div class="cart-upsell-product"> <img id="upsellProductImage" src="" alt="" class="cart-upsell-product-image"> <div class="cart-upsell-product-details"> <h3 id="upsellProductTitle" class="cart-upsell-product-title"></h3> <p class="cart-upsell-product-price"> </p> </div> <button type="button" id="addSingleUpsellToCartButton" class="cart-upsell-add-button"> <div class="add-button-circle"></div> <span class="button-text">ADD</span> </button> </div> </div> <script> const collectionHandle = 'cross-sell-cart-upsell'; let upsellProduct = null; async function fetchCollectionProducts(collectionHandle) { console.log('Fetching collection products for:', collectionHandle); try { const response = await fetch(`/collections/${collectionHandle}/products.json`); if (!response.ok) throw new Error('Failed to fetch collection'); const data = await response.json(); console.log('Collection products:', data.products); return data.products; } catch (error) { console.error('Error fetching collection:', error); return null; } } async function fetchCartContents() { try { const response = await fetch('/cart.js'); if (!response.ok) throw new Error('Failed to fetch cart contents'); return await response.json(); } catch (error) { console.error('Error fetching cart contents:', error); return null; } } function formatMoney(price) { return '$' + parseFloat(price).toFixed(2); } function calculateCartTotal() { return fetch('/cart.js') .then(response => response.json()) .then(cart => { let total = 0; cart.items.forEach(item => { // Skip order protection product if (item.handle !== 'order-package-protection') { total += item.final_line_price / 100; // Convert cents to dollars } }); return total; }) .catch(error => { console.error('Error fetching cart:', error); return 0; }); } function getProductDiscountGroup(productId) { // Check if discount groups are active and if the product is in any of them const discountGroups = [ { active: false, products: [{"id":7231393202270,"title":"Our 8 Store “All-in-One” Gift Card (Physical)","handle":"g-o-a-t-foods-gift-card","description":"\u003cp\u003e\u003cspan style=\"color: rgb(255, 42, 0);\"\u003e\u003cstrong\u003eThe Greatest Gift Card of All Time\u003c\/strong\u003e\u003c\/span\u003e\u003c\/p\u003e\n\u003cp\u003eGive the greatest confections, snacks and baked goods of all time to those you care about the most. Available in $25, $50 or $100 amounts. Beautifully packaged in an impressive sleeve. Redeemable at any of our eight exclusive stores! \u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eLicorice.com | Caramels.com | Pretzels.com | Taffy.com | Chocolate.com | Cupcakes.com \u003c\/strong\u003eby Dana's Bakery\u003cstrong\u003e | Truffles.com \u003c\/strong\u003eby Wolfgang Puck\u003cstrong\u003e | \u003cmeta charset=\"utf-8\"\u003eCookies.com \u003c\/strong\u003e\u003c\/p\u003e","published_at":"2024-11-22T13:16:59-05:00","created_at":"2024-10-29T12:51:10-04:00","vendor":"Taffy.com","type":"","tags":["gift card","GOAT Gift Card"],"price":2500,"price_min":2500,"price_max":10000,"available":true,"price_varies":true,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":41246728683614,"title":"$25","option1":"$25","option2":null,"option3":null,"sku":"FG-GOATGiftCard-25","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Our 8 Store “All-in-One” Gift Card (Physical) - $25","public_title":"$25","options":["$25"],"price":2500,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":41246728716382,"title":"$50","option1":"$50","option2":null,"option3":null,"sku":"FG-GOATGiftCard-50","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Our 8 Store “All-in-One” Gift Card (Physical) - $50","public_title":"$50","options":["$50"],"price":5000,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":41246728749150,"title":"$100","option1":"$100","option2":null,"option3":null,"sku":"FG-GOATGiftCard-100","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Our 8 Store “All-in-One” Gift Card (Physical) - $100","public_title":"$100","options":["$100"],"price":10000,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/DSC1332.jpg?v=1738180528","\/\/taffy.com\/cdn\/shop\/files\/GOAT_gif2.gif?v=1738180528","\/\/taffy.com\/cdn\/shop\/files\/DSC1370.png?v=1738180528"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/DSC1332.jpg?v=1738180528","options":["Value"],"media":[{"alt":null,"id":23783031504990,"position":1,"preview_image":{"aspect_ratio":1.0,"height":3072,"width":3072,"src":"\/\/taffy.com\/cdn\/shop\/files\/DSC1332.jpg?v=1738180528"},"aspect_ratio":1.0,"height":3072,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/DSC1332.jpg?v=1738180528","width":3072},{"alt":null,"id":23783070990430,"position":2,"preview_image":{"aspect_ratio":1.0,"height":500,"width":500,"src":"\/\/taffy.com\/cdn\/shop\/files\/GOAT_gif2.gif?v=1738180528"},"aspect_ratio":1.0,"height":500,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/GOAT_gif2.gif?v=1738180528","width":500},{"alt":null,"id":23783031537758,"position":3,"preview_image":{"aspect_ratio":1.0,"height":2903,"width":2903,"src":"\/\/taffy.com\/cdn\/shop\/files\/DSC1370.png?v=1738180528"},"aspect_ratio":1.0,"height":2903,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/DSC1370.png?v=1738180528","width":2903}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003e\u003cspan style=\"color: rgb(255, 42, 0);\"\u003e\u003cstrong\u003eThe Greatest Gift Card of All Time\u003c\/strong\u003e\u003c\/span\u003e\u003c\/p\u003e\n\u003cp\u003eGive the greatest confections, snacks and baked goods of all time to those you care about the most. Available in $25, $50 or $100 amounts. Beautifully packaged in an impressive sleeve. Redeemable at any of our eight exclusive stores! \u003c\/p\u003e\n\u003cp\u003e\u003cstrong\u003eLicorice.com | Caramels.com | Pretzels.com | Taffy.com | Chocolate.com | Cupcakes.com \u003c\/strong\u003eby Dana's Bakery\u003cstrong\u003e | Truffles.com \u003c\/strong\u003eby Wolfgang Puck\u003cstrong\u003e | \u003cmeta charset=\"utf-8\"\u003eCookies.com \u003c\/strong\u003e\u003c\/p\u003e"}], percentage: 25 }, { active: true, products: [{"id":6985566617694,"title":"Buttered Cinnamon Sugar Pretzels","handle":"buttered-cinnamon-sugar-twist","description":"\u003cp style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-fragment=\"1\" data-mce-style=\"margin: 0in; margin-bottom: .0001pt;\"\u003e\u003cspan style=\"font-family: Arial; color: black; background: white;\" data-mce-fragment=\"1\" data-mce-style=\"font-family: Arial; color: black; background: white;\"\u003eOur brown sugar cinnamon pretzel makes use of one of the tastiest culinary combinations around. It’s a tribute to sweet tooths everywhere and just what you need to turn your tastebuds into your best friends. Yep, we’re making “dessert pretzels” a thing. \u003c\/span\u003e\u003c\/p\u003e","published_at":"2024-04-08T15:11:41-04:00","created_at":"2024-04-08T15:11:48-04:00","vendor":"Licorice.com","type":"","tags":["exclude_PCG","exclude_rebuy","GOAT","hidden-search","not_recommended","pretzels"],"price":1200,"price_min":1200,"price_max":1200,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":40617509388382,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"FG-CinnSug","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Buttered Cinnamon Sugar Pretzels","public_title":null,"options":["Default Title"],"price":1200,"weight":318,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/IMG_2804.jpg?v=1712603508","\/\/taffy.com\/cdn\/shop\/files\/IMG_3327-Edit.jpg?v=1712603508","\/\/taffy.com\/cdn\/shop\/files\/f857edaf628d064e193ced524d53c9f3.jpg?v=1712603508"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/IMG_2804.jpg?v=1712603508","options":["Title"],"media":[{"alt":null,"id":22816756727902,"position":1,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/IMG_2804.jpg?v=1712603508"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/IMG_2804.jpg?v=1712603508","width":2000},{"alt":null,"id":22816756760670,"position":2,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/IMG_3327-Edit.jpg?v=1712603508"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/IMG_3327-Edit.jpg?v=1712603508","width":2000},{"alt":null,"id":22816756826206,"position":3,"preview_image":{"aspect_ratio":1.196,"height":1586,"width":1897,"src":"\/\/taffy.com\/cdn\/shop\/files\/f857edaf628d064e193ced524d53c9f3.jpg?v=1712603508"},"aspect_ratio":1.196,"height":1586,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/f857edaf628d064e193ced524d53c9f3.jpg?v=1712603508","width":1897}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-fragment=\"1\" data-mce-style=\"margin: 0in; margin-bottom: .0001pt;\"\u003e\u003cspan style=\"font-family: Arial; color: black; background: white;\" data-mce-fragment=\"1\" data-mce-style=\"font-family: Arial; color: black; background: white;\"\u003eOur brown sugar cinnamon pretzel makes use of one of the tastiest culinary combinations around. It’s a tribute to sweet tooths everywhere and just what you need to turn your tastebuds into your best friends. Yep, we’re making “dessert pretzels” a thing. \u003c\/span\u003e\u003c\/p\u003e"},{"id":7239678328926,"title":"Garlic Parm Pretzels","handle":"garlic-parm-pretzels","description":"\u003cp style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-fragment=\"1\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan data-sheets-userformat='{\"2\":15105,\"3\":{\"1\":0},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":0},\"15\":\"Arial, sans-serif\",\"16\":11}' data-sheets-value='{\"1\":2,\"2\":\"Our Garlic Parm is a love letter to Italy! The pungent, spicy, and herby flavors of garlic meld with the fruity, creamy, and nutty taste of parmesan cheese to create a buttery, crisp, and savory indulgence. Rich, tangy, and salty with the tiniest bit of lemon zest, this twist is a favorite among garlic lovers and those hoping to ward off vampires.\"}' data-sheets-root=\"1\"\u003eOur Garlic Parm Pretzel Twists are a love letter to Italy! The pungent, spicy, and herby flavors of garlic meld with the fruity, creamy, and nutty taste of parmesan cheese to create a buttery, crisp, and savory indulgence. Rich, tangy, and salty with the tiniest bit of lemon zest, this twist is a favorite among garlic lovers and those hoping to ward off vampires.\u003c\/span\u003e\u003cbr\u003e\u003c\/p\u003e","published_at":"2025-01-03T12:45:52-05:00","created_at":"2024-11-12T16:23:50-05:00","vendor":"Licorice.com","type":"","tags":["exclude_PCG","exclude_rebuy","GOAT","hidden-search","not_recommended","pretzels"],"price":1200,"price_min":1200,"price_max":1200,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":41271724638302,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"FG-GarPar","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Garlic Parm Pretzels","public_title":null,"options":["Default Title"],"price":1200,"weight":318,"compare_at_price":null,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/GarlicParm_1_5f21818c-2285-47b6-8b7d-c7da9a29b716.jpg?v=1735930365","\/\/taffy.com\/cdn\/shop\/files\/garlicparm.jpg?v=1731445751"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/GarlicParm_1_5f21818c-2285-47b6-8b7d-c7da9a29b716.jpg?v=1735930365","options":["Title"],"media":[{"alt":null,"id":23753896558686,"position":1,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/GarlicParm_1_5f21818c-2285-47b6-8b7d-c7da9a29b716.jpg?v=1735930365"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/GarlicParm_1_5f21818c-2285-47b6-8b7d-c7da9a29b716.jpg?v=1735930365","width":2000},{"alt":null,"id":23753900064862,"position":2,"preview_image":{"aspect_ratio":1.0,"height":938,"width":938,"src":"\/\/taffy.com\/cdn\/shop\/files\/garlicparm.jpg?v=1731445751"},"aspect_ratio":1.0,"height":938,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/garlicparm.jpg?v=1731445751","width":938}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-style=\"margin: 0in; margin-bottom: .0001pt;\" data-mce-fragment=\"1\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan data-sheets-userformat='{\"2\":15105,\"3\":{\"1\":0},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":0},\"15\":\"Arial, sans-serif\",\"16\":11}' data-sheets-value='{\"1\":2,\"2\":\"Our Garlic Parm is a love letter to Italy! The pungent, spicy, and herby flavors of garlic meld with the fruity, creamy, and nutty taste of parmesan cheese to create a buttery, crisp, and savory indulgence. Rich, tangy, and salty with the tiniest bit of lemon zest, this twist is a favorite among garlic lovers and those hoping to ward off vampires.\"}' data-sheets-root=\"1\"\u003eOur Garlic Parm Pretzel Twists are a love letter to Italy! The pungent, spicy, and herby flavors of garlic meld with the fruity, creamy, and nutty taste of parmesan cheese to create a buttery, crisp, and savory indulgence. Rich, tangy, and salty with the tiniest bit of lemon zest, this twist is a favorite among garlic lovers and those hoping to ward off vampires.\u003c\/span\u003e\u003cbr\u003e\u003c\/p\u003e"},{"id":6985569042526,"title":"Classic Butter Caramels","handle":"butter-caramel","description":"\u003cp class=\"p1\"\u003e\u003cspan class=\"s1\"\u003eButter goes on everything……..even caramel! This one-two-punch of rich and creamy confectionery creativity melts in your mouth and pleases the palate. It’s the ideal after-dinner treat. Or before dinner. Or as dinner.\u003c\/span\u003e\u003c\/p\u003e\n\u003cp class=\"p1\"\u003e\u003cspan class=\"s1\"\u003e\u003cmeta charset=\"utf-8\"\u003e\n\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Butterscotch, for many, is the flavor most synonymous with childhood, and we crafted this caramel carefully to honor that nostalgia. Flavors of browned butter, sugar, and molasses mix with creamy, small-batch caramel to provide a compact dessert that always delivers. Butterscotch is a best-seller among those who just can’t seem to keep their hands out of the candy jar.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":4073230},\"15\":\"Arial, sans-serif\",\"16\":10}'\u003eEach tube is filled with 12 oz of caramels.\u003c\/span\u003e\u003c\/span\u003e\u003c\/p\u003e","published_at":"2024-04-08T15:15:28-04:00","created_at":"2024-04-08T15:15:45-04:00","vendor":"Caramels.com","type":"Heavenly Caramels","tags":["caramels","exclude_PCG","exclude_rebuy","GOAT","hidden-search","not_recommended"],"price":1800,"price_min":1800,"price_max":1800,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":40617521479774,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"FG-CAR-Butter","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Classic Butter Caramels","public_title":null,"options":["Default Title"],"price":1800,"weight":907,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/ButterCaramel_9d6ab875-4f51-4beb-a5eb-f189d210bc93.jpg?v=1743441451","\/\/taffy.com\/cdn\/shop\/files\/TubeOutputArtboard5_21d7e04b-b3c6-40b7-ba4b-07b2b829e4bb.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-4_5f1a8216-4fb7-485f-8daa-b91708629a21.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-3_e41072cf-63b7-44bc-a394-9adbbdaba5d9.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/0001_Caramel_2_d74de322-19e7-462d-b8a0-a17dc79b890d.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/0000_Caramel_1_6983ce6e-c68b-4d84-95e8-691fe6a5ddf6.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-2_1c689cca-8d14-48a8-ba32-1d8498191c5f.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-6_e8413538-08b9-404b-8200-135c525e0475.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-5_72b75d94-c4eb-47ea-903a-62da674b29cb.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/0002_Caramel_3_1a458711-6e0f-49d9-8dd1-a3179a093e5c.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/CaramelsLabelIngredients.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube-1_b3a6e5ba-46ca-48e0-9882-09fa0ea344ad.jpg?v=1712603745","\/\/taffy.com\/cdn\/shop\/files\/Tube_ee1a3c10-3831-4410-97fc-0c9e91c804ec.jpg?v=1712603745"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/ButterCaramel_9d6ab875-4f51-4beb-a5eb-f189d210bc93.jpg?v=1743441451","options":["Title"],"media":[{"alt":null,"id":22816777601118,"position":1,"preview_image":{"aspect_ratio":1.0,"height":3608,"width":3608,"src":"\/\/taffy.com\/cdn\/shop\/files\/ButterCaramel_9d6ab875-4f51-4beb-a5eb-f189d210bc93.jpg?v=1743441451"},"aspect_ratio":1.0,"height":3608,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/ButterCaramel_9d6ab875-4f51-4beb-a5eb-f189d210bc93.jpg?v=1743441451","width":3608},{"alt":null,"id":22816777633886,"position":2,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/TubeOutputArtboard5_21d7e04b-b3c6-40b7-ba4b-07b2b829e4bb.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/TubeOutputArtboard5_21d7e04b-b3c6-40b7-ba4b-07b2b829e4bb.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777666654,"position":3,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-4_5f1a8216-4fb7-485f-8daa-b91708629a21.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-4_5f1a8216-4fb7-485f-8daa-b91708629a21.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777699422,"position":4,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-3_e41072cf-63b7-44bc-a394-9adbbdaba5d9.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-3_e41072cf-63b7-44bc-a394-9adbbdaba5d9.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777732190,"position":5,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/0001_Caramel_2_d74de322-19e7-462d-b8a0-a17dc79b890d.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/0001_Caramel_2_d74de322-19e7-462d-b8a0-a17dc79b890d.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777764958,"position":6,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/0000_Caramel_1_6983ce6e-c68b-4d84-95e8-691fe6a5ddf6.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/0000_Caramel_1_6983ce6e-c68b-4d84-95e8-691fe6a5ddf6.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777797726,"position":7,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-2_1c689cca-8d14-48a8-ba32-1d8498191c5f.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-2_1c689cca-8d14-48a8-ba32-1d8498191c5f.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777830494,"position":8,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-6_e8413538-08b9-404b-8200-135c525e0475.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-6_e8413538-08b9-404b-8200-135c525e0475.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777863262,"position":9,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-5_72b75d94-c4eb-47ea-903a-62da674b29cb.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-5_72b75d94-c4eb-47ea-903a-62da674b29cb.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777896030,"position":10,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/0002_Caramel_3_1a458711-6e0f-49d9-8dd1-a3179a093e5c.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/0002_Caramel_3_1a458711-6e0f-49d9-8dd1-a3179a093e5c.jpg?v=1712603745","width":2000},{"alt":null,"id":22816777928798,"position":11,"preview_image":{"aspect_ratio":1.0,"height":938,"width":938,"src":"\/\/taffy.com\/cdn\/shop\/files\/CaramelsLabelIngredients.jpg?v=1712603745"},"aspect_ratio":1.0,"height":938,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/CaramelsLabelIngredients.jpg?v=1712603745","width":938},{"alt":null,"id":22816777994334,"position":12,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-1_b3a6e5ba-46ca-48e0-9882-09fa0ea344ad.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube-1_b3a6e5ba-46ca-48e0-9882-09fa0ea344ad.jpg?v=1712603745","width":2000},{"alt":null,"id":22816778027102,"position":13,"preview_image":{"aspect_ratio":1.0,"height":2000,"width":2000,"src":"\/\/taffy.com\/cdn\/shop\/files\/Tube_ee1a3c10-3831-4410-97fc-0c9e91c804ec.jpg?v=1712603745"},"aspect_ratio":1.0,"height":2000,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Tube_ee1a3c10-3831-4410-97fc-0c9e91c804ec.jpg?v=1712603745","width":2000}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp class=\"p1\"\u003e\u003cspan class=\"s1\"\u003eButter goes on everything……..even caramel! This one-two-punch of rich and creamy confectionery creativity melts in your mouth and pleases the palate. It’s the ideal after-dinner treat. Or before dinner. Or as dinner.\u003c\/span\u003e\u003c\/p\u003e\n\u003cp class=\"p1\"\u003e\u003cspan class=\"s1\"\u003e\u003cmeta charset=\"utf-8\"\u003e\n\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Butterscotch, for many, is the flavor most synonymous with childhood, and we crafted this caramel carefully to honor that nostalgia. Flavors of browned butter, sugar, and molasses mix with creamy, small-batch caramel to provide a compact dessert that always delivers. Butterscotch is a best-seller among those who just can’t seem to keep their hands out of the candy jar.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":4073230},\"15\":\"Arial, sans-serif\",\"16\":10}'\u003eEach tube is filled with 12 oz of caramels.\u003c\/span\u003e\u003c\/span\u003e\u003c\/p\u003e"},{"id":7239251525726,"title":"Strawberry Sour Twists Licorice","handle":"strawberry-sour-twists-licorice","description":"\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Paying homage to the quintessential childhood candies, our Strawberry Sour Twists conjure up flavors of bubble gum, jawbreakers, and lollipops. Mixing and matching a juicy fruitiness with a subtle sourness, they’re a smash hit among candy connoisseurs who appreciate the palate powerhouse of sugar and tart.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":2039583},\"15\":\"Calibri, sans-serif\",\"16\":10}'\u003ePaying homage to the quintessential childhood candies, our Strawberry Sour Twists conjure up flavors of bubble gum, jawbreakers, and lollipops. Mixing and matching a juicy fruitiness with a subtle sourness, these licorice twists are a smash hit among candy connoisseurs who appreciate the palate powerhouse of sugar and tart.\u003c\/span\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003eEach tube is filled with 1 pound of licorice.\u003cbr\u003e\u003c\/p\u003e","published_at":"2024-11-18T19:17:36-05:00","created_at":"2024-11-11T13:47:29-05:00","vendor":"Licorice.com","type":"DARREL LEA","tags":["exclude_PCG","exclude_rebuy","GOAT","hidden-search","licorice","not_recommended"],"price":1600,"price_min":1600,"price_max":1600,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":41270203809886,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"FG-SSourTwist","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Strawberry Sour Twists Licorice","public_title":null,"options":["Default Title"],"price":1600,"weight":726,"compare_at_price":null,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/Strawberry_Sour_Twist.jpg?v=1731350612","\/\/taffy.com\/cdn\/shop\/files\/strawberry_sour_tube.jpg?v=1743441451","\/\/taffy.com\/cdn\/shop\/files\/strawberrysourtwists_a35bdf55-6758-49b7-a6b4-37a785abf4e7.jpg?v=1731350771"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/Strawberry_Sour_Twist.jpg?v=1731350612","options":["Title"],"media":[{"alt":null,"id":23750768132190,"position":1,"preview_image":{"aspect_ratio":1.0,"height":1500,"width":1500,"src":"\/\/taffy.com\/cdn\/shop\/files\/Strawberry_Sour_Twist.jpg?v=1731350612"},"aspect_ratio":1.0,"height":1500,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Strawberry_Sour_Twist.jpg?v=1731350612","width":1500},{"alt":null,"id":23750775504990,"position":2,"preview_image":{"aspect_ratio":1.122,"height":1483,"width":1664,"src":"\/\/taffy.com\/cdn\/shop\/files\/strawberry_sour_tube.jpg?v=1743441451"},"aspect_ratio":1.122,"height":1483,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/strawberry_sour_tube.jpg?v=1743441451","width":1664},{"alt":null,"id":23750776160350,"position":3,"preview_image":{"aspect_ratio":1.0,"height":938,"width":938,"src":"\/\/taffy.com\/cdn\/shop\/files\/strawberrysourtwists_a35bdf55-6758-49b7-a6b4-37a785abf4e7.jpg?v=1731350771"},"aspect_ratio":1.0,"height":938,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/strawberrysourtwists_a35bdf55-6758-49b7-a6b4-37a785abf4e7.jpg?v=1731350771","width":938}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Paying homage to the quintessential childhood candies, our Strawberry Sour Twists conjure up flavors of bubble gum, jawbreakers, and lollipops. Mixing and matching a juicy fruitiness with a subtle sourness, they’re a smash hit among candy connoisseurs who appreciate the palate powerhouse of sugar and tart.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":2039583},\"15\":\"Calibri, sans-serif\",\"16\":10}'\u003ePaying homage to the quintessential childhood candies, our Strawberry Sour Twists conjure up flavors of bubble gum, jawbreakers, and lollipops. Mixing and matching a juicy fruitiness with a subtle sourness, these licorice twists are a smash hit among candy connoisseurs who appreciate the palate powerhouse of sugar and tart.\u003c\/span\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003eEach tube is filled with 1 pound of licorice.\u003cbr\u003e\u003c\/p\u003e"},{"id":7239249690718,"title":"Watermelon Sour Twists Licorice","handle":"watermelon-sour-twists-licorice","description":"\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan\u003e\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Our Watermelon Sour Twists allow you to carry summer in your pocket. These candies start as brooding and bitter before softening into a sweet and playful bite. The result is a delicate combination of sour and sugar that tangos across your taste buds to offer an experience that is both lip-smacking and mouth-watering. These handcrafted handfuls are a top-ten selection for tart and tangy fanatics.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":2039583},\"15\":\"Calibri, sans-serif\",\"16\":10}'\u003eOur Watermelon Sour Twists allow you to carry summer in your pocket. These licorice candies start with tart before softening into a sweet and deliciously watermelon-packed bite. The result is a delicate combination of sour and sugar that tangos across your taste buds to offer an experience that is both lip-smacking and mouth-watering. These handcrafted handfuls are a top-ten selection for tart and tangy fanatics.\u003c\/span\u003e\u003c\/span\u003e\u003c\/p\u003e\n\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003eEach tube is filled with 1 pound of licorice.\u003cbr\u003e\u003c\/p\u003e","published_at":"2024-12-05T16:10:10-05:00","created_at":"2024-11-11T13:45:31-05:00","vendor":"Licorice.com","type":"DARREL LEA","tags":["exclude_PCG","exclude_rebuy","GOAT","hidden-search","licorice","not_recommended"],"price":1600,"price_min":1600,"price_max":1600,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":41270199353438,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"FG-WSourTwist","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Watermelon Sour Twists Licorice","public_title":null,"options":["Default Title"],"price":1600,"weight":726,"compare_at_price":null,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/taffy.com\/cdn\/shop\/files\/Watermelon_Sour_Twist.jpg?v=1731350612","\/\/taffy.com\/cdn\/shop\/files\/watermelon_sour_tube.jpg?v=1731350762","\/\/taffy.com\/cdn\/shop\/files\/watermelonsourtwists.jpg?v=1731350771"],"featured_image":"\/\/taffy.com\/cdn\/shop\/files\/Watermelon_Sour_Twist.jpg?v=1731350612","options":["Title"],"media":[{"alt":null,"id":23750768197726,"position":1,"preview_image":{"aspect_ratio":1.0,"height":1500,"width":1500,"src":"\/\/taffy.com\/cdn\/shop\/files\/Watermelon_Sour_Twist.jpg?v=1731350612"},"aspect_ratio":1.0,"height":1500,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/Watermelon_Sour_Twist.jpg?v=1731350612","width":1500},{"alt":null,"id":23750775439454,"position":2,"preview_image":{"aspect_ratio":1.122,"height":1483,"width":1664,"src":"\/\/taffy.com\/cdn\/shop\/files\/watermelon_sour_tube.jpg?v=1731350762"},"aspect_ratio":1.122,"height":1483,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/watermelon_sour_tube.jpg?v=1731350762","width":1664},{"alt":null,"id":23750776062046,"position":3,"preview_image":{"aspect_ratio":1.0,"height":938,"width":938,"src":"\/\/taffy.com\/cdn\/shop\/files\/watermelonsourtwists.jpg?v=1731350771"},"aspect_ratio":1.0,"height":938,"media_type":"image","src":"\/\/taffy.com\/cdn\/shop\/files\/watermelonsourtwists.jpg?v=1731350771","width":938}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan\u003e\u003cspan data-sheets-root=\"1\" data-sheets-value='{\"1\":2,\"2\":\"Our Watermelon Sour Twists allow you to carry summer in your pocket. These candies start as brooding and bitter before softening into a sweet and playful bite. The result is a delicate combination of sour and sugar that tangos across your taste buds to offer an experience that is both lip-smacking and mouth-watering. These handcrafted handfuls are a top-ten selection for tart and tangy fanatics.\"}' data-sheets-userformat='{\"2\":15107,\"3\":{\"1\":0},\"4\":{\"1\":2,\"2\":16777215},\"11\":4,\"12\":0,\"14\":{\"1\":2,\"2\":2039583},\"15\":\"Calibri, sans-serif\",\"16\":10}'\u003eOur Watermelon Sour Twists allow you to carry summer in your pocket. These licorice candies start with tart before softening into a sweet and deliciously watermelon-packed bite. The result is a delicate combination of sour and sugar that tangos across your taste buds to offer an experience that is both lip-smacking and mouth-watering. These handcrafted handfuls are a top-ten selection for tart and tangy fanatics.\u003c\/span\u003e\u003c\/span\u003e\u003c\/p\u003e\n\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta charset=\"utf-8\"\u003eEach tube is filled with 1 pound of licorice.\u003cbr\u003e\u003c\/p\u003e"}], percentage: 30 }, { active: false, products: "[]", percentage: 0 } ]; console.log(discountGroups); // Find the first active discount group that contains this product for (const group of discountGroups) { if (group.active && group.products && Array.isArray(group.products) && group.percentage > 0) { // Check if any product in the group has matching ID const productInGroup = group.products.some(product => product && typeof product === 'object' && String(product.id) === String(productId) ); if (productInGroup) { return { inDiscountGroup: true, discountGroupPercentage: group.percentage / 100 // Convert percentage to decimal }; } } } return { inDiscountGroup: false, discountGroupPercentage: 0 }; } async function updateProductDisplay(product) { document.getElementById('upsellProductImage').src = product.images[0]?.src || '/path/to/placeholder-image.jpg'; document.getElementById('upsellProductImage').alt = product.title; document.getElementById('upsellProductTitle').textContent = product.title; // Get cart total for discount calculation const cartTotal = await calculateCartTotal(); // Check if product is in a discount group const { inDiscountGroup, discountGroupPercentage } = getProductDiscountGroup(product.id); console.log('Discount check:', inDiscountGroup, discountGroupPercentage); // Get sitewide discount (only if product is not in a discount group) const sitewideDiscountActive = false; let discountPercentage = 0; let displayPercentage = 0; let finalPrice = 0; // Calculate the price based on priorities const originalPrice = parseFloat(product.variants[0].price); const comparePrice = product.variants[0].compare_at_price || product.variants[0].comparePrice || null; const comparePriceValue = comparePrice ? parseFloat(comparePrice) : null; // Priority 1: Use discount group if product is in one and the group is active if (inDiscountGroup) { discountPercentage = discountGroupPercentage; displayPercentage = discountPercentage * 100; finalPrice = (originalPrice * (1 - discountPercentage)).toFixed(2); } // Priority 2: Use sitewide discount if active else if (sitewideDiscountActive) { // Get the potential sitewide discount discountPercentage = getPotentialDiscount(cartTotal, originalPrice); displayPercentage = discountPercentage * 100; finalPrice = (originalPrice * (1 - discountPercentage)).toFixed(2); } // Priority 3: Use compare_at_price if available else if (comparePriceValue !== null && comparePriceValue > originalPrice) { // Calculate the implicit discount percentage discountPercentage = (comparePriceValue - originalPrice) / comparePriceValue; displayPercentage = Math.round(discountPercentage * 100); finalPrice = originalPrice.toFixed(2); } // No discount applies else { finalPrice = originalPrice.toFixed(2); displayPercentage = null; } // Update price display with discount tag document.querySelector('.cart-upsell-product-price').innerHTML = ` <div class="bfcm-product-card__pricing"> ${discountPercentage > 0 ? `<span class="bfcm-product-card__price product-price-potential" data-original-price="${originalPrice * 100}"> ${formatMoney(finalPrice)} </span> <span class="bfcm-product-card__compare-price"> ${formatMoney(originalPrice)} </span>`: `${comparePriceValue != null ? `<span class="bfcm-product-card__compare-price"> ${formatMoney(comparePriceValue)} </span>` : ''} <span class="bfcm-product-card__price"> ${formatMoney(originalPrice)} </span>`} ${displayPercentage != null ? `<div class="bfcm-product-card__discount discount-tag"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M22.1691 2.20818C22.1538 1.89961 21.9287 1.63707 21.6232 1.57535C21.597 1.57024 21.5711 1.56649 21.5452 1.5641L12.7302 0.692255C12.5253 0.671797 12.3255 0.744082 12.1809 0.888651L1.79037 11.2799C0.231823 12.8384 0.231823 13.789 1.79037 15.3472L8.38394 21.9415C9.08257 22.6405 9.69563 23.1049 10.4178 23.1049C11.1399 23.1049 11.753 22.6391 12.4503 21.9411L22.8425 11.5492C22.9871 11.405 23.059 11.2035 23.0389 10.9999L22.1691 2.20818ZM11.4864 20.9769C11.1587 21.3046 10.6912 21.7407 10.4178 21.7407C10.144 21.7407 9.67619 21.3046 9.34818 20.9769L2.75462 14.3827C1.73548 13.3638 1.73548 13.2633 2.75462 12.2445L12.9181 2.081L20.8636 2.86727L21.6505 10.8131L11.4864 20.9769Z" fill="white"></path> <path d="M7.75496 8.99659L4.65559 12.0956C3.87308 12.8781 3.65827 13.4087 4.55432 14.3047C4.62081 14.3712 4.7081 14.4046 4.79539 14.4046C4.88267 14.4046 4.96996 14.3712 5.03645 14.3047C5.16976 14.1714 5.16976 13.9563 5.03645 13.8226C4.50216 13.2883 4.50864 13.2072 5.13771 12.5777L8.23708 9.47872C8.3704 9.3454 8.3704 9.12991 8.23708 8.99659C8.10376 8.86328 7.88827 8.86328 7.75496 8.99659Z" fill="white"></path> <path d="M8.72515 8.02635L8.44794 8.3039C8.31497 8.43722 8.31497 8.65305 8.44863 8.78602C8.51511 8.85217 8.60206 8.88558 8.68935 8.88558C8.77663 8.88558 8.86392 8.85251 8.93075 8.78534L9.20795 8.5078C9.34093 8.37448 9.34093 8.15865 9.20727 8.02567C9.07395 7.89304 8.85847 7.89236 8.72515 8.02635Z" fill="white"></path> <path d="M16.811 4.00818C15.2525 4.00818 13.9834 5.27657 13.9834 6.83545C13.9834 8.39434 15.2525 9.66273 16.811 9.66273C18.3703 9.66273 19.638 8.39434 19.638 6.83545C19.638 5.27657 18.3699 4.00818 16.811 4.00818ZM16.811 8.29887C16.004 8.29887 15.3473 7.64217 15.3473 6.83545C15.3473 6.02873 16.004 5.37204 16.811 5.37204C17.6188 5.37204 18.2741 6.02873 18.2741 6.83545C18.2741 7.64217 17.6181 8.29887 16.811 8.29887Z" fill="white"></path> </svg> <span class="discount-amount">${Math.round(displayPercentage)}%</span> OFF </div>`:''} </div> `; } async function getNextUpsellProduct(products, currentUpsellId) { const cartContents = await fetchCartContents(); if (!cartContents || !products) return null; const cartProductIds = cartContents.items.map(item => item.product_id); // Get all available products not in cart const availableProducts = products.filter(product => !cartProductIds.includes(product.id) && product.id !== currentUpsellId && product.variants[0]?.available ); if (availableProducts.length > 0) { const randomIndex = Math.floor(Math.random() * availableProducts.length); return availableProducts[randomIndex]; } return null; } async function updateUpsellDisplay() { const products = await fetchCollectionProducts(collectionHandle); const nextProduct = await getNextUpsellProduct(products, upsellProduct?.id); if (nextProduct) { upsellProduct = nextProduct; updateProductDisplay(nextProduct); const addButton = document.getElementById('addSingleUpsellToCartButton'); const buttonText = addButton.querySelector('.button-text'); addButton.disabled = false; buttonText.textContent = 'ADD'; addButton.classList.remove('loading'); const upsellElement = document.getElementById('singleProductUpsell'); upsellElement.style.opacity = '0'; upsellElement.style.display = 'block'; setTimeout(() => { upsellElement.style.transition = 'opacity 0.3s ease-in-out'; upsellElement.style.opacity = '1'; }, 50); } else { document.getElementById('singleProductUpsell').style.display = 'none'; } } async function addToCart() { const addButton = document.getElementById('addSingleUpsellToCartButton'); const buttonText = addButton.querySelector('.button-text'); // Disable button and show loading state addButton.disabled = true; buttonText.textContent = 'Adding...'; addButton.classList.add('loading'); try { const response = await fetch('/cart/add.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ items: [{ id: upsellProduct.variants[0].id, quantity: 1 }] }), }); if (!response.ok) throw new Error('Failed to add item to cart'); window.refreshCartContents(response); bootstrap.Offcanvas.getOrCreateInstance('#offcanvas-cart').show(); // Instead of hiding, update with next upsell product await updateUpsellDisplay(); } catch (error) { console.error('Error adding product to cart:', error); alert('There was an error adding the product to your cart. Please try again.'); // Reset button state on error addButton.disabled = false; buttonText.textContent = 'ADD'; addButton.classList.remove('loading'); } } // In initializeSingleProductUpsell async function initializeSingleProductUpsell() { const products = await fetchCollectionProducts(collectionHandle); const cartContents = await fetchCartContents(); if (!products || !cartContents) { console.error('Failed to initialize upsell'); return; } const cartProductIds = cartContents.items.map(item => item.product_id); const availableProducts = products.filter(product => !cartProductIds.includes(product.id) && product.variants[0]?.available ); if (availableProducts.length > 0) { const randomIndex = Math.floor(Math.random() * availableProducts.length); upsellProduct = availableProducts[randomIndex]; } else { return; } updateProductDisplay(upsellProduct); const addButton = document.getElementById('addSingleUpsellToCartButton'); addButton.disabled = false; addButton.addEventListener('click', addToCart); document.getElementById('singleProductUpsell').style.display = 'block'; } // Add CSS for loading state and transitions const style = document.createElement('style'); style.textContent = ` .cart-upsell { opacity: 1; transition: opacity 0.3s ease-in-out; } .cart-upsell-add-button { position: relative; cursor: pointer; transition: all 0.3s ease; display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 8px 16px; border: none; background: transparent; outline: none; } .add-button-circle { width: 24px; height: 24px; border: 2px solid #000; border-radius: 50%; transition: all 0.3s ease; } .cart-upsell-add-button:hover .add-button-circle { background: #000; } .cart-upsell-add-button.loading { background-color: #cccccc; cursor: not-allowed; } .cart-upsell-add-button:disabled { cursor: not-allowed; opacity: 0.7; } .cart-upsell-add-button .button-text { display: inline-block; font-size: 14px; font-weight: 500; text-transform: uppercase; } `; document.head.appendChild(style); document.addEventListener('DOMContentLoaded', initializeSingleProductUpsell); </script> <style data-shopify> .new-delivery-container { display: grid; grid-template-columns: 50% 50%; align-items: center; justify-content: space-between; margin: 5px 0; gap: 10px; width: calc(100% - 10px); } #cart-delivery-wrapper h4 { color: white; font-size: 12px; margin-top: 10px; } .new-delivery-container svg { height: 100%; width: 100%; } .new-delivery-container svg path:first-of-type { fill: #807db6; } #btn-cart-note-modal, #btn-cart-date-modal { width: 100% !important; padding: 0; } </style> <div id="cart-delivery-wrapper" class=""> <div class="new-delivery-container collapse show"> <button id="btn-cart-note-modal" class="btn btn-link btn-sm py-2 w-100" type="button" onclick="openCartNoteModal(this, event)"> <svg class="cart-icon" width="182" height="40" viewBox="0 0 182 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="1.28182" y="1.43514" width="180.186" height="37.1239" fill="white"/> <rect x="1.28182" y="1.43514" width="180.186" height="37.1239" stroke="#E2E2E2" stroke-width="1.06364"/> <path d="M38.078 10.1028H16.1606C14.3834 10.1028 12.9375 11.4898 12.9375 13.1947V26.7994C12.9375 28.5043 14.3834 29.8914 16.1606 29.8914H38.078C39.8552 29.8914 41.3011 28.5043 41.3011 26.7994V13.1947C41.3011 11.4898 39.8552 10.1028 38.078 10.1028ZM40.0119 13.1947V17.8327H29.6978V15.6683C29.6978 15.4729 29.6015 15.2886 29.438 15.1724C29.274 15.0558 29.0629 15.0202 28.8679 15.0759L24.847 16.2329C24.4138 15.83 23.8646 15.5412 23.2512 15.4213V11.3396H38.0777C39.1445 11.3396 40.0119 12.1716 40.0119 13.1947ZM27.4565 24.0166H25.6218L24.3774 21.032C24.546 20.9253 24.7029 20.8035 24.8473 20.6693L26.2262 21.066L27.4565 24.0166ZM22.6069 16.5959C23.6735 16.5959 24.5408 17.428 24.5408 18.4511C24.5408 19.4742 23.6735 20.3063 22.6069 20.3063C21.5404 20.3063 20.673 19.4742 20.673 18.4511C20.673 17.428 21.5404 16.5959 22.6069 16.5959ZM19.6149 19.5942L16.8053 20.4027V16.4994L19.6149 17.308C19.4673 17.662 19.3838 18.0473 19.3838 18.4511C19.3838 18.8549 19.4673 19.2402 19.6149 19.5942ZM18.9877 21.066L20.3665 20.6693C20.5109 20.8035 20.6679 20.9253 20.8364 21.032L19.592 24.0166H17.7574L18.9877 21.066ZM25.599 19.5942C25.7466 19.2402 25.8301 18.8549 25.8301 18.4511C25.8301 18.0473 25.7466 17.662 25.599 17.308L28.4086 16.4994V20.4024L25.599 19.5942ZM16.1606 11.3396H21.9623V15.4216C21.3489 15.5416 20.7997 15.8303 20.3665 16.2332L16.346 15.0762C16.1513 15.0202 15.9392 15.0561 15.7758 15.1727C15.6124 15.2886 15.516 15.4729 15.516 15.6683V17.8327H14.2268V13.1947C14.2268 12.1716 15.0941 11.3396 16.1606 11.3396ZM14.2268 26.7994V19.0695H15.516V21.2339C15.516 21.4293 15.6124 21.6136 15.7758 21.7298C15.8883 21.8102 16.0237 21.8523 16.1606 21.8523C16.2225 21.8523 16.2851 21.8439 16.346 21.8263L17.4099 21.5202L16.2071 24.4053C16.1274 24.5958 16.1519 24.8116 16.2718 24.9816C16.3917 25.1517 16.5913 25.2534 16.8053 25.2534H20.0284C20.2921 25.2534 20.529 25.0994 20.6269 24.8648L21.9623 21.6621V28.6546H16.1606C15.0941 28.6546 14.2268 27.8225 14.2268 26.7994ZM38.078 28.6546H23.2515V21.6621L24.5869 24.8648C24.6849 25.0994 24.9218 25.2534 25.1854 25.2534H28.4086C28.6226 25.2534 28.8224 25.1517 28.9423 24.9816C29.0622 24.8116 29.0864 24.5958 29.0071 24.4053L27.8039 21.5202L28.8679 21.8263C28.9288 21.8439 28.9913 21.8523 29.0532 21.8523C29.1902 21.8523 29.3256 21.8102 29.438 21.7298C29.6015 21.6136 29.6978 21.4293 29.6978 21.2339V19.0695H40.0119V26.7994C40.0119 27.8225 39.1445 28.6546 38.078 28.6546Z" fill="#FF0404"/> <path d="M52.062 10.7171C53.902 10.7171 55.092 11.7771 55.162 13.4371H53.372C53.292 12.6671 52.812 12.2171 52.062 12.2171C51.122 12.2171 50.542 13.0571 50.542 14.4371C50.542 15.8171 51.122 16.6571 52.042 16.6571C52.792 16.6571 53.282 16.1971 53.382 15.3971H55.192C55.052 17.1671 53.852 18.1571 52.042 18.1571C49.992 18.1571 48.732 16.7471 48.732 14.4371C48.732 12.1271 50.002 10.7171 52.062 10.7171ZM58.0305 16.5271H61.2505V17.9971H56.3005V10.8771H58.0305V16.5271ZM63.8313 17.9971H62.1013V10.8771H63.8313V17.9971ZM68.2632 10.7171C70.1032 10.7171 71.2932 11.7771 71.3632 13.4371H69.5732C69.4932 12.6671 69.0132 12.2171 68.2632 12.2171C67.3232 12.2171 66.7432 13.0571 66.7432 14.4371C66.7432 15.8171 67.3232 16.6571 68.2432 16.6571C68.9932 16.6571 69.4832 16.1971 69.5832 15.3971H71.3932C71.2532 17.1671 70.0532 18.1571 68.2432 18.1571C66.1932 18.1571 64.9332 16.7471 64.9332 14.4371C64.9332 12.1271 66.2032 10.7171 68.2632 10.7171ZM75.8217 14.2471L78.6017 17.9971H76.4217L74.2517 14.7171H74.2317V17.9971H72.5017V10.8771H74.2317V13.9471H74.2517L76.3417 10.8771H78.4117L75.8217 14.2471ZM87.8006 17.9971H86.0706V15.0471H83.4406V17.9971H81.7106V10.8771H83.4406V13.5771H86.0706V10.8771H87.8006V17.9971ZM94.3481 12.3271H91.0481V13.6771H94.1281V15.1071H91.0481V16.5471H94.4281V17.9971H89.3181V10.8771H94.3481V12.3271ZM95.656 10.8771H98.546C100.366 10.8771 101.166 11.6171 101.166 12.9071C101.166 13.7771 100.666 14.4071 99.856 14.6471V14.6671C100.366 14.8471 100.616 15.1771 100.946 16.0971L101.636 17.9971H99.776L99.236 16.3871C98.986 15.6571 98.706 15.3971 98.036 15.3971H97.386V17.9971H95.656V10.8771ZM97.386 12.2171V14.0871H98.336C99.136 14.0871 99.456 13.7271 99.456 13.1271C99.456 12.4971 99.026 12.2171 98.266 12.2171H97.386ZM107.532 12.3271H104.232V13.6771H107.312V15.1071H104.232V16.5471H107.612V17.9971H102.502V10.8771H107.532V12.3271ZM116.354 11.9171H114.014V17.9971H112.824V11.9171H110.484V10.8771H116.354V11.9171ZM119.836 10.7271C121.876 10.7271 123.136 12.1471 123.136 14.4371C123.136 16.7271 121.876 18.1471 119.836 18.1471C117.796 18.1471 116.536 16.7271 116.536 14.4371C116.536 12.1471 117.796 10.7271 119.836 10.7271ZM119.836 11.7971C118.566 11.7971 117.776 12.8071 117.776 14.4371C117.776 16.0671 118.566 17.0771 119.836 17.0771C121.106 17.0771 121.896 16.0671 121.896 14.4371C121.896 12.8071 121.106 11.7971 119.836 11.7971ZM130.753 16.0671H127.803L127.143 17.9971H125.883L128.473 10.8771H130.083L132.673 17.9971H131.413L130.753 16.0671ZM130.393 15.0271L130.203 14.4671C129.883 13.5171 129.573 12.5871 129.283 11.6371H129.263C128.973 12.5871 128.683 13.5171 128.353 14.4671L128.163 15.0271H130.393ZM133.393 10.8771H135.673C138.053 10.8771 139.403 12.1571 139.403 14.4371C139.403 16.7171 138.053 17.9971 135.673 17.9971H133.393V10.8771ZM134.583 11.9171V16.9571H135.653C137.313 16.9571 138.163 16.0971 138.163 14.4371C138.163 12.7771 137.313 11.9171 135.653 11.9171H134.583ZM140.678 10.8771H142.958C145.338 10.8771 146.688 12.1571 146.688 14.4371C146.688 16.7171 145.338 17.9971 142.958 17.9971H140.678V10.8771ZM141.868 11.9171V16.9571H142.938C144.598 16.9571 145.448 16.0971 145.448 14.4371C145.448 12.7771 144.598 11.9171 142.938 11.9171H141.868ZM154.298 16.0671H151.348L150.688 17.9971H149.428L152.018 10.8771H153.628L156.218 17.9971H154.958L154.298 16.0671ZM153.938 15.0271L153.748 14.4671C153.428 13.5171 153.118 12.5871 152.828 11.6371H152.808C152.518 12.5871 152.228 13.5171 151.898 14.4671L151.708 15.0271H153.938ZM49.272 23.8771H51.842C53.522 23.8771 54.392 24.7671 54.392 26.0971C54.392 27.4371 53.522 28.3271 51.842 28.3271H50.472V30.9971H49.272V23.8771ZM50.472 24.8871V27.3171H51.702C52.712 27.3171 53.162 26.8571 53.162 26.0971C53.162 25.3471 52.712 24.8871 51.702 24.8871H50.472ZM60.2918 24.9171H56.7318V26.8471H60.0718V27.8771H56.7318V29.9571H60.3918V30.9971H55.5318V23.8771H60.2918V24.9171ZM61.7818 23.8771H64.2318C65.9818 23.8771 66.7718 24.6071 66.7718 25.8471C66.7718 26.7371 66.2618 27.4071 65.4518 27.6071V27.6271C65.9618 27.7971 66.1918 28.0971 66.5118 28.9871L67.2418 30.9971H65.9318L65.3318 29.2071C65.0518 28.4071 64.7418 28.1371 64.0118 28.1371H62.9818V30.9971H61.7818V23.8771ZM62.9818 24.8671V27.1571H64.1718C65.1618 27.1571 65.5718 26.6771 65.5618 25.9671C65.5618 25.2071 65.0418 24.8671 64.1018 24.8671H62.9818ZM70.385 23.7271C72.115 23.7271 73.005 24.5371 73.005 26.0671H71.795C71.795 25.1671 71.285 24.7071 70.365 24.7071C69.595 24.7071 69.115 25.0771 69.115 25.6571C69.115 26.3071 69.605 26.5071 70.745 26.7871C72.085 27.1171 73.205 27.4671 73.205 28.9671C73.205 30.2871 72.145 31.1471 70.545 31.1471C68.825 31.1471 67.775 30.2771 67.775 28.6471H69.005C69.005 29.6671 69.565 30.1571 70.555 30.1571C71.445 30.1571 71.965 29.7471 71.965 29.0771C71.965 28.3571 71.445 28.1971 70.355 27.9271C69.005 27.5871 67.885 27.2571 67.885 25.7671C67.885 24.5571 68.875 23.7271 70.385 23.7271ZM77.4143 23.7271C79.4543 23.7271 80.7143 25.1471 80.7143 27.4371C80.7143 29.7271 79.4543 31.1471 77.4143 31.1471C75.3743 31.1471 74.1143 29.7271 74.1143 27.4371C74.1143 25.1471 75.3743 23.7271 77.4143 23.7271ZM77.4143 24.7971C76.1443 24.7971 75.3543 25.8071 75.3543 27.4371C75.3543 29.0671 76.1443 30.0771 77.4143 30.0771C78.6843 30.0771 79.4743 29.0671 79.4743 27.4371C79.4743 25.8071 78.6843 24.7971 77.4143 24.7971ZM87.8867 30.9971H86.1667L84.6267 28.0171C84.1067 27.0071 83.5967 25.9771 83.1167 24.9571H83.0967C83.1367 26.0371 83.1567 27.1171 83.1567 28.1971V30.9971H81.9967V23.8771H83.7267L85.2567 26.8571C85.7767 27.8671 86.2867 28.8971 86.7667 29.9171H86.7867C86.7567 28.8371 86.7367 27.7571 86.7367 26.6771V23.8771H87.8867V30.9971ZM93.4876 29.0671H90.5376L89.8776 30.9971H88.6176L91.2076 23.8771H92.8176L95.4076 30.9971H94.1476L93.4876 29.0671ZM93.1276 28.0271L92.9376 27.4671C92.6176 26.5171 92.3076 25.5871 92.0176 24.6371H91.9976C91.7076 25.5871 91.4176 26.5171 91.0876 27.4671L90.8976 28.0271H93.1276ZM97.3275 29.9571H100.828V30.9971H96.1275V23.8771H97.3275V29.9571ZM106.936 23.7271C108.626 23.7271 109.696 24.6371 109.836 26.0571H108.556C108.416 25.2471 107.846 24.7971 106.936 24.7971C105.666 24.7971 104.876 25.8071 104.876 27.4671C104.876 29.1371 105.646 30.1571 106.886 30.1571C107.976 30.1571 108.686 29.5271 108.696 28.1471H106.876V27.1471H109.816V30.9971H108.786V30.1171H108.766C108.386 30.7371 107.596 31.1271 106.616 31.1271C104.796 31.1271 103.636 29.7471 103.636 27.4671C103.636 25.1471 104.896 23.7271 106.936 23.7271ZM112.689 30.9971H111.489V23.8771H112.689V30.9971ZM119.058 24.9171H115.648V27.1071H118.818V28.1371H115.648V30.9971H114.448V23.8771H119.058V24.9171ZM125.524 24.9171H123.184V30.9971H121.994V24.9171H119.654V23.8771H125.524V24.9171ZM134.703 30.9971H132.983L131.443 28.0171C130.923 27.0071 130.413 25.9771 129.933 24.9571H129.913C129.953 26.0371 129.973 27.1171 129.973 28.1971V30.9971H128.813V23.8771H130.543L132.073 26.8571C132.593 27.8671 133.103 28.8971 133.583 29.9171H133.603C133.573 28.8371 133.553 27.7571 133.553 26.6771V23.8771H134.703V30.9971ZM139.289 23.7271C141.329 23.7271 142.589 25.1471 142.589 27.4371C142.589 29.7271 141.329 31.1471 139.289 31.1471C137.249 31.1471 135.989 29.7271 135.989 27.4371C135.989 25.1471 137.249 23.7271 139.289 23.7271ZM139.289 24.7971C138.019 24.7971 137.229 25.8071 137.229 27.4371C137.229 29.0671 138.019 30.0771 139.289 30.0771C140.559 30.0771 141.349 29.0671 141.349 27.4371C141.349 25.8071 140.559 24.7971 139.289 24.7971ZM148.639 24.9171H146.299V30.9971H145.109V24.9171H142.769V23.8771H148.639V24.9171ZM154.227 24.9171H150.667V26.8471H154.007V27.8771H150.667V29.9571H154.327V30.9971H149.467V23.8771H154.227V24.9171Z" fill="black"/> </svg> <span class="d-none">GIFT NOTE ADDED | Click to edit note</span> </button> <button id="btn-cart-date-modal" class="btn btn-link btn-sm py-2 w-100" type="button" onclick="openCartDateModal(this, event)"> <svg class="cart-icon" width="182" height="40" viewBox="0 0 182 40" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="0.531818" y="1.43514" width="180.186" height="37.1239" fill="white"/> <rect x="0.531818" y="1.43514" width="180.186" height="37.1239" stroke="#E2E2E2" stroke-width="1.06364"/> <path d="M23.2496 14.8399V19.5056L27.0914 21.8316C27.2849 21.9489 27.4242 22.1389 27.4789 22.3599C27.5336 22.5809 27.499 22.8148 27.3828 23.0101C27.2666 23.2053 27.0782 23.3461 26.8593 23.4012C26.6402 23.4563 26.4085 23.4215 26.215 23.3042L21.9605 20.7282C21.8346 20.6518 21.7304 20.5439 21.6581 20.4149C21.5858 20.2858 21.5478 20.1401 21.5479 19.9919V14.8399C21.5479 14.6122 21.6375 14.3938 21.7971 14.2327C21.9566 14.0717 22.1731 13.9812 22.3988 13.9812C22.6244 13.9812 22.8408 14.0717 23.0004 14.2327C23.16 14.3938 23.2496 14.6122 23.2496 14.8399ZM32.6093 12.2639C32.3837 12.2639 32.1672 12.3544 32.0077 12.5154C31.8481 12.6764 31.7585 12.8948 31.7585 13.1226V15.0546C31.083 14.2646 30.3938 13.5036 29.6185 12.7115C28.1995 11.2793 26.3937 10.301 24.4268 9.89856C22.4599 9.49616 20.4192 9.68761 18.5596 10.449C16.6999 11.2103 15.1038 12.5079 13.9707 14.1794C12.8376 15.851 12.2177 17.8224 12.1886 19.8475C12.1594 21.8724 12.7223 23.8613 13.8068 25.5653C14.8913 27.2694 16.4494 28.6131 18.2864 29.4287C20.1233 30.2442 22.1577 30.4954 24.1353 30.1508C26.1129 29.8062 27.9462 28.8812 29.4058 27.4912C29.487 27.4137 29.5524 27.3207 29.5981 27.2178C29.6439 27.1148 29.669 27.0036 29.6721 26.8908C29.6752 26.778 29.6564 26.6657 29.6165 26.5602C29.5766 26.4548 29.5166 26.3583 29.4398 26.2762C29.363 26.1942 29.2709 26.1282 29.1688 26.0821C29.0667 26.036 28.9567 26.0106 28.8449 26.0074C28.7331 26.0042 28.6217 26.0233 28.5172 26.0635C28.4127 26.1038 28.3171 26.1644 28.2358 26.2418C27.019 27.399 25.4915 28.1688 23.8439 28.455C22.1962 28.7413 20.5015 28.5315 18.9714 27.8516C17.4413 27.1717 16.1435 26.052 15.2402 24.6324C14.3368 23.2126 13.868 21.5558 13.8921 19.8688C13.9163 18.1818 14.4324 16.5394 15.376 15.1466C16.3197 13.7539 17.649 12.6725 19.1979 12.0375C20.7469 11.4026 22.4469 11.2422 24.0856 11.5765C25.7244 11.9107 27.2293 12.7247 28.4124 13.9168C29.2781 14.8013 30.0364 15.6535 30.8012 16.5572H28.3549C28.1293 16.5572 27.9128 16.6477 27.7533 16.8087C27.5936 16.9697 27.504 17.1882 27.504 17.4159C27.504 17.6436 27.5936 17.862 27.7533 18.023C27.9128 18.184 28.1293 18.2745 28.3549 18.2745H32.6093C32.835 18.2745 33.0514 18.184 33.211 18.023C33.3705 17.862 33.4602 17.6436 33.4602 17.4159V13.1226C33.4602 12.8948 33.3705 12.6764 33.211 12.5154C33.0514 12.3544 32.835 12.2639 32.6093 12.2639Z" fill="#FF0404"/> <path d="M44.2211 10.7171C46.0611 10.7171 47.2511 11.7771 47.3211 13.4371H45.5311C45.4511 12.6671 44.9711 12.2171 44.2211 12.2171C43.2811 12.2171 42.7011 13.0571 42.7011 14.4371C42.7011 15.8171 43.2811 16.6571 44.2011 16.6571C44.9511 16.6571 45.4411 16.1971 45.5411 15.3971H47.3511C47.2111 17.1671 46.0111 18.1571 44.2011 18.1571C42.1511 18.1571 40.8911 16.7471 40.8911 14.4371C40.8911 12.1271 42.1611 10.7171 44.2211 10.7171ZM50.1896 16.5271H53.4096V17.9971H48.4596V10.8771H50.1896V16.5271ZM55.9904 17.9971H54.2604V10.8771H55.9904V17.9971ZM60.4223 10.7171C62.2623 10.7171 63.4523 11.7771 63.5223 13.4371H61.7323C61.6523 12.6671 61.1723 12.2171 60.4223 12.2171C59.4823 12.2171 58.9023 13.0571 58.9023 14.4371C58.9023 15.8171 59.4823 16.6571 60.4023 16.6571C61.1523 16.6571 61.6423 16.1971 61.7423 15.3971H63.5523C63.4123 17.1671 62.2123 18.1571 60.4023 18.1571C58.3523 18.1571 57.0923 16.7471 57.0923 14.4371C57.0923 12.1271 58.3623 10.7171 60.4223 10.7171ZM67.9808 14.2471L70.7608 17.9971H68.5808L66.4108 14.7171H66.3908V17.9971H64.6608V10.8771H66.3908V13.9471H66.4108L68.5008 10.8771H70.5708L67.9808 14.2471ZM79.9597 17.9971H78.2297V15.0471H75.5997V17.9971H73.8697V10.8771H75.5997V13.5771H78.2297V10.8771H79.9597V17.9971ZM86.5072 12.3271H83.2072V13.6771H86.2872V15.1071H83.2072V16.5471H86.5872V17.9971H81.4772V10.8771H86.5072V12.3271ZM87.8151 10.8771H90.7051C92.5251 10.8771 93.3251 11.6171 93.3251 12.9071C93.3251 13.7771 92.8251 14.4071 92.0151 14.6471V14.6671C92.5251 14.8471 92.7751 15.1771 93.1051 16.0971L93.7951 17.9971H91.9351L91.3951 16.3871C91.1451 15.6571 90.8651 15.3971 90.1951 15.3971H89.5451V17.9971H87.8151V10.8771ZM89.5451 12.2171V14.0871H90.4951C91.2951 14.0871 91.6151 13.7271 91.6151 13.1271C91.6151 12.4971 91.1851 12.2171 90.4251 12.2171H89.5451ZM99.6908 12.3271H96.3908V13.6771H99.4708V15.1071H96.3908V16.5471H99.7708V17.9971H94.6608V10.8771H99.6908V12.3271ZM108.513 11.9171H106.173V17.9971H104.983V11.9171H102.643V10.8771H108.513V11.9171ZM111.995 10.7271C114.035 10.7271 115.295 12.1471 115.295 14.4371C115.295 16.7271 114.035 18.1471 111.995 18.1471C109.955 18.1471 108.695 16.7271 108.695 14.4371C108.695 12.1471 109.955 10.7271 111.995 10.7271ZM111.995 11.7971C110.725 11.7971 109.935 12.8071 109.935 14.4371C109.935 16.0671 110.725 17.0771 111.995 17.0771C113.265 17.0771 114.055 16.0671 114.055 14.4371C114.055 12.8071 113.265 11.7971 111.995 11.7971ZM124.552 17.9971H123.362V14.8171H120.082V17.9971H118.882V10.8771H120.082V13.7771H123.362V10.8771H124.552V17.9971ZM129.144 10.7271C131.184 10.7271 132.444 12.1471 132.444 14.4371C132.444 16.7271 131.184 18.1471 129.144 18.1471C127.104 18.1471 125.844 16.7271 125.844 14.4371C125.844 12.1471 127.104 10.7271 129.144 10.7271ZM129.144 11.7971C127.874 11.7971 127.084 12.8071 127.084 14.4371C127.084 16.0671 127.874 17.0771 129.144 17.0771C130.414 17.0771 131.204 16.0671 131.204 14.4371C131.204 12.8071 130.414 11.7971 129.144 11.7971ZM134.926 16.9571H138.426V17.9971H133.726V10.8771H134.926V16.9571ZM139.41 10.8771H141.69C144.07 10.8771 145.42 12.1571 145.42 14.4371C145.42 16.7171 144.07 17.9971 141.69 17.9971H139.41V10.8771ZM140.6 11.9171V16.9571H141.67C143.33 16.9571 144.18 16.0971 144.18 14.4371C144.18 12.7771 143.33 11.9171 141.67 11.9171H140.6ZM153.61 11.9171H150.2V14.1071H153.37V15.1371H150.2V17.9971H149V10.8771H153.61V11.9171ZM157.611 10.7271C159.651 10.7271 160.911 12.1471 160.911 14.4371C160.911 16.7271 159.651 18.1471 157.611 18.1471C155.571 18.1471 154.311 16.7271 154.311 14.4371C154.311 12.1471 155.571 10.7271 157.611 10.7271ZM157.611 11.7971C156.341 11.7971 155.551 12.8071 155.551 14.4371C155.551 16.0671 156.341 17.0771 157.611 17.0771C158.881 17.0771 159.671 16.0671 159.671 14.4371C159.671 12.8071 158.881 11.7971 157.611 11.7971ZM162.193 10.8771H164.643C166.393 10.8771 167.183 11.6071 167.183 12.8471C167.183 13.7371 166.673 14.4071 165.863 14.6071V14.6271C166.373 14.7971 166.603 15.0971 166.923 15.9871L167.653 17.9971H166.343L165.743 16.2071C165.463 15.4071 165.153 15.1371 164.423 15.1371H163.393V17.9971H162.193V10.8771ZM163.393 11.8671V14.1571H164.583C165.573 14.1571 165.983 13.6771 165.973 12.9671C165.973 12.2071 165.453 11.8671 164.513 11.8671H163.393ZM45.4611 29.0671H42.5111L41.8511 30.9971H40.5911L43.1811 23.8771H44.7911L47.3811 30.9971H46.1211L45.4611 29.0671ZM45.1011 28.0271L44.9111 27.4671C44.5911 26.5171 44.2811 25.5871 43.9911 24.6371H43.9711C43.6811 25.5871 43.3911 26.5171 43.0611 27.4671L42.8711 28.0271H45.1011ZM55.2111 24.9171H51.8011V27.1071H54.9711V28.1371H51.8011V30.9971H50.6011V23.8771H55.2111V24.9171ZM61.8021 23.8771V28.3071C61.8021 30.1571 60.8321 31.1471 59.0721 31.1471C57.3121 31.1471 56.3321 30.1571 56.3321 28.3071V23.8771H57.5321V28.2671C57.5321 29.4671 58.0921 30.0771 59.0721 30.0771C60.0521 30.0771 60.6121 29.4671 60.6121 28.2671V23.8771H61.8021ZM68.445 24.9171H66.105V30.9971H64.915V24.9171H62.575V23.8771H68.445V24.9171ZM74.6829 23.8771V28.3071C74.6829 30.1571 73.7129 31.1471 71.9529 31.1471C70.1929 31.1471 69.2129 30.1571 69.2129 28.3071V23.8771H70.4129V28.2671C70.4129 29.4671 70.9729 30.0771 71.9529 30.0771C72.9329 30.0771 73.4929 29.4671 73.4929 28.2671V23.8771H74.6829ZM76.3921 23.8771H78.8421C80.5921 23.8771 81.3821 24.6071 81.3821 25.8471C81.3821 26.7371 80.8721 27.4071 80.0621 27.6071V27.6271C80.5721 27.7971 80.8021 28.0971 81.1221 28.9871L81.8521 30.9971H80.5421L79.9421 29.2071C79.6621 28.4071 79.3521 28.1371 78.6221 28.1371H77.5921V30.9971H76.3921V23.8771ZM77.5921 24.8671V27.1571H78.7821C79.7721 27.1571 80.1821 26.6771 80.1721 25.9671C80.1721 25.2071 79.6521 24.8671 78.7121 24.8671H77.5921ZM87.6853 24.9171H84.1253V26.8471H87.4653V27.8771H84.1253V29.9571H87.7853V30.9971H82.9253V23.8771H87.6853V24.9171ZM91.48 23.8771H93.76C96.14 23.8771 97.49 25.1571 97.49 27.4371C97.49 29.7171 96.14 30.9971 93.76 30.9971H91.48V23.8771ZM92.67 24.9171V29.9571H93.74C95.4 29.9571 96.25 29.0971 96.25 27.4371C96.25 25.7771 95.4 24.9171 93.74 24.9171H92.67ZM103.525 24.9171H99.9651V26.8471H103.305V27.8771H99.9651V29.9571H103.625V30.9971H98.7651V23.8771H103.525V24.9171ZM106.215 29.9571H109.715V30.9971H105.015V23.8771H106.215V29.9571ZM111.899 30.9971H110.699V23.8771H111.899V30.9971ZM116.502 30.9971H114.982L112.642 23.8771H113.872L114.842 26.8471C115.172 27.8371 115.462 28.8371 115.732 29.8271H115.752C116.012 28.8371 116.312 27.8371 116.632 26.8471L117.602 23.8771H118.832L116.502 30.9971ZM124.336 24.9171H120.776V26.8471H124.116V27.8771H120.776V29.9571H124.436V30.9971H119.576V23.8771H124.336V24.9171ZM125.826 23.8771H128.276C130.026 23.8771 130.816 24.6071 130.816 25.8471C130.816 26.7371 130.306 27.4071 129.496 27.6071V27.6271C130.006 27.7971 130.236 28.0971 130.556 28.9871L131.286 30.9971H129.976L129.376 29.2071C129.096 28.4071 128.786 28.1371 128.056 28.1371H127.026V30.9971H125.826V23.8771ZM127.026 24.8671V27.1571H128.216C129.206 27.1571 129.616 26.6771 129.606 25.9671C129.606 25.2071 129.086 24.8671 128.146 24.8671H127.026ZM134.76 28.1371V30.9971H133.56V28.1371L131.06 23.8771H132.42L133.2 25.2871C133.53 25.8871 133.85 26.5071 134.15 27.1271H134.17C134.47 26.5071 134.79 25.8871 135.13 25.2871L135.9 23.8771H137.25L134.76 28.1371ZM140.474 23.8771H142.754C145.134 23.8771 146.484 25.1571 146.484 27.4371C146.484 29.7171 145.134 30.9971 142.754 30.9971H140.474V23.8771ZM141.664 24.9171V29.9571H142.734C144.394 29.9571 145.244 29.0971 145.244 27.4371C145.244 25.7771 144.394 24.9171 142.734 24.9171H141.664ZM151.535 29.0671H148.585L147.925 30.9971H146.665L149.255 23.8771H150.865L153.455 30.9971H152.195L151.535 29.0671ZM151.175 28.0271L150.985 27.4671C150.665 26.5171 150.355 25.5871 150.065 24.6371H150.045C149.755 25.5871 149.465 26.5171 149.135 27.4671L148.945 28.0271H151.175ZM158.601 24.9171H156.261V30.9971H155.071V24.9171H152.731V23.8771H158.601V24.9171ZM164.189 24.9171H160.629V26.8471H163.969V27.8771H160.629V29.9571H164.289V30.9971H159.429V23.8771H164.189V24.9171Z" fill="black"/> </svg> <span class="d-none"></span> </button> </div> <div id="cart-note-modal" class="cart-delivery-modal gift-note-wrapper" > <div class="header-modal"> <h3 class="h6 mb-0"> Personalization note </h3> <button id="modal-note-clear-button" class="btn btn-md btn-secondary" style="width: fit-content; margin: 0 10px 0 auto; font-size: 12px;" onClick="clearCartNote()">CLEAR NOTE</button> <button class="btn-close" type="button" onclick="closeCartModal(this, event)" aria-label="Close"> </button> </div> <div class="row mb-4"> <div class="col-6"> <label for="cart-gift-note-to" class="form-label mb-2"> To </label> <input id="cart-gift-note-to" name="attributes[To]" type="text" class="form-control" placeholder="To"> </div> <div class="col-6"> <label for="cart-gift-note-from" class="form-label mb-2"> From </label> <input id="cart-gift-note-from" name="attributes[From]" type="text" class="form-control" placeholder="From"> </div> </div> <div class="mb-4"> <label for="cart-gift-note-message" class="form-label mb-2"> Message (Max characters: 100) </label> <textarea id="cart-gift-note-message" name="attributes[Message]" type="text" class="form-control" rows="3" maxlength="100" placeholder="E.g Happy Birthday"></textarea> </div> <button type="button" class="btn btn-sm btn-primary w-100" data-note-saved-edit="Translation missing: en.cart.delivery_info.note_saved_edit" data-text="Save gift note" onclick="savePersonalizationNote(this, event)"> Save gift note </button> </div> <div id="cart-date-modal" class="cart-delivery-modal"> <div class="header-modal"> <h3 class="h6 mb-0"> Schedule Delivery </h3> <button id="modal-date-clear-button" class="btn btn-md btn-secondary d-none" style="width: fit-content; margin: 0 10px 0 auto; font-size: 12px;" onClick="clearCartDate()">CLEAR DATE</button> <button class="btn-close" type="button" onclick="closeCartModal(this, event)" aria-label="Close"> </button> </div> <div class="alert alert-primary text-center p-3"> <p style="font-size: 13px; font-weight: 400; margin: 0"> Attention: <strong style="font-weight: 700">If you're looking for immediate delivery options, continue to checkout.</strong> Your delivery may arrive up to 2 business days earlier than date selected. </p> </div> <div id="cart-delivery-info-calendar" class="cart-delivery-info-calendar" name="attributes[Delivery]"> </div> </div> </div> <div class="offcanvas-footer border-top border-dark p-5 pt-0"> <button class="btn btn-continue-no-items w-100" type="button" data-bs-dismiss="offcanvas"> Continue shopping </button> </div> </div> </div> <script> const countdownTimerElement = document.querySelector('.offcanvas-cart__countdown-timer-container'); const offcanvasCartElement = document.querySelector('#offcanvas-cart'); countdownTimerElement.addEventListener('click', () => bootstrap.Offcanvas.getOrCreateInstance(offcanvasCartElement).hide()); </script> <div id="offcanvas-search" class="offcanvas offcanvas-end offcanvas-mobile-full " tabindex="-1" aria-labelledby="offcanvas-search-label"> <div class="offcanvas-header "> <h2 id="offcanvas-search-label" class="offcanvas-title h5"> Search our store </h2> <button class="btn-close " type="button" data-bs-dismiss="offcanvas" aria-label="Close"> </button> </div> <div class="offcanvas-body"> <predictive-search> <form action="/search" method="get" role="search"> <div class="form-control-wrapper"> <svg xmlns="http://www.w3.org/2000/svg" class="icon-search" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> <input class="form-control" type="search" name="q" value="" aria-describedby="predictive-search-alert" aria-label="Start typing to see results..." placeholder="Start typing to see results..." data-search-collections="true" data-search-pages="true" data-search-articles="true"> <button class="btn btn-search-by-voice" type="button" aria-label="Search by voice" title="Search by voice" data-lang="en-US" data-bs-toggle="tooltip" data-bs-trigger="hover" data-bs-placement="bottom"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 2c-1.7 0-3 1.2-3 2.6v6.8c0 1.4 1.3 2.6 3 2.6s3-1.2 3-2.6V4.6C15 3.2 13.7 2 12 2z"/><path d="M19 10v1a7 7 0 0 1-14 0v-1M12 18.4v3.3M8 22h8"/> </svg> </button> </div> <input type="hidden" name="type" value="product"> </form> <p id="predictive-search-alert" class="visually-hidden" role="status" data-text-result-found="1 result found" data-text-results-found="[count] results found" data-text-no-results="No results found"> </p> <div id="predictive-search" tabindex="-1"></div> </predictive-search> <div id="search-popular-products-wrapper" class="mt-6"> <h3 id="search-popular-products-label" class="predictive-search-results-title h6 mb-4"> Popular Searches </h3> <ul id="search-popular-products" class="product-list list-unstyled" aria-labelledby="search-popular-products-label"> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/banana-bonanza" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Banana_Bonanza_f2ad1b5b-abbd-4201-81d8-266b6b2ad0fe.jpg?crop=center&height=600&v=1744996584&width=600" alt="Banana Bonanza" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/banana-bonanza" class="link-dark"> Banana Bonanza </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938040303710" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938040303710" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476505342046"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938040303710" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/chocolate-fudge" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Chocolate_Fudge_88f711d9-a4ee-4071-bfea-46874b820b84.jpg?crop=center&height=600&v=1744997061&width=600" alt="Chocolate Fudge" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/chocolate-fudge" class="link-dark"> Chocolate Fudge </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938046365790" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938046365790" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476525035614"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938046365790" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/cherry-bomb" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Cherry_Bomb_e7dc1e89-1fe9-4d97-9461-5f436b1cccab.jpg?crop=center&height=600&v=1744996855&width=600" alt="Cherry Bomb" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/cherry-bomb" class="link-dark"> Cherry Bomb </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938047184990" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938047184990" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476532408414"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938047184990" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/coconut-cream" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Coconut_Cream_184e794e-cdb5-4f25-a4a1-4f138204197c.jpg?crop=center&height=600&v=1744996888&width=600" alt="Coconut Cream" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/coconut-cream" class="link-dark"> Coconut Cream </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938051706974" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938051706974" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476545810526"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938051706974" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/cranberry-meets-raspberry" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Cranberry_Meets_Raspberry_6772a111-1e8d-44ae-a3fe-de9884a51b35.jpg?crop=center&height=600&v=1744997454&width=600" alt="Cranberry Meets Raspberry" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/cranberry-meets-raspberry" class="link-dark"> Cranberry Meets Raspberry </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938050986078" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938050986078" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476545319006"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938050986078" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/fresh-strawberry" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Fresh_Strawberry.jpg?crop=center&height=600&v=1744997019&width=600" alt="Fresh Strawberry" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/fresh-strawberry" class="link-dark"> Fresh Strawberry </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938047971422" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938047971422" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476537061470"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938047971422" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/juicy-watermelon" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Juicy_Watermelon_def55c81-8fd3-4589-9ebb-6722dec70140.jpg?crop=center&height=600&v=1744996693&width=600" alt="Juicy Watermelon" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/juicy-watermelon" class="link-dark"> Juicy Watermelon </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938049216606" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938049216606" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476540502110"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938049216606" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/pink-lemonade" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Pink_Lemonade_145cf507-b65a-4774-959c-7f70e46f46b9.jpg?crop=center&height=600&v=1744997500&width=600" alt="Pink Lemonade" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/pink-lemonade" class="link-dark"> Pink Lemonade </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938047610974" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938047610974" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476532703326"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938047610974" /></form> </div> </div> </div> </li> <li class="product-item py-3"> <div class="row align-items-center mx-n3"> <div class="col-4 px-3"> <a href="/products/sex-on-the-beach" class=""> <img class="product-item-img img-fluid me-3 rounded " src="//taffy.com/cdn/shop/files/Sex_On_The_Beach_1f9828c7-b291-43cf-a1ea-a7a29a0a120c.jpg?crop=center&height=600&v=1744997164&width=600" alt="Sex on the Beach" width="600" height="600" loading="lazy"> </a> </div> <div class="col-8 px-3"> <h4 class="product-item-title h6 mb-1 text-truncate"> <a href="/products/sex-on-the-beach" class="link-dark"> Sex on the Beach </a> </h4> <style data-shopify> .yotpo-rating-container { visibility: hidden !important; opacity: 0; height: auto; /* Ensures it retains space but is invisible */ pointer-events: none; /* Prevents interaction */ } .yotpo-reviews-star-ratings-widget { justify-content: center !important; } .star-container, .star-container svg{ outline:none!important; } .yotpo-sr-bottom-line-text { margin-left: 8px !important; font-weight: 500 !important; color: #000 !important; text-align: center !important; font-family: 'Besley-Bold' !important; font-size: 16px !important; font-style: normal !important; text-transform: capitalize !important; line-height:100%!important; } .yotpo-sr-bottom-line-summary{ align-items:center!important; flex-direction:row!important; } .yotpo-sr-bottom-line-summary > div{ margin-right:0!important; height:auto!important; } .star-container path{ stroke:lightgray!important; } /* fixes yotpo default height for mobile */ .yotpo-sr-bottom-line-summary > div, .yotpo-sr-bottom-line-summary > div > span { height: auto!important; max-height:auto!important } @media screen and (max-width:991px){ .yotpo-sr-bottom-line-summary{ flex-direction:row!important; gap:0!important; margin-bottom:0!important; } /* Not all styles need to be smaller for mobile */ .sm-review-badge .yotpo-sr-bottom-line-text { font-size: 10px !important; margin-left:4px!important; } .sm-review-badge .star-container { width: 12px !important; height: 12px !important; margin-right:2px!important; } } @media only screen and (max-width: 375px) { .sm-review-badge .yotpo-sr-bottom-line-summary { flex-direction: column!important; margin-bottom: 10px; gap: 5px!important; } } </style> <div class="centered "> <div style="display:inline-block;" class="yotpo-widget-instance" data-yotpo-instance-id="791984" data-yotpo-product-id="6938049675358" data-yotpo-cart-product-id="" data-yotpo-section-id="index"></div> </div> <script> (() => { // Configurable Options ** Note for eventListeners, use this to trigger a refresh when badges are added dynamically const CONFIG = { observerTimeout: 2000, // Stop the MutationObserver after X milliseconds yotpoCheckInterval: 250, // Interval for checking if Yotpo is available yotpoMaxWaitTime: 10000, // Maximum time to wait for Yotpo before stopping refreshDelay: 500, // Delay after refresh before updating widgets eventListeners: [ 'updated.ecomify.collection', // Ajax event for collection scroll to load more products 'rebuy.products.updated', // Rebuy event for slider updates on PDP 'predictiveSearch.updated' // riggers when a search is placed ], }; // Prevent multiple script executions on the same page if (window.yotpoLoaded) return; window.yotpoLoaded = true; document.addEventListener('DOMContentLoaded', () => { // Wait for Yotpo to be Ready function waitForYotpo(callback) { const startTime = Date.now(); if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { callback(); return; } const interval = setInterval(() => { if (window.Yotpo && typeof window.Yotpo.API !== "undefined") { clearInterval(interval); callback(); } else if (Date.now() - startTime > CONFIG.yotpoMaxWaitTime) { clearInterval(interval); console.error("Yotpo failed to load within the timeout period."); } }, CONFIG.yotpoCheckInterval); } // Update Review Widgets function updateReviewWidgets() { console.log('update-reviews'); document.querySelectorAll('.yotpo-rating-container').forEach(reviewContainer => { const widget = reviewContainer.querySelector('.yotpo-widget-instance'); if (!widget) return; function checkAndUpdate() { const firstStar = widget.querySelector('.star-container'); if (!firstStar) return; // Exit if stars are not found const hasReviews = !firstStar.classList.contains('yotpo-sr-star-empty'); reviewContainer.style.visibility = hasReviews ? 'visible' : 'hidden'; reviewContainer.style.opacity = hasReviews ? '1' : '0'; reviewContainer.style.pointerEvents = hasReviews ? 'auto' : 'none'; } checkAndUpdate(); // Run immediately if stars are available // Observe changes to update when Yotpo modifies the widget const observer = new MutationObserver(checkAndUpdate); observer.observe(widget, { childList: true, subtree: true }); // Stop observing after X milliseconds setTimeout(() => observer.disconnect(), CONFIG.observerTimeout); }); } // Refresh Yotpo on AJAX Events function refreshYotpoForNewElements() { console.log('refresh-now'); try { if (window.Yotpo && typeof window.yotpo !== "undefined") { console.log("Refreshing only missing Yotpo widgets..."); // Find all unprocessed Yotpo review elements document.querySelectorAll('.yotpo-widget-instance').forEach(el => { if (!el.hasAttribute('data-yotpo-widget-uuid')) { const productId = el.getAttribute('data-product-id'); // Use Yotpo API to refresh only this specific widget yotpo.initWidgets([{ productId }]); console.log('ran');s } }); setTimeout(updateReviewWidgets, CONFIG.refreshDelay); } } catch (error) { console.error("Error refreshing Yotpo widgets:", error); } } // Initialize waitForYotpo(updateReviewWidgets); // Attach Event Listeners Dynamically CONFIG.eventListeners.forEach(eventName => { window.addEventListener(eventName, refreshYotpoForNewElements); }); /* prevent yotpo scroll to reviews widget ** add the class yotpo-no-scroll to the anchor tag wrapper around the widget rendering ie: <a class="yotpo-no-scroll">...</a> */ document.addEventListener('click', function (event) { const target = event.target.closest('.yotpo-no-scroll'); if (target) { console.log("Preventing Yotpo scroll..."); event.preventDefault(); // Stop the default scroll behavior event.stopPropagation(); // Stop event from reaching Yotpo's parent elements window.location.href = target.getAttribute('href'); // Navigate immediately } }, true); }); })(); </script> <p class="product-item-price small mb-3"> <span class="product-item-price-final"> $12.00 </span> </p> <div class="form-wrapper"> <form method="post" action="/cart/add" id="product_form_6938049675358" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" onsubmit="onSubmitAtcForm(this, event)"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /> <div class="d-flex"> <input type="hidden" name="id" value="40476541583454"> <button class="btn-atc btn btn-sm btn-primary px-4 flex-shrink-0" type="submit" name="add" data-text-add-to-cart="ADD" > ADD </button> <input type="hidden" name="product-id" value="6938049675358" /></form> </div> </div> </div> </li> </ul> </div> </div> <div class="offcanvas-footer border-top p-5" hidden> <form action="/search" method="get" role="search"> <input type="hidden" name="q" value=""> <input type="hidden" name="type" value="product"> <button class="btn btn-outline-primary w-100" data-text-search-for="Search for" tabindex="-1"> </button> </form> </div> </div><script> window.addEventListener('load', function() { var _learnq = window._learnq || []; function addedToCart() { fetch(`${window.location.origin}/cart.js`) .then(res => res.clone().json().then(data => { var cart = { total_price: data.total_price/100, $value: data.total_price/100, total_discount: data.total_discount, original_total_price: data.original_total_price/100, items: data.items } if (item !== 'undefined') { cart = Object.assign(cart, item) } if (klAjax) { _learnq.push(['track', 'Added to Cart', cart]); klAjax = false; } })) }; (function (ns, fetch) { ns.fetch = function() { const response = fetch.apply(this, arguments); response.then(res => { if (`${window.location.origin}/cart/add.js` .includes(res.url)) { addedToCart() } }); return response } }(window, window.fetch)); var klAjax = true; var atcButtons = document.querySelectorAll("form[action*='/cart/add'] button[type='submit']"); for (var i = 0; i < atcButtons.length; i++) { atcButtons[i].addEventListener("click", function() { console.log('test') if (klAjax) { _learnq.push(['track', 'Added to Cart', item]); klAjax = false; } }) } }); </script> <img id="cannellamedia" class="d-block"> <script src="https://df8nroy20256x.cloudfront.net/cannella_GOAT.js" defer="defer"></script> <style> @font-face { font-family: "Tropical Island Vibes"; src: url('https://cdn.shopify.com/s/files/1/0557/8860/1438/files/tropicalislandvibes-arl6l.ttf?v=1715723072') format("truetype"); } @font-face { font-family: "Travel Journal"; src: url('https://cdn.shopify.com/s/files/1/0557/8860/1438/files/Travel_Journal.ttf?v=1715782642') format("truetype"); } @font-face { font-family: "Besley-Bold"; src: url('https://cdn.shopify.com/s/files/1/0557/8860/1438/files/Besley-Bold.ttf?v=1727472336') format("truetype"); } h1, h2, h3, h4, h5, h6 { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } </style> <script src="//cdn.datasteam.io/js/D2ADC1526102F6.js" async defer></script> <style> div.quantity-wrapper {background-color: #ffffff !important;} .quantity-wrapper .form-control {color: #7f7db6;} </style> <div id="shopify-block-10641372206048101839" class="shopify-block shopify-app-block"> <script> window.rebuyAppEmbedEnabled = true; </script> </div></body> </html>