${affiliateName ? decodeURIComponent(affiliateName) : "We've"} sent you ${ discountType === 'percentage' ? `${discountValue}%` : `$${discountValue}` } off!

Click below to redeem your discount code

Your discount will automatically be applied at checkout
`; overlay.appendChild(modal); document.body.appendChild(overlay); // Close handler document.getElementById('__growi-close-modal').onclick = () => { window.growiCookieUtils.setCookie('discount_seen', `${affiliateId.toLowerCase()}`, -1); overlay.remove(); }; // Redeem handler document.getElementById('__growi-redeem-btn').onclick = () => { const redeemBtn = document.getElementById('__growi-redeem-btn'); // Set loading state redeemBtn.disabled = true; redeemBtn.style.cursor = 'not-allowed'; redeemBtn.innerHTML = ` Loading... `; // Add spinning animation const style = document.createElement('style'); style.textContent = ` @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; document.head.appendChild(style); // Simulate loading delay then show discount code setTimeout(() => { // Replace button with discount code redeemBtn.style.display = 'none'; // Create discount code container const discountCodeDiv = document.createElement('div'); discountCodeDiv.id = '__growi-discount-code'; discountCodeDiv.style.cssText = ` background-color:#ecf0ff; display:block; width:90%; margin:20px auto 0 auto; text-align:center; color:#3860fb; font-size:25px; padding:8px; cursor:pointer; border-radius:5px; font-weight:bold; font-family:-apple-system, Inter, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif; `; discountCodeDiv.innerHTML = ` ${discountCode.toUpperCase()} `; // Add copy functionality discountCodeDiv.onclick = () => { navigator.clipboard .writeText(discountCode.toUpperCase()) .then(() => { // Show copied feedback under the code let copiedText = document.getElementById('__growi-copied-text'); if (!copiedText) { copiedText = document.createElement('div'); copiedText.id = '__growi-copied-text'; copiedText.style.cssText = ` font-size:0.9em; color:#28a745; margin-top:8px; text-align:center; `; discountCodeDiv.parentNode.insertBefore(copiedText, discountCodeDiv.nextSibling); } copiedText.innerHTML = '✓ Discount applied!'; }) .catch(() => { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = discountCode.toUpperCase(); document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); let copiedText = document.getElementById('__growi-copied-text'); if (!copiedText) { copiedText = document.createElement('div'); copiedText.id = '__growi-copied-text'; copiedText.style.cssText = ` font-size:0.9em; color:#28a745; margin-top:8px; text-align:center; `; discountCodeDiv.parentNode.insertBefore(copiedText, discountCodeDiv.nextSibling); } copiedText.innerHTML = '✓ Discount applied!'; }); }; // Insert the discount code div after the button redeemBtn.parentNode.insertBefore(discountCodeDiv, redeemBtn.nextSibling); }, 1500); window.growiCookieUtils.setCookie('discount_seen', `${affiliateId.toLowerCase()}`); }; } async function showDiscountModalV2(discountCode, affiliateName, discountValue, discountType, affiliateId) { console.log('showDiscountModalV2', discountCode, affiliateName, discountValue, discountType, affiliateId); if ( !discountValue || discountValue === '0' || discountValue === 0 || discountValue === null || discountValue === undefined || discountValue === 'null' ) return; // Fetch customization from API const customization = await fetchCustomization(affiliateId); // If no customization exists, fall back to the original showDiscountModal if (!customization) { console.log('ℹ️ No customization available, falling back to default modal'); showDiscountModal(discountCode, affiliateName, discountValue, discountType, affiliateId); return; } // Prevent duplicate modals if (document.getElementById('__growi-modal-overlay')) return; // Merge customization with defaults const config = { ...defaultCustomization, ...customization }; // Check if popup is enabled if (!config.popup_enabled) { console.log('ℹ️ Popup is disabled by customization settings'); if (config.banner_enabled) { window.growiCookieUtils.setCookie('discount_seen', affiliateId.toLowerCase()); showBanner(affiliateId, discountCode, customization); } return; } const headingText = config.heading_text || `${affiliateName ? decodeURIComponent(affiliateName) : "We've"} sent you ${ discountType === 'percentage' ? `${discountValue}%` : `$${discountValue}` } off!`; const bodyText = config.body_text || 'Click below to redeem your discount code'; const buttonText = config.button_text || 'Redeem Coupon'; const helperText = config.helper_text || 'Your discount will automatically be applied at checkout'; const buttonMarkup = config.hide_button ? '' : ``; const helperMarkup = `
${helperText}
`; const overlay = document.createElement('div'); overlay.id = '__growi-modal-overlay'; overlay.style.cssText = ` display:block; position:fixed; top:0; left:0; width:100%; height:100%; background-color:rgba(0,0,0,0.5); z-index:9998; `; const modal = document.createElement('div'); modal.className = '__growi_modal_content'; modal.style.cssText = ` display:block; background-color:${config.background_color}; z-index:9999; border-top:10px solid #2C2C2C; border-radius:10px; text-align:center; margin:auto; min-height:400px; height:auto; position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); width:90%; max-width:500px; `; // Add mobile-specific styles const mobileStyles = document.createElement('style'); mobileStyles.textContent = ` @media (max-width: 768px) { .__growi_modal_content { top: calc(50% + 20px) !important; } } @media (max-width: 480px) { .__growi_modal_content { top: calc(50% + 30px) !important; } } `; document.head.appendChild(mobileStyles); modal.innerHTML = `

