Looking to purchase with a cycle to work scheme?Mauritius (MUR₨)
Header ImageClick here
to get in touch and get the ball rolling!Mayotte (EUR€)
The Avenida 6 is Ridgeback's city bike with easy-to-use gearing - perfect for flatter environments. Comfort continues through the specification, as the Avenida boasts ergonomic handlebar grips, a high level of seat padding and a suspension seatpost to take out any jarring bumps.
Generously equipped, the Avenida 6 also features mudguards to keep road spray at bay and a rear rack, which can be fitted with pannier bags - meaning no more sweaty rucksacks.Monaco (EUR€) The bike also features an adjustable stem, allowing you to customise your handlebar position for a relaxed and stress-free ride, with durable tyres designed to minimise the risk of punctures from road debris completing the package.
Weight - 14.37kg  
Rim
Mozambique (GBP£)
Namibia (GBP£)
Fork Material :   Mauritius (MUR₨) Faroe Islands (DKKkr.)

Moldova (MDLL) France (EUR€)
Togo (XOFFr)
Hubs :Monaco (EUR€) French Southern Territories (EUR€)
Joytech JY-753F / JY-754R / front / rear
Montenegro (EUR€) Gabon (XOFFr)
Tunisia (GBP£)
Morocco (MADد.م.) Gambia (GMDD) Mudguard : Türkiye (GBP£)
  FittedMozambique (GBP£) Georgia (GBP£) Namibia (GBP£) Germany (EUR€) Pedals : Ukraine (UAH₴) United Kingdom (GBP£) Niger (XOFFr) Gibraltar (GBP£) Nigeria (NGN₦) Greece (EUR€)  
Shimano Tourney RD-TY300 Vatican City (EUR€)
Western Sahara (MADد.م.)
Rims :Norway (GBP£) Guadeloupe (EUR€) Poland (PLNzł) Guernsey (GBP£)
 Somalia (GBP£) Liberia (GBP£) #productTemplate--template--26482384994687__main { --PT: 60px; --PB: 30px; }
Kenda Kwick Journey 700 x 40c
South Africa (GBP£) Libya (GBP£) Frame Shape : South Sudan (GBP£) Liechtenstein (CHFCHF) Spain (EUR€) Lithuania (EUR€)
Gender :St. Helena (SHP£) Luxembourg (EUR€)
  Mens, Womens
Sudan (GBP£) Madagascar (GBP£)
[] Switzerland (CHFCHF) Malta (EUR€)
#relatedProducts--template--26482385912191__related { --PT: 60px; --PB: 60px; } #relatedProducts--template--26482385912191__related .tabs__nav { --text-size: calc(var(--adjust-accent) * 1.2); } @media screen and (max-width: 767px) { #relatedProducts--template--26482385912191__related .grid--mobile, #relatedProducts--template--26482385912191__related .carousel--mobile { grid-template-columns: repeat(1, minmax(0, 1fr)); } }
This section doesn’t currently include any content. Add content to this section using the sidebar.
Tristan da Cunha (GBP£) Mayotte (EUR€)
#Accordions--template--26482385912191__section_accordions_with_images_3mP8Yx { --PT: 60px; --PB: 60px; --border-opacity: 0; --border-width: 1px; --MB: 10px; --padding-left: 0; --bg-padded-line: var(--bg); } #Accordions--template--26482385912191__section_accordions_with_images_3mP8Yx .section__heading { --heading-size: calc(var(--adjust-heading) * 1.2); } #Accordions--template--26482385912191__section_accordions_with_images_3mP8Yx .accordion__item { --bg-item: #fafafa; }
Tunisia (GBP£) Moldova (MDLL)
Türkiye (GBP£) Frequently Asked Questions Monaco (EUR€)
Uganda (UGXUSh) Montenegro (EUR€)
I'm looking to find out more information about a product, where can I find this?

Ukraine (UAH₴) Please get in touch with a member of the team either by phone (Morocco (MADد.م.)
01313745324

) or email (
[email protected]
United Kingdom (GBP£) ) where on of the team will be more than happy to help.Mozambique (GBP£)
ProjektRide Bike Shop Edinburgh


United States (GBP£) Namibia (GBP£)

I'm looking to buy this product, when will it arrive and how much does postage cost?

