With a lightweight aluminium frame and wide range of gears, the Ridgeback Velocity is modern utility bike built for everyday riding.
Shimano's reliable Acera groupset features 24-gears, making tough climbs manageable and still giving enough scope for high speed work on the flat.
Mounts for mudguards and racks add versatility, allowing you to turn the bike into a load-lugger or wet-weather commuter.Close
V-brakes provide assured stopping power and puncture resistant tyres give you added peace-of-mind when encountering poor road conditions.
Weight - 14.5kg
25-01-07T15:16:47+00:00","alt":null,"width":1200,"height":880,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-ELECTRICBLUE-0_4906f91c-a920-4ef6-9dc1-f0eeda6290ab.jpg?v=1736263007","variant_ids":[44049932812514]},"available":false,"name":"Frog 61 - Electric Blue","public_title":"Electric Blue","options":["Electric Blue"],"price":46350,"weight":0,"compare_at_price":51500,"inventory_management":"shopify","barcode":"","featured_media":{"alt":null,"id":63810026144127,"position":5,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-ELECTRICBLUE-0_4906f91c-a920-4ef6-9dc1-f0eeda6290ab.jpg?v=1736263007"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":44049932878050,"title":"Green","option1":"Green","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":{"id":72808891089279,"product_id":8082534826210,"position":6,"created_a
t":"2025-01-07T15:16:47+00:00","updated_at":"2025-01-07T15:16:47+00:00","alt":null,"width":1200,"height":880,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-GREEN-0.default_a2585bb4-683b-4938-8de0-0fe5906e24d0.jpg?v=1736263007","variant_ids":[44049932878050]},"available":true,"name":"Frog 61 - Green","public_title":"Green","options":["Green"],"price":46350,"weight":0,"compare_at_price":51500,"inventory_management":"shopify","barcode":"","featured_media":{"alt":null,"id":63810026176895,"position":6,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-GREEN-0.default_a2585bb4-683b-4938-8de0-0fe5906e24d0.jpg?v=1736263007"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":44049932976354,"title":"Orange","option1":"Orange","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":{"id":72808890925439,"product_id":80825348262
10,"position":2,"created_at":"2025-01-07T15:16:47+00:00","updated_at":"2025-01-07T15:16:47+00:00","alt":null,"width":1200,"height":880,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-ORANGE-0_cec6ab92-d3f0-4ddd-a437-065b021785e8.jpg?v=1736263007","variant_ids":[44049932976354]},"available":false,"name":"Frog 61 - Orange","public_title":"Orange","options":["Orange"],"price":46350,"weight":0,"compare_at_price":51500,"inventory_management":"shopify","barcode":"","featured_media":{"alt":null,"id":63810026045823,"position":2,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-ORANGE-0_cec6ab92-d3f0-4ddd-a437-065b021785e8.jpg?v=1736263007"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":44049933009122,"title":"Purple","option1":"Purple","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":{"id":72808890990975,"product
_id":8082534826210,"position":3,"created_at":"2025-01-07T15:16:47+00:00","updated_at":"2025-01-07T15:16:47+00:00","alt":null,"width":1200,"height":880,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-PURPLE-0_c726a8e4-95ef-4000-bccf-40c4cb1e5d91.jpg?v=1736263007","variant_ids":[44049933009122]},"available":false,"name":"Frog 61 - Purple","public_title":"Purple","options":["Purple"],"price":46350,"weight":0,"compare_at_price":51500,"inventory_management":"shopify","barcode":"","featured_media":{"alt":null,"id":63810026078591,"position":3,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-PURPLE-0_c726a8e4-95ef-4000-bccf-40c4cb1e5d91.jpg?v=1736263007"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":44049933041890,"title":"Red","option1":"Red","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":{"id":7280889089267
1,"product_id":8082534826210,"position":1,"created_at":"2025-01-07T15:16:47+00:00","updated_at":"2025-01-07T15:16:47+00:00","alt":null,"width":1200,"height":880,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-RED-0_f64b6c8b-0baf-4eea-8db3-310355059fe2.jpg?v=1736263007","variant_ids":[44049933041890]},"available":true,"name":"Frog 61 - Red","public_title":"Red","options":["Red"],"price":46350,"weight":0,"compare_at_price":51500,"inventory_management":"shopify","barcode":"","featured_media":{"alt":null,"id":63810026013055,"position":1,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-RED-0_f64b6c8b-0baf-4eea-8db3-310355059fe2.jpg?v=1736263007"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-RED-0_f64b6c8b-0baf-4eea-8db3-310355059fe2.jpg?v=1736263007","\/\/projektride.co.uk\/cdn\/shop\/files\/L-F
H61_media-ORANGE-0_cec6ab92-d3f0-4ddd-a437-065b021785e8.jpg?v=1736263007","\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-PURPLE-0_c726a8e4-95ef-4000-bccf-40c4cb1e5d91.jpg?v=1736263007","\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-BLACK-0_fc82bed3-0eab-49ed-94a7-f321cccc1219.jpg?v=1736263007","\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-ELECTRICBLUE-0_4906f91c-a920-4ef6-9dc1-f0eeda6290ab.jpg?v=1736263007","\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-GREEN-0.default_a2585bb4-683b-4938-8de0-0fe5906e24d0.jpg?v=1736263007"],"featured_image":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-RED-0_f64b6c8b-0baf-4eea-8db3-310355059fe2.jpg?v=1736263007","options":["Colour"],"media":[{"alt":null,"id":63810026013055,"position":1,"preview_image":{"aspect_ratio":1.364,"height":880,"width":1200,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/L-FH61_media-RED-0_f64b6c8b-0baf-4eea-8db3-310355059fe2.jpg?v=1736263007"},"aspect_ratio":1.364,"height":880,"media_type":"image","src":"\/\/<
version>/assets/...
// Trailing digits (e.g. ".../restockrocket-1-521/assets/" -> "521"). Kept numeric to
// match ParseStoqData, so funnel app_version lines up with the order-attribution
// app_version. Reflects the ACTUAL deployed build. This is the SINGLE source of the
// parsed version — preorder.js getAppVersion() reads it back off config rather than
// re-parsing, so the regex lives in exactly one place.
try {
const _stoqVersionMatch = window._RestockRocketConfig.scriptHost.match(/(\d+)\/?(?:assets\/?)?$/);
window._RestockRocketConfig.appVersion = (_stoqVersionMatch && _stoqVersionMatch[1]) || '';
} catch (e) {
window._RestockRocketConfig.appVersion = '';
}
const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds
const LIQUID_CACHE_MAX_AGE = 15 * 60; // 15 minutes in seconds
// Calculate Liquid cache freshness once at initialization
const liquidRenderedAt = window._RestockRocketConfig.liquidRenderedAt;
// Validate timestamp and calculate ca
che age
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); // Current time in seconds
const liquidCacheAge = now - liquidRenderedAt; // Age in seconds
// Surfaced into funnel events: a stale cache means the app rendered with
// outdated inventory/selling-plan data — a real "had the opportunity but
// failed" cause. Negative (client clock ahead) clamps to 0.
window._RestockRocketConfig.liquidCacheAge = Math.max(0, liquidCacheAge);
// Handle client clock ahead of server
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
<);
}
function initializeScripts(settings) {
settings = applyTranslations(settings);
window._RestockRocketConfig.settings = settings;
console.debug(`STOQ - settings configured for ${window._RestockRocketConfig.pageType}`);
// Stale-Liquid resilience (default-on, per-shop opt-out via the
// `disable_refresh_on_stale_liquid` Toggle, surfaced as the negative
// `disable_refresh_on_stale_liquid` flag in settings.json so that
// `undefined` -- in CDN-cached metafield payloads that predate this
// key -- reads as `!undefined === true` and gets default-on behavior
// immediately, no metafield rewrite required).
// When the Liquid CDN cache is older than LIQUID_CACHE_MAX_AGE the in-page
// selling_plans / integrations metafields can be wrong; refresh both from
// the API before launching scripts. Race against a 1000ms timeout so a slow
// API can't block init indefinitely. If the timeout wins, the in-flight
// fetches still complete and update window._Resto
ckRocketConfig — the
// bundle re-reads sellingPlans/integrations on every interaction, so the
// late-arriving values benefit subsequent renders even though the first
// paint may use the Liquid-cached values. On any failure the existing
// Liquid-loaded values stay in place via fetchEmbedConfig's catch.
if (!window._RestockRocketConfig.isLiquidCacheFresh && !settings.disable_refresh_on_stale_liquid) {
console.debug('STOQ - Liquid cache stale, refreshing selling_plans + integrations');
Promise.race([
Promise.all([
fetchEmbedConfig('selling_plans', function(data) {
if (data && Array.isArray(data.plans)) {
window._RestockRocketConfig.sellingPlans = data.plans;
window._RestockRocketConfig.disabledSellingPlanIds = data.disabled_plan_ids || [];
}
}),
fetchEmbedConfig('integrations', function(data) {
if (Array.isArray(data)) {
window._RestockRocketConfig.integrations
= data;
}
})
]),
new Promise(function(resolve) { setTimeout(resolve, 1000); })
]).then(function() { loadScripts(settings); });
return;
}
loadScripts(settings);
}
function loadScripts(settings) {
// Setup cart selling plan updater BEFORE loading any scripts to avoid race conditions
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);
})
// STOQ-1520: serve the lean back-in-stock-only build (no preorder/hijack code)
// only to shops with NO preorder plans. Use the full build if preorder is on,
// an enabled offer exists, or a disabled-but-kept plan id remains (cart sweep
// must still strip those). Rationale in the PR.
const hasEnabledOffer = Arra
y.isArray(window._RestockRocketConfig.sellingPlans)
&& window._RestockRocketConfig.sellingPlans.some(function(plan) { return plan && plan.enabled; });
const hasDisabledPlanIds = Array.isArray(window._RestockRocketConfig.disabledSellingPlanIds)
&& window._RestockRocketConfig.disabledSellingPlanIds.length > 0;
const usePreorderBuild = settings.preorder_enabled || hasEnabledOffer || hasDisabledPlanIds;
const collectionScriptUrl = usePreorderBuild
? window._RestockRocketConfig.scriptUrlCollection
: window._RestockRocketConfig.scriptUrlCollectionBis;
const productScriptUrl = usePreorderBuild
? window._RestockRocketConfig.scriptUrlProduct
: window._RestockRocketConfig.scriptUrlProductBis;
const pageType = window._RestockRocketConfig.pageType;
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(window._RestockRocketConfig.scriptUrlCollection);
} else if(usePreorderBuild) {
// cart/article/blog/list-collections: full build so the cart sweep runs.
createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection);
} else {
console.debug(`STOQ - no scripts enabled for ${pageType}`);
}
// Dispatch custom event when app is loaded
// Cart selling plan updates will be triggered by stoq:inventory-data-loaded event
const appLoadedEvent = new CustomEvent('stoq:loaded', {
detail: {
pageType: window._RestockRocketConfig.pageType,
enabled: settings.enable_app,
settings: settings,
preorderEnabled: settings.preorder_enabled
}
});
consol
e.debug('STOQ - dispatching app loaded event');
window.dispatchEvent(appLoadedEvent);
}
}