${config.emoji || '🎉'}

${headingText}

${bodyText}

${buttonMarkup} ${helperMarkup}
`; overlay.appendChild(modal); document.body.appendChild(overlay); // Close handler const closeButton = document.getElementById('__growi-close-modal'); if (closeButton) { closeButton.onclick = () => { window.growiCookieUtils.setCookie('discount_seen', affiliateId.toLowerCase(), -1); overlay.remove(); }; } // Redeem handler const redeemBtn = document.getElementById('__growi-redeem-btn'); if (redeemBtn) { redeemBtn.onclick = () => { // Set loading state (preserve custom button colors) redeemBtn.disabled = true; redeemBtn.style.cursor = 'not-allowed'; redeemBtn.style.backgroundColor = config.button_color; redeemBtn.style.color = config.button_text_color; redeemBtn.innerHTML = ` Loading... `; // Add spinning animation const style = document.createElement('style'); style.textContent = ` @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; document.head.appendChild(style); // Simulate loading delay then show discount code setTimeout(() => { // Replace button with discount code redeemBtn.style.display = 'none'; // Create discount code container const discountCodeDiv = document.createElement('div'); discountCodeDiv.id = '__growi-discount-code'; discountCodeDiv.style.cssText = ` background-color:#ecf0ff; display:block; width:90%; margin:20px auto 0 auto; text-align:center; color:#3860fb; font-size:25px; padding:8px; cursor:pointer; border-radius:5px; font-weight:bold; font-family:-apple-system, Inter, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif; `; discountCodeDiv.innerHTML = ` ${discountCode.toUpperCase()} `; // Add copy functionality discountCodeDiv.onclick = () => { navigator.clipboard .writeText(discountCode.toUpperCase()) .then(() => { // Show copied feedback under the code let copiedText = document.getElementById('__growi-copied-text'); if (!copiedText) { copiedText = document.createElement('div'); copiedText.id = '__growi-copied-text'; copiedText.style.cssText = ` font-size:0.9em; color:#28a745; margin-top:8px; text-align:center; `; discountCodeDiv.parentNode.insertBefore(copiedText, discountCodeDiv.nextSibling); } copiedText.innerHTML = '✓ Discount applied!'; }) .catch(() => { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = discountCode.toUpperCase(); document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); let copiedText = document.getElementById('__growi-copied-text'); if (!copiedText) { copiedText = document.createElement('div'); copiedText.id = '__growi-copied-text'; copiedText.style.cssText = ` font-size:0.9em; color:#28a745; margin-top:8px; text-align:center; `; discountCodeDiv.parentNode.insertBefore(copiedText, discountCodeDiv.nextSibling); } copiedText.innerHTML = '✓ Discount applied!'; }); }; // Insert the discount code div after the button redeemBtn.parentNode.insertBefore(discountCodeDiv, redeemBtn.nextSibling); }, 1500); window.growiCookieUtils.setCookie('discount_seen', affiliateId.toLowerCase()); }; } } async function showBanner(affiliateId, discountCode, customizationData = null) { // Prevent duplicate banners if (document.getElementById('__growi-banner')) return; // Fetch customization from API if not provided const customization = customizationData || (await fetchCustomization(affiliateId)); // If no customization exists or banner not enabled, return if (!customization || !customization.banner_enabled) { console.log('ℹ️ Banner is disabled or no customization available'); return; } // Merge customization with defaults const config = { ...defaultCustomization, ...customization }; const affiliateName = window.growiCookieUtils.getCookie('affiliate_name'); const discountValue = window.growiCookieUtils.getCookie('discount_value'); const discountType = window.growiCookieUtils.getCookie('discount_type'); const bannerHeading = config.heading_text || `${affiliateName ? decodeURIComponent(affiliateName) : 'We'} sent you ${ discountType === 'percentage' ? `${discountValue}%` : `$${discountValue}` } off!`; const bannerSubtext = config.body_text || `Click below to redeem your discount code`; const bannerButtonText = config.button_text || 'Redeem Coupon'; const bannerButtonMarkup = config.hide_button ? '' : ``; // Create banner element const banner = document.createElement('div'); banner.id = '__growi-banner'; banner.style.cssText = ` display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; background-color: ${config.background_color}; color: ${config.text_color}; position: fixed; top: 0; left: 0; right: 0; width: 100%; z-index: 9997; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border-bottom: 1px solid rgba(0,0,0,0.08); font-family: -apple-system, Inter, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif; gap: 20px; box-sizing: border-box; `; banner.innerHTML = `
${config.emoji || '🎉'}
${bannerHeading}
${bannerSubtext}
${bannerButtonMarkup} `; // Add responsive styles and hover effects const bannerStyles = document.createElement('style'); bannerStyles.textContent = ` #__growi-banner-btn:hover { opacity: 0.9; } #__growi-banner-close:hover { opacity: 1; } @media (max-width: 768px) { #__growi-banner { flex-direction: column; align-items: stretch !important; padding: 16px; width: 100%; } #__growi-banner > div:first-child { margin-bottom: 12px; } #__growi-banner-btn { width: 100%; } #__growi-banner-close { position: absolute; top: 16px; right: 16px; } } `; document.head.appendChild(bannerStyles); // Append to body document.body.appendChild(banner); // Add body padding to prevent content from being hidden behind banner const originalPaddingTop = document.body.style.paddingTop; // Wait for banner to render to get actual height setTimeout(() => { const bannerBottom = banner.getBoundingClientRect().bottom; document.body.style.paddingTop = `${bannerBottom}px`; // Push down any existing sticky announcement bars so they appear below our banner const stickyAnnouncementBars = document.querySelectorAll( '[class*="announcement-bar"], [class*="announcement_bar"], [id*="announcement-bar"]' ); stickyAnnouncementBars.forEach((el) => { const style = getComputedStyle(el); if (style.position === 'sticky') { el.style.top = `${bannerBottom}px`; } }); }, 0); // Store original padding for cleanup banner.dataset.originalPadding = originalPaddingTop; // Button click handler - always copy code to clipboard, and optionally open modal const bannerBtn = document.getElementById('__growi-banner-btn'); if (bannerBtn) { bannerBtn.onclick = () => { const discountCode = window.growiCookieUtils.getCookie('discount_code'); const affiliateName = window.growiCookieUtils.getCookie('affiliate_name'); const discountType = window.growiCookieUtils.getCookie('discount_type'); const discountValue = window.growiCookieUtils.getCookie('discount_value'); if (discountCode && discountValue) { // Always copy discount code to clipboard const originalText = bannerBtn.innerHTML; navigator.clipboard .writeText(discountCode.toUpperCase()) .then(() => { bannerBtn.innerHTML = '✓ Discount applied!'; bannerBtn.style.backgroundColor = '#28a745'; setTimeout(() => { bannerBtn.innerHTML = originalText; bannerBtn.style.backgroundColor = config.button_color; }, 2000); }) .catch(() => { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = discountCode.toUpperCase(); textArea.style.position = 'fixed'; textArea.style.opacity = '0'; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); bannerBtn.innerHTML = '✓ Discount applied!'; bannerBtn.style.backgroundColor = '#28a745'; setTimeout(() => { bannerBtn.innerHTML = originalText; bannerBtn.style.backgroundColor = config.button_color; }, 2000); }); // Additionally show modal if enabled if (config.popup_enabled) { showDiscountModalV2(discountCode, affiliateName, discountValue, discountType, affiliateId); } } }; } // Close button handler document.getElementById('__growi-banner-close').onclick = () => { // Restore original padding const originalPadding = banner.dataset.originalPadding || ''; document.body.style.paddingTop = originalPadding; banner.remove(); // Store in cookie that banner was dismissed window.growiCookieUtils.setCookie('banner_dismissed', affiliateId.toLowerCase(), 1); // 1 day }; } // ---- PAGE VIEW (exact referrer only) ---- function hasFiredPageView(visitorUid) { const key = `growi_pv_sent::${visitorUid || 'anon'}::${location.pathname}`; try { if (sessionStorage.getItem(key)) return true; } catch {} if (window.growiCookieUtils) { const ck = window.growiCookieUtils.getCookie(encodeURIComponent(key)); if (ck === '1') return true; } return false; } function markFiredPageView(visitorUid) { const key = `growi_pv_sent::${visitorUid || 'anon'}::${location.pathname}`; try { sessionStorage.setItem(key, '1'); } catch {} // ~30 minutes lock across tabs window.growiCookieUtils && window.growiCookieUtils.setCookie(encodeURIComponent(key), '1', 0.02); } async function sendOneTimePageView(externalId) { console.log('sendOneTimePageView', externalId); if (!window.growiCookieUtils) return; console.log('sendOneTimePageView1', externalId); if (!externalId) return; const affiliateId = window.growiCookieUtils.getCookie('growi_affiliate_id'); const visitorUid = window.growiCookieUtils.getCookie('growi_visitor_uid'); if (!affiliateId || affiliateId === 'null') return; // keep your current rule console.log('sendOneTimePageView2', affiliateId); if (hasFiredPageView(visitorUid)) return; console.log('sendOneTimePageView3', visitorUid); markFiredPageView(visitorUid); // EXACT referrer only const referrerRaw = document.referrer || null; let referrerHost = null; try { referrerHost = referrerRaw ? new URL(referrerRaw).host : null; } catch {} // Referrer captured at script-execute time, before any same-host nav // could blank document.referrer. Survives pushState / SPA-style nav // inside in-app browsers. const referrerInitialRaw = (typeof window !== 'undefined' && typeof window.__growi_initial_referrer !== 'undefined' ? window.__growi_initial_referrer : null) || null; let referrerInitialHost = null; try { referrerInitialHost = referrerInitialRaw ? new URL(referrerInitialRaw).host : null; } catch {} // Get UTM parameters for Meta/Facebook ad tracking const utmParams = window.growiCookieUtils.getUtmParams ? window.growiCookieUtils.getUtmParams() : {}; // Check if traffic is from Facebook/Meta based on utm_source const isFacebookSource = utmParams.utm_source && ['fb', 'facebook', 'meta'].includes(utmParams.utm_source.toLowerCase()); // Click IDs + first-touch snapshot for paid-search fraud detection const clickIds = window.growiCookieUtils.getClickIds ? window.growiCookieUtils.getClickIds() : {}; const firstTouch = window.growiCookieUtils.getFirstTouch ? window.growiCookieUtils.getFirstTouch() : null; // In-app-browser / platform inference from UA. Always safe to call — // returns { platform: 'browser', in_app_browser: false, ... } when // nothing matches. const clientPlatform = window.growiCookieUtils.detectClientPlatform ? window.growiCookieUtils.detectClientPlatform() : { platform: 'browser', in_app_browser: false, user_agent: '', is_mobile: false }; // Prefer the value stamped onto first_touch (computed when the affiliate // cookie was set / backfilled — most accurate). Fall back to recomputing // live so payloads without a first_touch still carry signal. let inferredSource = (firstTouch && firstTouch.inferred_source) || null; if (!inferredSource) { if (clientPlatform && clientPlatform.platform && clientPlatform.platform !== 'browser') { inferredSource = clientPlatform.platform; } else if (referrerHost) { inferredSource = referrerHost; } else if (clickIds.gclid) { inferredSource = 'google_ads'; } else if (clickIds.msclkid) { inferredSource = 'bing_ads'; } else if (clickIds.fbclid) { inferredSource = 'facebook'; } else if (clickIds.ttclid) { inferredSource = 'tiktok'; } else { inferredSource = 'direct'; } } const event = { name: 'page_viewed', id: (crypto.randomUUID && crypto.randomUUID()) || `${Date.now()}-${Math.random().toString(16).slice(2)}`, timestamp: new Date().toISOString(), data: { title: document.title || null, path: location.pathname, url: location.href, referrer_raw: referrerRaw, referrer_host: referrerHost, referrer_initial_raw: referrerInitialRaw, referrer_initial_host: referrerInitialHost, utm_source: utmParams.utm_source || null, utm_medium: utmParams.utm_medium || null, utm_campaign: utmParams.utm_campaign || null, utm_content: utmParams.utm_content || null, utm_term: utmParams.utm_term || null, utm_id: utmParams.utm_id || null, // Meta Ad ID (only set if utm_source is fb/facebook/meta) meta_ad_id: isFacebookSource ? (utmParams.tw_id || utmParams.utm_id || utmParams.utm_content || null) : null, click_ids: clickIds, first_touch: firstTouch, inferred_source: inferredSource, client_platform: clientPlatform, }, clientId: visitorUid, }; const body = { tracking_event: { event_name: event.name, occurred_at: event.timestamp, visitor_uid: visitorUid, event_data: { pageEventId: event.id, timeStamp: event.timestamp, data: { ...event.data, clientId: event.clientId }, }, }, campaign_affiliate_id: affiliateId, external_id: `gid://shopify/Shop/${externalId}`, conversion_platform: 'shopify', }; // Optional server dedupe const idempKey = `${visitorUid || 'anon'}::${location.pathname}::${Math.floor(Date.now() / 60000)}`; try { await fetch('https://api.growi.io/api/v1/tracking_events', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Idempotency-Key': idempKey, }, body: JSON.stringify(body), }); } catch (err) { console.warn('page_viewed send failed', err); } } function waitForUrlParams(retries = 10, delay = 200) { // Check if URL has any parameters yet const hasParams = window.location.search.length > 0; const affiliateParam = new URLSearchParams(window.location.search).get('a') || new URLSearchParams(window.location.search).get('snowball') || new URLSearchParams(window.location.search).get('growi'); // If we found affiliate params or exhausted retries, proceed if (affiliateParam || retries <= 0 || hasParams) { console.log(`✅ URL stabilized after ${10 - retries} attempts. Affiliate param:`, affiliateParam); initializeAffiliate(); return; } // Wait and retry - Instagram WebView needs time to stabilize console.log(`⏳ Waiting for URL params to stabilize... (${retries} retries left)`); setTimeout(() => waitForUrlParams(retries - 1, delay), delay); } function waitForUtils(retries = 5) { console.log(`🔍 [WAIT-FOR-UTILS] Attempt ${6 - retries}/5 - Checking for window.growiCookieUtils...`); console.log( `🔍 [WAIT-FOR-UTILS] window.growiCookieUtils exists?`, typeof window.growiCookieUtils !== 'undefined' ); console.log(`🔍 [WAIT-FOR-UTILS] Document readyState:`, document.readyState); console.log(`🔍 [WAIT-FOR-UTILS] Timestamp:`, new Date().toISOString()); if (window.growiCookieUtils) { console.log('✅ [WAIT-FOR-UTILS] Cookie utils found! Available methods:', Object.keys(window.growiCookieUtils)); // Don't immediately read params - wait for URL to stabilize first waitForUrlParams(); } else if (retries > 0) { console.log(`⏳ [WAIT-FOR-UTILS] Not found yet, retrying in 100ms... (${retries} retries left)`); setTimeout(() => waitForUtils(retries - 1), 100); } else { console.error('❌ [WAIT-FOR-UTILS] Growi cookie utilities not loaded after 5 retries (500ms total)'); console.error('❌ [WAIT-FOR-UTILS] All window properties:', Object.keys(window)); console.error('❌ [WAIT-FOR-UTILS] Check if cookie-utils.js is loading correctly'); } } function initializeAffiliate() { console.log('🎯 [INIT-AFFILIATE] initializeAffiliate() called'); console.log( '🎯 [INIT-AFFILIATE] window.growiCookieUtils exists?', typeof window.growiCookieUtils !== 'undefined' ); if (!window.growiCookieUtils) { console.error('❌ [INIT-AFFILIATE] Cookie utils not available - CANNOT PROCEED'); console.error('❌ [INIT-AFFILIATE] This usually means cookie-utils.js failed to load or execute'); return; } console.log('✅ [INIT-AFFILIATE] Cookie utils available, proceeding...'); // Now read affiliate params after URL has stabilized const urlAffiliateId = new URLSearchParams(window.location.search).get('a') || new URLSearchParams(window.location.search).get('snowball') || new URLSearchParams(window.location.search).get('growi'); // Get affiliate info from cookies const cookieInfo = window.growiCookieUtils.manageAffiliateCookies(); // Determine which affiliate ID to use (URL param takes precedence) const affiliateId = urlAffiliateId || cookieInfo.affiliateId; const visitorUid = cookieInfo.visitorUid; // Brand-built Meta ads carry only a gcs_id (no affiliate param/cookie). // gcs_id alone is enough to stamp the cart so the backend can attribute // the sale. const gcsId = window.growiCookieUtils.getQueryParam('gcs_id') || window.growiCookieUtils.getCookie('growi_gcs_id'); const autoResponderId = window.growiCookieUtils.getQueryParam('igar_id') || cookieInfo.autoResponderId || window.growiCookieUtils.getCookie('growi_auto_responder_id'); // Creator-set sub-ID for platform-level tracking (e.g. ?sub_id=instagram) const subId = window.growiCookieUtils.getQueryParam('sub_id') || cookieInfo.subId || window.growiCookieUtils.getCookie('growi_sub_id'); console.log('🔍 Final affiliate detection:', { urlAffiliateId, cookieAffiliateId: cookieInfo.affiliateId, finalAffiliateId: affiliateId, gcsId, autoResponderId, subId, }); // Run if we have an affiliate from either source OR a gcs_id (brand-built // Meta ad). visitorUid is always created by manageAffiliateCookies. if ((affiliateId || gcsId || autoResponderId) && visitorUid) { // Get UTM parameters to pass to order const utmParams = window.growiCookieUtils.getUtmParams ? window.growiCookieUtils.getUtmParams() : {}; // Check if traffic is from Facebook/Meta based on utm_source const isFacebookSource = utmParams.utm_source && ['fb', 'facebook', 'meta'].includes(utmParams.utm_source.toLowerCase()); // Build cart attributes const cartAttributes = { __growi_visitor_uid: visitorUid, }; if (affiliateId) cartAttributes.__growi_affiliate_id = affiliateId; if (gcsId) cartAttributes.__growi_gcs_id = gcsId; if (autoResponderId) cartAttributes.__growi_auto_responder_id = autoResponderId; if (subId) cartAttributes.__growi_sub_id = subId; if (utmParams.utm_source) cartAttributes.__growi_utm_source = utmParams.utm_source; if (utmParams.utm_medium) cartAttributes.__growi_utm_medium = utmParams.utm_medium; if (utmParams.utm_campaign) cartAttributes.__growi_utm_campaign = utmParams.utm_campaign; if (utmParams.utm_content) cartAttributes.__growi_utm_content = utmParams.utm_content; if (utmParams.utm_term) cartAttributes.__growi_utm_term = utmParams.utm_term; if (utmParams.utm_id) cartAttributes.__growi_utm_id = utmParams.utm_id; if (utmParams.campaign_id) cartAttributes.__growi_campaign_id = utmParams.campaign_id; if (utmParams.user_id) cartAttributes.__growi_user_id = utmParams.user_id; if (utmParams.campaign_affiliate_id) cartAttributes.__growi_campaign_affiliate_id = utmParams.campaign_affiliate_id; if (utmParams.asset_id) cartAttributes.__growi_asset_id = utmParams.asset_id; if (utmParams.tw_id) cartAttributes.__growi_tw_id = utmParams.tw_id; if (isFacebookSource && (utmParams.tw_id || utmParams.utm_id || utmParams.utm_content)) { cartAttributes.__growi_meta_ad_id = utmParams.tw_id || utmParams.utm_id || utmParams.utm_content; } fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ attributes: cartAttributes, }), }) .then((res) => { // Extract x-shopid from response headers const externalId = res.headers.get('x-shopid'); console.log('🏪 Shop ID extracted from headers:', externalId); return res.json().then((data) => ({ data, externalId })); }) .then(({ data, externalId }) => { console.log('✅ Cart attributes updated with affiliate & visitor ID', data); // --- Discount code logic start --- // Only fetch if we have an affiliateId and no discount_code cookie // Only fetch if we have an affiliateId and no discount_code cookie const discountCode = window.growiCookieUtils.getCookie('discount_code'); const affiliateName = window.growiCookieUtils.getCookie('affiliate_name'); const discountType = window.growiCookieUtils.getCookie('discount_type'); const discountValue = window.growiCookieUtils.getCookie('discount_value'); const campaignType = window.growiCookieUtils.getCookie('campaign_type'); const discountSeen = window.growiCookieUtils.getCookie('discount_seen'); const isDiscountSeen = discountSeen && discountSeen === `${affiliateId}`.toLowerCase(); console.log('Test', affiliateId, discountCode, affiliateId !== 'null', externalId); if (affiliateId && !!discountCode && affiliateId !== 'null' && isDiscountSeen) { const bannerDismissed = window.growiCookieUtils.getCookie('banner_dismissed'); const isBannerDismissed = bannerDismissed && bannerDismissed === `${affiliateId}`.toLowerCase(); if (!isBannerDismissed) { // Check if banner is enabled before showing fetchCustomization(affiliateId).then((customization) => { if (customization && customization.banner_enabled) { showBanner(affiliateId, discountCode, customization); } }); } sendOneTimePageView(externalId); } else if ( affiliateId && (!discountCode || (!!discountCode && !isDiscountSeen)) && affiliateId !== 'null' ) { const currentUrl = window.location.href; // gcs_id (Growi Content Submission ID) lets the backend attribute // brand-built Meta ads. Prefer the live URL param, fall back to the // cookie captured on the landing page. const gcsId = window.growiCookieUtils.getQueryParam('gcs_id') || window.growiCookieUtils.getCookie('growi_gcs_id'); const gcsQuery = gcsId ? `&gcs_id=${encodeURIComponent(gcsId)}` : ''; fetch( `https://api.growi.io/api/v1/campaign_affiliates/${encodeURIComponent( affiliateId )}/discount_code?url=${encodeURIComponent(currentUrl)}${gcsQuery}`, { method: 'GET', headers: { 'Content-Type': 'application/json', }, } ) .then((response) => { if (!response.ok) throw new Error('Network response was not ok'); return response.json(); }) .then((data) => { if (data.success) { cookieDuration = data.cookie_duration; if (!!cookieDuration) { updateAffiliateCookieDuration(cookieDuration); console.log('✅ Affiliate cookie duration updated:', cookieDuration); } } if (data.success && data.discount_code) { // Set discount_code cookie for 30 days window.growiCookieUtils.setCookie('discount_code', data.discount_code, 30); // Set new response format cookies if (data.affiliate_name) { window.growiCookieUtils.setCookie('affiliate_name', data.affiliate_name, 30); } if (data.discount_type) { window.growiCookieUtils.setCookie('discount_type', data.discount_type, 30); } if (data.discount_value) { window.growiCookieUtils.setCookie('discount_value', data.discount_value, 30); } if (data.campaign_type) { window.growiCookieUtils.setCookie('campaign_type', data.campaign_type, 30); } console.log('✅ Discount code cookies set:', data.discount_code); // Show discount modal only for ambassador programs and if not seen yet const discountSeen = window.growiCookieUtils.getCookie('discount_seen'); const isDiscountSeen = discountSeen && discountSeen === `${affiliateId}`.toLowerCase(); if (!isDiscountSeen) { if (data.is_v2) { showDiscountModalV2( data.discount_code, data.affiliate_name, data.discount_value, data.discount_type, affiliateId ); } else { showDiscountModal( data.discount_code, data.affiliate_name, data.discount_value, data.discount_type, affiliateId ); } } else { // If modal was already seen, show banner instead (if not dismissed) const bannerDismissed = window.growiCookieUtils.getCookie('banner_dismissed'); const isBannerDismissed = bannerDismissed && bannerDismissed === `${affiliateId}`.toLowerCase(); if (!isBannerDismissed) { // Check if banner is enabled before showing fetchCustomization(affiliateId).then((customization) => { if (customization && customization.banner_enabled) { showBanner(affiliateId, data.discount_code, customization); } }); } } } }) .catch((error) => { console.error('There has been a problem with your fetch operation:', error); }); } // --- Discount code logic end --- sendOneTimePageView(externalId); }) .catch((err) => { console.error('❌ Failed to update cart attributes', err); }); } else { console.log('ℹ️ No affiliate data to process'); } } // Start the process - wait for utils first, then URL stability console.log('🚀 [GROWI-EMBED] Starting waitForUtils() immediately...'); console.log('🚀 [GROWI-EMBED] Current timestamp:', new Date().toISOString()); waitForUtils(); // Also try on window.load as a fallback for very slow WebViews window.addEventListener('load', () => { setTimeout(() => { console.log('🔄 [WINDOW-LOAD] Window load backup trigger fired (500ms after window.load)'); console.log('🔄 [WINDOW-LOAD] window.growiCookieUtils exists?', typeof window.growiCookieUtils !== 'undefined'); initializeAffiliate(); }, 500); }); })(); Skip to main content
RYZE Rye Tm 3d Side Pose 1