Vatican City (EUR€) If the item is showing in stock, we aim to post the product within 24 hours. Please allow 5 working days to receive the item. Netherlands (EUR€)
Postage is free on orders over £50. Orders under £50, our postage charge is £3.99. ProjektRide Bike Shop Edinburgh Western Sahara (MADد.م.) 82 Newington Road, EH91QN, Edinburgh.Niger (XOFFr)
Zambia (GBP£) Nigeria (NGN₦)
Zimbabwe (USD$) #SiteFooter { --PT: 100px; --PB: 10px; --bg-lighten-darken-shimmer-bg: #0d0d0d; --bg-lighten-darken-shimmer-effect: #121212; --text: #ffffff; --text-alpha-15: rgba(255, 255, 255, 0.15); --text-alpha-50: rgba(255, 255, 255, 0.6); --text-alpha-85: rgba(255, 255, 255, 0.85);--border: #ffffff;} #SiteFooter .footer-bottom { --grid-columns: 3; }North Macedonia (MKDден) #SiteFooter .footer-block--logo { min-width: calc(160px + calc(var(--gutter) / 2)); } #SiteFooter .footer-block__logo-image { width: 160px; }
Buy, sell and ride in confidence on ProjektRide’s premium bikes Quick Links© 2026, ProjektRide .
About Us
Powered by
Shopify
.Contact Us BlogAmerican Express
Track Service Progress
Apple Pay
Building Your Bike From the Box DiscoverInsure Your Bike Google Pay
Privacy Policy
Klarna
Cookie Policy MastercardTerms of Service
PayPalRefund policy
Satispay
Union Pay Servicing
Visa
Book a Service
Workshop Prices Cycle to Work
Delivery & Returns
Information Mon - Fri: 08:30 - 17:30 Sat: 9:00 - 16:00 Sun: Closed
0131 374 5324
Newington Road
Edinburgh
EH9 1QN
await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.shop-follow-button.en.esm.js");
Country
GBP£
Close
= 0); }); } else { _sqArm = (_sqc.integrations || []).some(function (i) { return i && i.type === 'featured_product' && i.enabled && Array.isArray(i.page_types) && i.page_types.indexOf(_sqc.pageType) !== -1; }); } } if (_sqArm && document.documentElement) { _sqc.acceleratedGateArmed = true; document.documentElement.classList.add('stoq-buy-now-pending'); setTimeout(function () { document.documentElement.classList.remove('stoq-buy-now-pending'); }, 6000); } } catch (e) { } window._RestockRocketConfig.scriptUrlProduct = 'https://cdn.shopify.com/extensions/01a1cf87-0c5a-7dbe-b46c-5802cf5d64ec/restockrocket-1-641/assets/restockrocket-product.js' window._RestockRocketConfig.scriptUrlCollection = 'https://cdn.shopify.com/extensions/01a1cf87-0c5a-7dbe-b46c-5802cf5d64ec/restockrocket-1-641/assets/restockrocket-collection.js' window._RestockRocketConfig.scriptUrlCollectionFull = 'https://cdn.shopify.com/extensie) { window._RestockRocketConfig.appVersion = ''; } const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; const LIQUID_CACHE_MAX_AGE = 15 * 60; const liquidRenderedAt = window._RestockRocketConfig.liquidRenderedAt; if (!liquidRenderedAt || typeof liquidRenderedAt !== 'number' || isNaN(liquidRenderedAt)) { console.debug('STOQ - Invalid or missing liquidRenderedAt timestamp, assuming fresh'); window._RestockRocketConfig.isLiquidCacheFresh = true; window._RestockRocketConfig.liquidCacheAge = null; } else { const now = Math.floor(Date.now() / 1000); const liquidCacheAge = now - liquidRenderedAt; window._RestockRocketConfig.liquidCacheAge = Math.max(0, liquidCacheAge); if (liquidCacheAge 0) { console.debug(`STOQ - Client clock appears ahead of server by ${Math.abs(Math.round(liquidCacheAge / 60))} minutes, assuming cache fresh`); window._RestockRocketConfig.isLiquidCacheFresh = true; } else if (liquidCacheAge = LIQUID_CACHE_MAX_AGE) { console.debug(`STOQ - Liquid cache is fresh (${Math.round(liquidCacheAge / 60)} minutes old)`); window._RestockRocketConfig.isLiquidCacheFresh = true; } else { console.debug(`STOQ - Liquid cache is stale (${Math.round(liquidCacheAge / 60)} minutes old, max ${Math.round(LIQUID_CACHE_MAX_AGE / 60)} minutes)`); window._RestockRocketConfig.isLiquidCacheFresh = false; } } function checkSettingsExpiry(settings) { try { if (!settings || !settings.updated_at) { console.debug('STOQ - Invalid settings data structure'); return null; } if (!settings.cache) { console.debug('STOQ - settings caching disabled'); return null; } if (settings.multi_language_enabled) { if (!settings.translations) { console.debug('STOQ - multi-language enabled but no translation data in cache, fetching fresh'); return null; } if (window._RestockRocketConfig.normalizedLocale &
<
.body.appendChild(plainScriptElement); }; restockRocketScriptElement.src = scriptUrl; document.body.appendChild(restockRocketScriptElement); } createRestockRocketContainer() console.debug('STOQ - extension activated') try { const _stoqInitConfig = window._RestockRocketConfig; const _stoqDetectedVariantIds = (_stoqInitConfig.product && Array.isArray(_stoqInitConfig.product.variants)) ? _stoqInitConfig.product.variants.map(function(v) { return v.id }) : []; const _stoqSelectedVariantId = _stoqInitConfig.selected_variant_id; var _stoqPageSeq = 0; try { _stoqPageSeq = (parseInt(window.sessionStorage.getItem('_stoq_pls') || '0', 10) || 0) + 1; window.sessionStorage.setItem('_stoq_pls', String(_stoqPageSeq)); } catch (e) { } Shopify?.analytics?.publish?.('stoq_initialized', { cart_token: _stoqInitConfig.cartToken || '', page_url: window.location.origin + window.location.pathname, page_type: _stoqInitConfig.pageType || '',
.closest('.shopify-payment-button, shopify-payment-terms'); if (!host) return; var channel = host.matches && host.matches('shopify-payment-terms') ? 'shop_pay_installments' : 'buy_now'; var form = host.closest('form'); var vidEl = form && form.querySelector('[name="id"]'); var variantId = (vidEl && vidEl.value) || _sqTrack.selected_variant_id || ''; var _sqVidNum = Number(variantId); var _sqPlan = null; var _sqPlans = Array.isArray(_sqTrack.sellingPlans) ? _sqTrack.sellingPlans : []; var _sqMktId = Number(_sqTrack.marketId); var _sqOffersOn = !!(_sqTrack.readFlags && _sqTrack.readFlags.enable_storefront_plan_offers === true); var _sqAlloc = _sqOffersOn ? ((_sqTrack.offerAllocations && _sqTrack.offerAllocations[_sqVidNum]) || (_sqTrack.variantSellingPlanIds && _sqTrack.variantSellingPlanIds[_sqVidNum])) : null; var _sqPlanIds = function (pl)
_sqPlans.forEach(function (pl) { if (!_sqPlan && _sqForVariant(pl) && !pl.markets_enabled) { _sqPlan = pl; } }); } Shopify?.analytics?.publish?.('stoq_accelerated_checkout_clicked', { variant_id: variantId, product_id: (_sqTrack.product && _sqTrack.product.id) || '', channel: channel, market_id: _sqTrack.marketId || '', country_code: _sqTrack.countryIsoCode || '', page_type: _sqTrack.pageType || '', cart_token: _sqTrack.cartToken || '', page_url: (window.location && window.location.origin + window.location.pathname) || '', properties: { is_preorder_variant: (function () { var vid = Number(variantId); var has = function (a) { return Array.isArray(a) && a.indexOf(vid) !== -1; }; return has(_sqTrack.preorderVariantIds) || has(_sqTrack.cachedPreorderVariantIds && lassList.contains('stoq-buy-now-pending')), blocked: (function () { try { var rr = window._RestockRocket; return !!(rr && typeof rr.willBlockAcceleratedClick === 'function' && rr.willBlockAcceleratedClick(e)); } catch (err) { return false; } })(), }, }); } catch (err) { } }, true); } } catch (e) { } function applyTranslations(settings) { try { if (!settings || !settings.multi_language_enabled) { return settings; } if (!settings.translations) { console.debug('STOQ - No translations found, skipping translation'); return settings; } const normalizedLocale = window._RestockRocketConfig.normalizedLocale; const translations = settings.translations; if (!normalizedLocale) { console.debug('STOQ - No matching locale for translations. Available:', Object.keys(translations || {})); 'STOQ - Inventory data loaded, updating cart selling plans'); if (window._RestockRocket && window._RestockRocket.updateCartSellingPlans) { window._RestockRocket.updateCartSellingPlans() .then(hasUpdates => { if (hasUpdates) { console.debug('STOQ - cart selling plans updated successfully'); } else { console.debug('STOQ - no cart selling plan updates needed'); } }) .catch(error => { console.error('STOQ - error updating cart selling plans:', error); }); } }); } function storefrontGraphql(query, variables) { const cfg = window._RestockRocketConfig; let token = cfg.storefrontAccessToken || null; if (!token && typeof cfg.sk === 'string' && cfg.sk !== '') { try { token = atob(cfg.sk).split('').reverse().join('') || null; } catch (e) { token = null; } } if (!token || cfg.disableStorefrontApi === true) { return Promise.reject(new Error('Storefrourn storefrontGraphql(query, { namespace: cfg.metafieldNamespace, key: key }) .then(function(data) { const value = data && data.shop && data.shop.metafield && data.shop.metafield.value; if (!value) { throw new Error('Storefront API returned no ' + key + ' metafield value'); } return JSON.parse(value); }); } function fetchStorefrontSettings() { const query = 'query StoqSettings($namespace: String!) { shop { settings: metafield(namespace: $namespace, key: "settings") { value } translations: metafield(namespace: $namespace, key: "settings_translations") { value } } }'; return storefrontGraphql(query, { namespace: window._RestockRocketConfig.metafieldNamespace }) .then(function(data) { const settings = JSON.parse(data.shop.settings.value); if (!settings.updated_at) { throw new Error('settings metafield is not a settings payload'); } if (settings.single_locale_translations_inline) { settings.translations = data.shop.translations && JSON.parse(data const storefrontRead = window._RestockRocketConfig.readFlags?.enable_storefront_settings_read === true ? Promise.race([ fetchStorefrontSettings(), new Promise(function(_, reject) { setTimeout(function() { reject(new Error('timed out')); }, 1500); }) ]).catch(function(error) { console.debug('STOQ - Storefront settings read failed, using setting.json:', error.message); }) : Promise.resolve(); storefrontRead .then(function(settings) { return settings || fetch( `${window._RestockRocketConfig.host}/api/v1/setting.json?translation_locale=${window._RestockRocketConfig.normalizedLocale}`, { headers } ) .then(function(response) { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }); }) .then(function(settings) { initializeScripts(settings); }) .catch(function(error) { if (cachedSettings) { console.de
r.message); }); } function refreshShopConfig(source) { const cfg = window._RestockRocketConfig; const viaEmbed = function() { return fetchEmbedConfig(source.endpoint, source.apply); }; const flagOn = !!cfg.readFlags && cfg.readFlags[source.flag] === true; if (!flagOn) { return viaEmbed(); } return fetchStorefrontShopMetafield(source.metafieldKey) .then(function(value) { if (!source.isValid(value)) { throw new Error(source.metafieldKey + ' metafield is not a valid ' + source.endpoint + ' payload'); } source.apply(value); console.debug('STOQ - refreshed ' + source.endpoint + ' from the Storefront API'); }) .catch(function(error) { console.debug('STOQ - Storefront ' + source.endpoint + ' read failed, using embed:', error.message); return viaEmbed(); }); } function refreshIntegrations() { const cfg = window._RestockRocketConfig; return refreshShopConfig({ endpoint: 'integrations', metafieldKey: 'in
ngs configured for ${window._RestockRocketConfig.pageType}`); const staleRefresh = !window._RestockRocketConfig.isLiquidCacheFresh && !settings.disable_refresh_on_stale_liquid; if (staleRefresh) { console.debug('STOQ - refreshing selling_plans + integrations (Liquid cache stale)'); Promise.race([ Promise.all([refreshSellingPlans(), refreshIntegrations()]), new Promise(function(resolve) { setTimeout(resolve, 1000); }) ]).then(function() { loadScripts(settings); }); return; } loadScripts(settings); } function loadScripts(settings) { setupCartSellingPlanUpdater(settings); if(settings.enable_app) { const hijackIntegration = window._RestockRocketConfig.integrations.find(function(integration) { return integration.type === 'hijack' && integration.enabled && integration.page_types.includes(window._RestockRocketConfig.pageType); }) const hasEnabledOffer = Array.isArray(window._RestockRocketConfig.sellingPlans) && w
ionScriptUrl = preorderUiOnPage ? window._RestockRocketConfig.scriptUrlCollectionFull : window._RestockRocketConfig.scriptUrlCollection; const collectionScriptUrl = usePreorderBuild ? preorderCollectionScriptUrl : window._RestockRocketConfig.scriptUrlCollectionBis; const productScriptUrl = usePreorderBuild ? window._RestockRocketConfig.scriptUrlProduct : window._RestockRocketConfig.scriptUrlProductBis; const collectionPageTypes = ['collection', 'index', 'search', 'page']; if(collectionPageTypes.indexOf(pageType) !== -1 && (settings[`show_button_on_${pageType}`] || settings[`preorder_${pageType}_enabled`])) { createRestockRocketScript(collectionScriptUrl); } else if(pageType === 'product') { createRestockRocketScript(productScriptUrl); } else if(hijackIntegration) { createRestockRocketScript(preorderCollectionScriptUrl); } else if(usePreorderBuild) { createRestockRocketScript(preorderColl
|| !(wishlistImageHeart || document.querySelector(wishlistHeartTarget))) return; wishlistHeartsRequested = true; createRestockRocketScript(window._RestockRocketConfig.scriptHost + 'restockrocket-wishlist-hearts.js'); }; loadWishlistHearts(); document.addEventListener('shopify:section:load', loadWishlistHearts); } if (document.querySelector('[data-stoq-wishlist-page]')) { createRestockRocketScript(window._RestockRocketConfig.scriptHost + 'restockrocket-wishlist-page.js'); } try { if (localStorage.getItem('stoq_wl_host') !== window._RestockRocketConfig.scriptHost) localStorage.setItem('stoq_wl_host', window._RestockRocketConfig.scriptHost); } catch (e) {} try { const guestWishlist = window._RestockRocketConfig.customer && !localStorage.getItem('stoq_wl_c') && JSON.parse(localStorage.getItem('stoq_wl')); if (Array.isArray(guestWishlist) && guestWishlist.length) {

® connect system lets you easily disconnect the drink tube from the reservoir for easy filling\nMade of ultra-durable, abrasion resistant TPU \u0026amp; RF welded seams for superior durability and elasticity\n100% BPA \u0026amp; PVC free, wide working temperature range (can be frozen - max temp 60° C \/ 140° F)\nCAPACITY: 2 L \/ 70 fl oz\nWEIGHT: 121 g \/ 4.3 oz\nDIMENSIONS: 343 mm x 170 mm \/ 13.5 in x 6.7 in\nMATERIALS: TPU, ABS, POM, PP, EPDM, Silicone, 304SS, TPU Coated Nylon Fabric\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","image":"https:\/\/projektride.co.uk\/cdn\/shop\/files\/15392.jpg?v=1720880043\u0026width=1920","name":"Hydrapak Velocity 2L","offers":{"@id":"\/products\/hydrapak-velocity-2l?variant=45694285021410#offer","@type":"Offer","availability":"http:\/\/schema.org\/InStock","price":"38.00","priceCurrency":"GBP","url":"https:\/\/projektride.co.uk\/products\/hydrapak-velocity-2l?variant=45694285021410"},"url":"https:\/\/projektride.co.uk\/products\/hydrapak-veloc
  • 4287184098 : "",}; window._RestockRocketConfig.variantsShippingTextForMarket = {45694287184098 : null,};window._RestockRocketConfig.selected_variant_id = 45694287184098; window._RestockRocketConfig.selected_variant_available = (window._RestockRocketConfig.product.variants.find(function(variant) { return variant.id == window._RestockRocketConfig.selected_variant_id }) || {}).available; (function (c) { c.cartInventoryQuantity = {}; function s(k, id, v) { if (v !== null) (c[k] = c[k] || {})[id] = v; } function sm(k, id, v) { if (v !== null) ((c[k] = c[k] || {})[id] = {})[c.marketId] = v; } function p(k, id, v) { if (v !== null) (c[k] = c[k] || []).push(id); } })(window._RestockRocketConfig); try { var _sqCfg = window._RestockRocketConfig; var _sqPlanEnabled = Array.isArray(_sqCfg.sellingPlans) && _sqCfg.sellingPlans.some(function (p) { return p && p.enabled; }); var _sqPreCount = _sqCfg.inlinePreorderIdsDropped ? _sqCfg.cachedPreorderVariantIdsCount : (

    _plan_id)); (Array.isArray(p.payment_options) ? p.payment_options : []).forEach(function (o) { if (o) _sqAlwaysPlanIds.push(Number(o.shopify_selling_plan_id)); }); } }); var _sqAllocAlways = function (id) { var a = _sqGateAlloc && _sqGateAlloc[id]; return Array.isArray(a) && a.some(function (planId) { return planId && _sqAlwaysPlanIds.indexOf(Number(planId)) !== -1; }); }; var _sqArm = false; if (_sqOn && (_sqc.preordersConfigured || _sqAlways.length || _sqAlwaysPlanIds.length)) { if (_sqc.pageType === 'product' && _sqc.product && _sqc.product.variants) { _sqArm = _sqc.product.variants.some(function (v) { return _sqPre.indexOf(Number(v.id)) !== -1 || _sqAlways.indexOf(Number(v.id)) !== -1 || _sqAllocAlways(Number(v.id)) || (_sqc.inlinePreorderIdsDropped === true && (_sqc.variantsInventoryPolicy || {})[v.id] === 'continue' && (_sqc.variantsInventoryQuantity || {})[v.id] = 0); }); } else { _sqArm = (_sqc.integrations || []).some(function (i) { return i && i.type === 'featured_product' && i.enabled && Array.isArray(i.page_types) && i.page_types.indexOf(_sqc.pageType) !== -1; }); } } if (_sqArm && document.documentElement) { _sqc.acceleratedGateArmed = true; document.documentElement.classList.add('stoq-buy-now-pending'); setTimeout(function () { document.documentElement.classList.remove('stoq-buy-now-pending'); }, 6000); } } catch (e) { } window._RestockRocketConfig.scriptUrlProduct = 'https://cdn.shopify.com/extensions/01a1cf87-0c5a-7dbe-b46c-5802cf5d64ec/restockrocket-1-641/assets/restockrocket-product.js' window._RestockRocketConfig.scriptUrlCollection = 'https://cdn.shopify.com/extensions/01a1cf87-0c5a-7dbe-b46c-5802cf5d64ec/restockrocket-1-641/assets/restockrocket-collection.js' window._RestockRocketConfig.scriptUrlCollectionFull = 'https://cdn.shopify.com/extensie) { window._RestockRocketConfig.appVersion = ''; } const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; const LIQUID_CACHE_MAX_AGE = 15 * 60; const liquidRenderedAt = window._RestockRocketConfig.liquidRenderedAt; if (!liquidRenderedAt || typeof liquidRenderedAt !== 'number' || isNaN(liquidRenderedAt)) { console.debug('STOQ - Invalid or missing liquidRenderedAt timestamp, assuming fresh'); window._RestockRocketConfig.isLiquidCacheFresh = true; window._RestockRocketConfig.liquidCacheAge = null; } else { const now = Math.floor(Date.now() / 1000); const liquidCacheAge = now - liquidRenderedAt; window._RestockRocketConfig.liquidCacheAge = Math.max(0, liquidCacheAge); if (liquidCacheAge 0) { console.debug(`STOQ - Client clock appears ahead of server by ${Math.abs(Math.round(liquidCacheAge / 60))} minutes, assuming cache fresh`); window._RestockRocketConfig.isLiquidCacheFresh = true; } else if (liquidCacheAge = LIQUID_CACHE_MAX_AGE) { console.debug(`STOQ - Liquid cache is fresh (${Math.round(liquidCacheAge / 60)} minutes old)`); window._RestockRocketConfig.isLiquidCacheFresh = true; } else { console.debug(`STOQ - Liquid cache is stale (${Math.round(liquidCacheAge / 60)} minutes old, max ${Math.round(LIQUID_CACHE_MAX_AGE / 60)} minutes)`); window._RestockRocketConfig.isLiquidCacheFresh = false; } } function checkSettingsExpiry(settings) { try { if (!settings || !settings.updated_at) { console.debug('STOQ - Invalid settings data structure'); return null; } if (!settings.cache) { console.debug('STOQ - settings caching disabled'); return null; } if (settings.multi_language_enabled) { if (!settings.translations) { console.debug('STOQ - multi-language enabled but no translation data in cache, fetching fresh'); return null; } if (window._RestockRocketConfig.normalizedLocale &

    <

    .body.appendChild(plainScriptElement); }; restockRocketScriptElement.src = scriptUrl; document.body.appendChild(restockRocketScriptElement); } createRestockRocketContainer() console.debug('STOQ - extension activated') try { const _stoqInitConfig = window._RestockRocketConfig; const _stoqDetectedVariantIds = (_stoqInitConfig.product && Array.isArray(_stoqInitConfig.product.variants)) ? _stoqInitConfig.product.variants.map(function(v) { return v.id }) : []; const _stoqSelectedVariantId = _stoqInitConfig.selected_variant_id; var _stoqPageSeq = 0; try { _stoqPageSeq = (parseInt(window.sessionStorage.getItem('_stoq_pls') || '0', 10) || 0) + 1; window.sessionStorage.setItem('_stoq_pls', String(_stoqPageSeq)); } catch (e) { } Shopify?.analytics?.publish?.('stoq_initialized', { cart_token: _stoqInitConfig.cartToken || '', page_url: window.location.origin + window.location.pathname, page_type: _stoqInitConfig.pageType || '',
    .closest('.shopify-payment-button, shopify-payment-terms'); if (!host) return; var channel = host.matches && host.matches('shopify-payment-terms') ? 'shop_pay_installments' : 'buy_now'; var form = host.closest('form'); var vidEl = form && form.querySelector('[name="id"]'); var variantId = (vidEl && vidEl.value) || _sqTrack.selected_variant_id || ''; var _sqVidNum = Number(variantId); var _sqPlan = null; var _sqPlans = Array.isArray(_sqTrack.sellingPlans) ? _sqTrack.sellingPlans : []; var _sqMktId = Number(_sqTrack.marketId); var _sqOffersOn = !!(_sqTrack.readFlags && _sqTrack.readFlags.enable_storefront_plan_offers === true); var _sqAlloc = _sqOffersOn ? ((_sqTrack.offerAllocations && _sqTrack.offerAllocations[_sqVidNum]) || (_sqTrack.variantSellingPlanIds && _sqTrack.variantSellingPlanIds[_sqVidNum])) : null; var _sqPlanIds = function (pl)
  • _sqPlans.forEach(function (pl) { if (!_sqPlan && _sqForVariant(pl) && !pl.markets_enabled) { _sqPlan = pl; } }); } Shopify?.analytics?.publish?.('stoq_accelerated_checkout_clicked', { variant_id: variantId, product_id: (_sqTrack.product && _sqTrack.product.id) || '', channel: channel, market_id: _sqTrack.marketId || '', country_code: _sqTrack.countryIsoCode || '', page_type: _sqTrack.pageType || '', cart_token: _sqTrack.cartToken || '', page_url: (window.location && window.location.origin + window.location.pathname) || '', properties: { is_preorder_variant: (function () { var vid = Number(variantId); var has = function (a) { return Array.isArray(a) && a.indexOf(vid) !== -1; }; return has(_sqTrack.preorderVariantIds) || has(_sqTrack.cachedPreorderVariantIds && lassList.contains('stoq-buy-now-pending')), blocked: (function () { try { var rr = window._RestockRocket; return !!(rr && typeof rr.willBlockAcceleratedClick === 'function' && rr.willBlockAcceleratedClick(e)); } catch (err) { return false; } })(), }, }); } catch (err) { } }, true); } } catch (e) { } function applyTranslations(settings) { try { if (!settings || !settings.multi_language_enabled) { return settings; } if (!settings.translations) { console.debug('STOQ - No translations found, skipping translation'); return settings; } const normalizedLocale = window._RestockRocketConfig.normalizedLocale; const translations = settings.translations; if (!normalizedLocale) { console.debug('STOQ - No matching locale for translations. Available:', Object.keys(translations || {}));
    'STOQ - Inventory data loaded, updating cart selling plans'); if (window._RestockRocket && window._RestockRocket.updateCartSellingPlans) { window._RestockRocket.updateCartSellingPlans() .then(hasUpdates => { if (hasUpdates) { console.debug('STOQ - cart selling plans updated successfully'); } else { console.debug('STOQ - no cart selling plan updates needed'); } }) .catch(error => { console.error('STOQ - error updating cart selling plans:', error); }); } }); } function storefrontGraphql(query, variables) { const cfg = window._RestockRocketConfig; let token = cfg.storefrontAccessToken || null; if (!token && typeof cfg.sk === 'string' && cfg.sk !== '') { try { token = atob(cfg.sk).split('').reverse().join('') || null; } catch (e) { token = null; } } if (!token || cfg.disableStorefrontApi === true) { return Promise.reject(new Error('Storefro

    urn storefrontGraphql(query, { namespace: cfg.metafieldNamespace, key: key }) .then(function(data) { const value = data && data.shop && data.shop.metafield && data.shop.metafield.value; if (!value) { throw new Error('Storefront API returned no ' + key + ' metafield value'); } return JSON.parse(value); }); } function fetchStorefrontSettings() { const query = 'query StoqSettings($namespace: String!) { shop { settings: metafield(namespace: $namespace, key: "settings") { value } translations: metafield(namespace: $namespace, key: "settings_translations") { value } } }'; return storefrontGraphql(query, { namespace: window._RestockRocketConfig.metafieldNamespace }) .then(function(data) { const settings = JSON.parse(data.shop.settings.value); if (!settings.updated_at) { throw new Error('settings metafield is not a settings payload'); } if (settings.single_locale_translations_inline) { settings.translations = data.shop.translations && JSON.parse(data

    const storefrontRead = window._RestockRocketConfig.readFlags?.enable_storefront_settings_read === true ? Promise.race([ fetchStorefrontSettings(), new Promise(function(_, reject) { setTimeout(function() { reject(new Error('timed out')); }, 1500); }) ]).catch(function(error) { console.debug('STOQ - Storefront settings read failed, using setting.json:', error.message); }) : Promise.resolve(); storefrontRead .then(function(settings) { return settings || fetch( `${window._RestockRocketConfig.host}/api/v1/setting.json?translation_locale=${window._RestockRocketConfig.normalizedLocale}`, { headers } ) .then(function(response) { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }); }) .then(function(settings) { initializeScripts(settings); }) .catch(function(error) { if (cachedSettings) { console.de

    r.message); }); } function refreshShopConfig(source) { const cfg = window._RestockRocketConfig; const viaEmbed = function() { return fetchEmbedConfig(source.endpoint, source.apply); }; const flagOn = !!cfg.readFlags && cfg.readFlags[source.flag] === true; if (!flagOn) { return viaEmbed(); } return fetchStorefrontShopMetafield(source.metafieldKey) .then(function(value) { if (!source.isValid(value)) { throw new Error(source.metafieldKey + ' metafield is not a valid ' + source.endpoint + ' payload'); } source.apply(value); console.debug('STOQ - refreshed ' + source.endpoint + ' from the Storefront API'); }) .catch(function(error) { console.debug('STOQ - Storefront ' + source.endpoint + ' read failed, using embed:', error.message); return viaEmbed(); }); } function refreshIntegrations() { const cfg = window._RestockRocketConfig; return refreshShopConfig({ endpoint: 'integrations', metafieldKey: 'in

    ngs configured for ${window._RestockRocketConfig.pageType}`); const staleRefresh = !window._RestockRocketConfig.isLiquidCacheFresh && !settings.disable_refresh_on_stale_liquid; if (staleRefresh) { console.debug('STOQ - refreshing selling_plans + integrations (Liquid cache stale)'); Promise.race([ Promise.all([refreshSellingPlans(), refreshIntegrations()]), new Promise(function(resolve) { setTimeout(resolve, 1000); }) ]).then(function() { loadScripts(settings); }); return; } loadScripts(settings); } function loadScripts(settings) { setupCartSellingPlanUpdater(settings); if(settings.enable_app) { const hijackIntegration = window._RestockRocketConfig.integrations.find(function(integration) { return integration.type === 'hijack' && integration.enabled && integration.page_types.includes(window._RestockRocketConfig.pageType); }) const hasEnabledOffer = Array.isArray(window._RestockRocketConfig.sellingPlans) && w

    ionScriptUrl = preorderUiOnPage ? window._RestockRocketConfig.scriptUrlCollectionFull : window._RestockRocketConfig.scriptUrlCollection; const collectionScriptUrl = usePreorderBuild ? preorderCollectionScriptUrl : window._RestockRocketConfig.scriptUrlCollectionBis; const productScriptUrl = usePreorderBuild ? window._RestockRocketConfig.scriptUrlProduct : window._RestockRocketConfig.scriptUrlProductBis; const collectionPageTypes = ['collection', 'index', 'search', 'page']; if(collectionPageTypes.indexOf(pageType) !== -1 && (settings[`show_button_on_${pageType}`] || settings[`preorder_${pageType}_enabled`])) { createRestockRocketScript(collectionScriptUrl); } else if(pageType === 'product') { createRestockRocketScript(productScriptUrl); } else if(hijackIntegration) { createRestockRocketScript(preorderCollectionScriptUrl); } else if(usePreorderBuild) { createRestockRocketScript(preorderColl

    || !(wishlistImageHeart || document.querySelector(wishlistHeartTarget))) return; wishlistHeartsRequested = true; createRestockRocketScript(window._RestockRocketConfig.scriptHost + 'restockrocket-wishlist-hearts.js'); }; loadWishlistHearts(); document.addEventListener('shopify:section:load', loadWishlistHearts); } if (document.querySelector('[data-stoq-wishlist-page]')) { createRestockRocketScript(window._RestockRocketConfig.scriptHost + 'restockrocket-wishlist-page.js'); } try { if (localStorage.getItem('stoq_wl_host') !== window._RestockRocketConfig.scriptHost) localStorage.setItem('stoq_wl_host', window._RestockRocketConfig.scriptHost); } catch (e) {} try { const guestWishlist = window._RestockRocketConfig.customer && !localStorage.getItem('stoq_wl_c') && JSON.parse(localStorage.getItem('stoq_wl')); if (Array.isArray(guestWishlist) && guestWishlist.length) {