Surly
See Moregress_bar_fill_color":"#000000","preorder_progress_bar_background_color":"#e5e5e5","preorder_progress_bar_text_color":"#FFFFFF","preorder_progress_bar_border_radius":4,"preorder_progress_bar_show_percentage":false}];window._RestockRocketConfig.integrations = [{"id":"15c94526-b6b8-4de1-9bc1-23b1ca52ddb0","shop_id":38436,"enabled":true,"page_types":["product","collection","index","search","page","cart","list-collections","article","blog"],"configuration":{"toastDuration":10000,"toastPosition":"bottom-right","enableXHRHijack":true,"enableFetchHijack":true,"quantityLimitDisabled":false},"type":"hijack","css_config":null,"js_config":null,"created_at":"2025-07-26T09:16:04.076Z","updated_at":"2025-07-26T09:16:04.076Z"}];window._RestockRocketConfig.obfuscateInventoryQuantity = false;window._RestockRocketConfig.product = {"id":14965979775359,"title":"Hire Ortlieb 40L Pannier Bags","handle":"hire-ortlieb-40l-pannier-bags","description":"\u003cdiv\u003e\n\u003cdiv class=\"flex h-full flex-col justify-center gap-3\"\u003
rying comfort when taken off the rack.\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cbutton class=\"heading-button flex min-h-[52px] w-full py-2.5 items-center\" type=\"button\"\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\u003cbutton class=\"heading-button flex min-h-[52px] w-full py-2.5 items-center\" type=\"button\"\u003e\u003cspan class=\"ml-auto inline-block h-6 transition duration-300 rotate-180\"\u003e\u003csvg viewbox=\"0 0 32 32\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"h-full w-4 rotate-90 text-[#D31716]\"\u003e\u003cpath fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M19.775 16 4.555 7.629l2.89-5.258L24.26 11.62c3.454 1.9 3.454 6.863 0 8.762L7.447 29.63l-2.893-5.26L19.774 16Z\" fill=\"currentColor\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/span\u003e\u003c\/button\u003e\u003c\/div\u003e","publis
rying comfort when taken off the rack.\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003cstrong\u003e\u003c\/strong\u003e\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cbutton class=\"heading-button flex min-h-[52px] w-full py-2.5 items-center\" type=\"button\"\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\u003cbutton class=\"heading-button flex min-h-[52px] w-full py-2.5 items-center\" type=\"button\"\u003e\u003cspan class=\"ml-auto inline-block h-6 transition duration-300 rotate-180\"\u003e\u003csvg viewbox=\"0 0 32 32\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"h-full w-4 rotate-90 text-[#D31716]\"\u003e\u003cpath fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M19.775 16 4.555 7.629l2.89-5.258L24.26 11.62c3.454 1.9 3.454 6.863 0 8.762L7.447 29.63l-2.893-5.26L19.774 16Z\" fill=\"currentColor\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/span\u003e\u003c\/button\u003e\u003c\/div\u003e","publis
:["Title"],"media":[{"alt":null,"id":64543150244223,"position":1,"preview_image":{"aspect_ratio":1.215,"height":745,"width":905,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/resize_width_1000.jpg?v=1741085512"},"aspect_ratio":1.215,"height":745,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/resize_width_1000.jpg?v=1741085512","width":905}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cdiv\u003e\n\u003cdiv class=\"flex h-full flex-col justify-center gap-3\"\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003cspan class=\"text-xl font-semibold text-default-text\"\u003eOrtlieb Back-Roller 40L Pannier Bags - ProjektRide Bike Hire Edinburgh.\u003c\/span\u003e\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003cspan\u003e\u003c\/span\u003e\u003c\/div\u003e\n\u003cdiv class=\"text-lighter-text\"\u003e\u003cspan\u003eSupplied as a pair, these rear pannier bags have hermetical roll closures, shoulder straps so you can take them with you at your desti
pan class=\"ml-auto inline-block h-6 transition duration-300 rotate-180\"\u003e\u003csvg viewbox=\"0 0 32 32\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"h-full w-4 rotate-90 text-[#D31716]\"\u003e\u003cpath fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M19.775 16 4.555 7.629l2.89-5.258L24.26 11.62c3.454 1.9 3.454 6.863 0 8.762L7.447 29.63l-2.893-5.26L19.774 16Z\" fill=\"currentColor\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/span\u003e\u003c\/button\u003e\u003c\/div\u003e"};
window._RestockRocketConfig.variantsInventoryPolicy = {55162210320767 : "deny",};
window._RestockRocketConfig.variantsInventoryQuantity = {55162210320767 : parseInt("-63"),};
window._RestockRocketConfig.variantsPreorderCount = {55162210320767 : parseInt(""),};
window._RestockRocketConfig.variantsPreorderCountForMarket = {55162210320767 : null,};
window._RestockRocketConfig.variantsPreorderMaxCount = {55162210320767 : parseInt(""),};
window._RestockRocketConfig.variantsPreorderMaxCountF
}.restock-rocket-preorder-progress-bar{padding:12px 15px;margin-bottom:20px;font-family:inherit;}.restock-rocket-preorder-progress-bar .preorder-progress-text{margin-bottom:8px;}.restock-rocket-preorder-progress-bar .preorder-progress-bar-row{display:flex;align-items:center;gap:10px;}.restock-rocket-preorder-progress-bar .preorder-progress-track{flex:1;height:12px;overflow:hidden;}.restock-rocket-preorder-progress-bar .preorder-progress-fill{display:block;height:100%;min-width:2px;transition:width 0.3s ease;}.restock-rocket-preorder-progress-bar .preorder-progress-percentage{font-weight:500;min-width:35px;text-align:right;}
Handlebars
window._RestockRocketConfig.host = 'https://app.restockrocket.io'
const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds
const LIQUID_CACHE_MAX_AGE = 2 * 60 * 60; // 2 hours in seconds
// Calculate Liquid cache freshness once at initialization
const liquidRenderedAt = window._RestockRocketConfig.liquidRenderedAt;
// Validate timestamp and calculate cache age
if (!liquidRenderedAt || typeof liquidRenderedAt !== 'number' || isNaN(liquidRenderedAt)) {
console.debug('STOQ - Invalid or missing liquidRenderedAt timestamp, assuming fresh');
window._RestockRocketConfig.isLiquidCacheFresh = true;
} else {
const now = Math.floor(Date.now() / 1000); // Current time in seconds
const liquidCacheAge = now - liquidRenderedAt; // Age in seconds
// Handle client clock ahead of server
if (liquidCacheAge
uto;min-width:0}.restock-rocket-preorder-discount-badge{background:#ebebeb;height:25px;line-height:25px;padding:0 15px;border-radius:25px;font-size:0.8rem;flex:0 0 auto}.restock-rocket-payment-input{margin-right:10px;margin-top:-3px;vertical-align:middle;margin-left:0;accent-color:#202223}.restock-rocket-payment-description{margin-top:4px;flex:1 1 100%}.restock-rocket-preorder-badge{font-size:13px;line-height:1;padding:5px 13px 6px;border-radius:40px;height:auto;border:none;width:auto;z-index:2;margin:0;background:0 0}.preorder-badge-collection{position:absolute;top:10px;right:10px}.preorder-badge-product{margin-left:10px}.restock-rocket-price-strike{text-decoration:line-through;color: #666666;}.restock-rocket-discounted-price{margin-left:10px;}.restock-rocket-acknowledgement-checkbox{margin-bottom:12px;display:flex;align-items:flex-start;gap:8px;font-size:14px;line-height: 1.5;}.restock-rocket-acknowledge-checkbox-input{width:18px;height:18px;margin-top:2px;cursor:pointer;flex-shrink:0;accent-color: #0d0d0d;ck-rocket-preorder-countdown-timer .countdown-label{font-size:11px}}@media (max-width:480px){.restock-rocket-preorder-countdown-timer{padding:12px}.restock-rocket-preorder-countdown-timer .countdown-units{width:100%;gap:10px}.restock-rocket-preorder-countdown-timer .countdown-box{width:100%;min-width:50px;padding:12px 8px;font-size:24px}.restock-rocket-preorder-countdown-timer .countdown-label{font-size:10px}}.restock-rocket-toast{position:fixed;cursor:pointer;background:#fff;border:0;min-width:40px;min-height:40px;box-shadow:0 0 15px rgba(0,0,0,.1)!important;z-index:622004;padding:20px 30px;font-family:inherit;font-size:inherit;color:#000;display:flex;justify-content:center;align-items:center}.restock-rocket-toast a{text-decoration:none;font-weight:700;color:#000}.restock-rocket-toast .dismiss{margin-left:15px;z-index:1;font-size:20px;}.restock-rocket-toast-top{top:60px}.restock-rocket-toast-bottom{bottom:75px}.restock-rocket-toast-left,.restock-rocket-toast-right{-webkit-animation:.5s forwards slide;animatiwindow._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;
}
// Check if translations are enabled but missing from cache
// This handles the backfill period where DB has translations but metafield doesn't
if (settings.multi_language_enabled) {
if (!settings.translations) {
// Translations enabled but no age = Date.now() - updatedAt.getTime();
if (age
SETTINGS_CACHE_DURATION) {
console.debug('STOQ - settings changed recently, skipping cache');
return null;
}
return settings;
} catch (error) {
console.debug('STOQ - Error checking settings cache:', error);
return null;
}
}
function createRestockRocketContainer() {
const restockRocketContainer = document.createElement('div');
restockRocketContainer.id = 'restock-rocket';
document.body.appendChild(restockRocketContainer);
}
function createRestockRocketScript(scriptUrl) {
const restockRocketScriptElement = document.createElement('script');
restockRocketScriptElement.setAttribute('defer', 'defer');
restockRocketScriptElement.src = scriptUrl;
document.body.appendChild(restockRocketScriptElement);
}
createRestockRocketContainer()
console.debug('STOQ - extension activated')
function applyTranslations(settings) {
try {
// Skip translation logic entirely if multi-language is not enabled
if (!settings ||
f translatedFields === 'object') {
Object.keys(translatedFields).forEach(function(key) {
const value = translatedFields[key];
if (value !== null && value !== undefined && value !== '') {
settings[key] = value;
}
});
} else {
console.debug('STOQ - No translated fields found for locale:', normalizedLocale);
}
delete settings.translations;
return settings;
} catch (e) {
console.debug('STOQ - error applying translations:', e);
return settings;
}
}
// Setup event listener for cart selling plan updates
// This must be called before any scripts are loaded to avoid race conditions
function setupCartSellingPlanUpdater(settings) {
if (!settings || !settings.preorder_enabled) {
return;
}
// Listen for stoq:preorder-api-ready event dispatched by preorder.js
window.addEventListener('stoq:preorder-api-ready', function(event) {
console.debug('STOQ - Preorder API ready, updating-Domain': window._RestockRocketConfig.shop || window.Shopify.shop,
'ngrok-skip-browser-warning': 'skip'
};
if (window.Shopify?.theme?.role === 'main') {
headers['X-Shopify-Theme-Schema-Name'] = window.Shopify.theme.schema_name;
headers['X-Shopify-Theme-Schema-Version'] = window.Shopify.theme.schema_version;
headers['X-Shopify-Theme-Store-Id'] = window.Shopify.theme.theme_store_id;
}
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 request failed and we have cached settings (even if expired), use them as fallback
if (cachedSettings) {
console.debug('STOQ - using expired cached createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'index' && (settings.show_button_on_index || settings.preorder_index_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'search' && (settings.show_button_on_search || settings.preorder_search_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'page' && (settings.show_button_on_page || settings.preorder_page_enabled)) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else if(window._RestockRocketConfig.pageType === 'product') {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlProduct);
} else if(hijackIntegration) {
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
Cleaners, Degreasers and Lubrication
Maintenance
- Log in
- £50
- to qualify for free shippingCongratulations! Your order qualifies for free shipping
Early Rider

Log in
Cart
£50