HALLOWEEN SALE
UP TO 50% OFF + FREE GIFTS

  • Try Now
  • Our Story
  • Recipes
  • Manage Subscription
  • Shop on Demand
  • Gift Sets
  • Recipes
  • Contact Us
  • Facebook
  • Instagram
  • Twitter
  • Pinterest

Shop Our Bestseller!

Mushroom Coffee Ritual Set (3 Month Plan)
BESTSELLER
RYZE Ritual Set
70 Servings
View
Not ready for the full Ritual? Start Here!
Mushroom Coffee (30 Servings)
Mushroom Coffee
30 Servings
View
Mushroom Coffee Starter Kit (60 servings)
RYZE Starter Kit
60 Servings
View
Shop on Demand
Gift Sets
Recipes
Contact Us
Manage Subscription
  • Mushroom Coffee
    30 Servings

    $27 $45 40% OFF
    LEARN MORE
  • Mushroom Coffee - Dark Roast
    30 Servings

    $27 $45 40% OFF
    LEARN MORE
  • Mushroom Matcha
    30 Servings

    $36 $64 43% OFF
    LEARN MORE
  • Mushroom Hot Cocoa
    20 Servings

    $27 $45 40% OFF
    LEARN MORE
Cart

Collections

  • two brown pouches labeled Mushroom Coffee and one pale cream pouch labeled Superfood Creamer and Vanilla.

    3 bag kits

    3 bag kits

  • RYZE Mushroom Coffee bag

    3 Month Upgrade

    3 Month Upgrade

  • Four RYZE-branded stand-up pouches arranged together on a white background: two dark brown mushroom coffee pouches in back and two pale cream creamer pouches in front labeled Superfood Creamer, Vanilla.

    All bundles and kits

    All bundles and kits

  • RYZE Medium Roast Single Bag 02

    All Discount Products

    All Discount Products

  • RYZE Probiotic Creamer (SPECIAL PRICING)

    All Products With Creamer

    All Products With Creamer

  • B2B test

  • RYZE Medium Roast Single Bag 02

    b2b-blends

    B2B Blends test collection

    b2b-blends

  • Black Friday

  • RYZE Informative Image N1

    BYBO RYZE ADDONS

    BYBO RYZE ADDONS

  • RYZE Informative Image N1 2

    BYOB RYZE

    BYOB RYZE

  • Ryze Mushroom Chai package on a white background

    Chai Single Bag

    Chai Single Bag

  • Three packages of RYZE Superfood Creamer on a white background

    Creamer

    Creamer

  • RYZE Dark Roast Single Bag 02 Compressed

    Dark Roast

    Dark Roast

  • RYZE Medium Roast Single Bag 02

    First Time

    First Time

  • Three RYZE mushroom product packages on a white background

    Gift Bundles

    Gift Bundles

  • Gummies

    Gummies

    Gummies

  • Two stand-up pouches of RYZE Mushroom Coffee, Bright & Smooth flavor, shown on a plain white background.

    Headless Price Testing

    Headless Price Testing

  • RYZE Medium Roast Single Bag 02

    Holiday Gifting

    Holiday Gifting

  • Two stand-up pouches of Ryze Food Creamer in Pumpkin Spice flavor, shown overlapping on a plain white background.

    Limited Edition Creamer

    Limited Edition Creamer

  • RYZE Medium Roast Single Bag 02

    Main

    Main

  • Ryze Mushroom Chai package on a white background

    Main Chai Products

    Main Chai Products

  • RYZE Mushroom Chicory package with abstract design on a white background

    Main Chicory Products

    Main Chicory Products

  • RYZE Chocolate Indulgence Bundle: Mushroom Hot Cocoa bag, RYZE recipe box, Mushroom Chocolates box, coaster, acacia scoop...

    Main Chocolate Products

    Main Chocolate Products

  • Ryze Mushroom Hot Cocoa package with colorful design on a white background

    Main Cocoa Products

    Main Cocoa Products

  • RYZE Medium Roast Single Bag 02

    Main Coffee Products

    Main Coffee Products

  • two dark brown stand-up pouches labeled Dark Roast Mushroom Coffee (Rich & Robust) in the back, and two pale cream pouches labeled Superfood Creamer.

    Main Creamer Products

    Main Creamer Products

  • Green package of RYZE Mushroom Matcha on a white background

    Main Matcha Products

    Main Matcha Products

  • RYZE Informative Image N1

    Main Oats Products

    Main Oats Products

  • Mushroom Chai

    Mushroom Chai

    Mushroom Chai

  • Mushroom Chicory - RYZE

    Mushroom Chicory

    All chicory products

    Mushroom Chicory

  • 1
  • 2
RYZE

Loaded with adaptogenic mushrooms, our blend supports everyday energy, focus and immune health for a balanced routine.

  • Surprise! You discovered Rye.

    Here to spread a little joy in your day.
    Here's a 15% off code for you.

    RYZENSHINE!

  • About The Brand
  • Store Locator
  • Manage Subscription
  • Track Your Order
  • Careers
  • Coffee Shops - Partner with Us
  • Privacy policy
  • Terms of sale
  • Refund policy
  • Do Not Share or Sell My Personal Information
  • Accessibility

© 2026, RYZE Superfoods All Rights Reserved

"These statements have not been evaluated by the Food and Drug Administration. This product is not intended to diagnose, treat, or prevent any disease."
  • Choosing a selection results in a full page refresh.
  • Opens in a new window.