Vecnum free1 QENCE -
THE ultimate suspension stem with the longest travel, damping an sag. Effectively absorbs up to 75% of vibrations and shocks.
2
Scope of delivery:
1x Suspension stem Vecnum freeQENCE in desired length
1x Manual for operation, mounting, maintenance3
1x Gauge for testing the minimum distance from stem to head tube for freeQENCE 90
THE SUSPENSION STEM
4
More comfort, safety & fun.
For gravel, road, touring bikes,
suspensionless (e-)bikes.
5
MORE FUN ON THE BIKE
6
The suspension stem freeQENCE absorbs up to 75% of all vibrations and impacts and therefore reduces your fatigue. You are riding more comfortable, faster and safer on paved roads, cobblestones, gravel roads, singletrails and technical terrain. The significant relief of your wrists may also avoid tingling and numb hands.
7
GEOMETRY NEUTRAL
PARALLELOGRAM
The torsionally stiff and ultra compact parallelogram construction guarantees optimal absorption of vertical impacts. In contrast to single pivot suspension stems, the handle bar does not tilt down. In contrast to supension forks, the frame geometry remains unchanged. The freeQENCE parallelogram enables an internal spring linkage.8
TOP PERFORMANCE 9 IN ALL HANDLEBAR POSITIONS
In contrast to single pivot supsenion stems, the lever length does not influence the spring characteristics - due to the elaborate and complex parallelogram kinematics. No matter if you use your handebars hoods, drop or top position - suspension and damping performance always remain optimal.
10 +
30 MM TRAVEL
WITH DAMPING & SAG
Four unobtrusive but perfectly tuned high-tech elastomers protect you from harsh impacts and vibrations. The maximum suspension travel of 30mm is split into 20mm positive travel and 10mm negative travel - similar to the sag of a supension fork. The supension stem freeQENCE has a homogeneous, linear spring characteristic with srong progression towards the end of stroke.
Quantity
Decrease QuantityEXTERNALLY ADUSTABLE
FROM 50 TO 120 KG
The suspension stem freeQENCE offers you an external and steples adjustment to your weight and inteded riding style. The patented internal spring linkage makes setting up your desired spring characteristics easier than on any suspension fork.Increase Quantity
SPIRIT OF GRAVEL LIGHTWEIGHT, AGILE, STRONG
The freeQENCE design is consequently optimized for high loads and low weight - starting with 287 grams at 90mm length. That is only about 150 grams additional weight compared to a standard stem. Without the disadvantages of a supension fork, your bike does not suffer ftom aerodynamic losses, it remains light and agile when sprinting and riding out of the saddle. The bike geometry remains unchanged. You do not need a lockout for your freeQENCE stem.
SIMPLY
UPGRADE YOUR BIKE
The suspension stem freeQENCE is simply mounted like a standard a-head stem. Upgrading is easy and done in a few minutes. Thanks to the open face 4-screw clamping, nothing needs to be dismounted from your handlebars.
Add to Cart
£90.00
IN 3 LENGTHS £90.00 FOR ALL SUSPENSIONLESS BIKES
Available in 3 lengths - 90 mm, 105 mm, 120 mm.
For 1⅛ inch forks and all handlebar types with 31,8 mm diameter including carbon handlebars. Please note the required shaft length of your fork.
DESIGN. BUILD. RIDE. VECNUM ALLGAEU GERMANY
At Vecnum, development, CNC processing, assembly and field testing is all single source and under one roof. As usual we focus on highest quality: all structural freeQENCE parts are machined from solid AL7075, the stem is equipped with titanium axles and screws, etc. The suspension stem freeQENCE was tested externally by the independant EFBE laboratory according to their test standards for gravel stems and handlebars. This item is a deferred, subscription, or recurring purchase. By continuing, I agree to the
cancellation policy
and authorize you to charge my payment method at the prices, frequency and dates listed on this page until my order is fulfilled or I cancel, if permitted.
31,8mm diameter handlebars, including carbon, all widths and types
Required minimum distance from stem to head tube has to be tested with gauge included in freeQENCE 90 package
Your spacious one-click shopping bag: the Bike-Shopper with QL2.1 system can be quickly attached to and removed from your rack. The flexible market and shopping bag remains stable - also on bumpy roads. The adjustable carrying straps allow it to be carried comfortably on your shoulder (adjusted by velcro) and will not be in the way during biking. A waterproof Quick-Seal closure provides protection from rain. Occasional use of ORTLIEB lubricant will keep the closure running smoothly.
Fabric: PS33
Features: QL2.1
TypeHeight: 42cmfreeQENCEWidth: 23cm
Upper width: 32cm
freeQENCEDepth: 17cm 90 mm
Volume: 20L
Rider weight
Stepless and external adjustment from 50 to 120 kg
Please get in touch with a member of the team either by phone (Refund policy01313745324
) or email (
[email protected]
) where on of the team will be more than happy to help.Service
ProjektRide Bike Shop Edinburgh
Servicing
Book a Service
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.
Postage is free on orders over £50. Orders under £50, our postage charge is £3.99.
We also have a physical store, if you are local please pop in -Workshop Prices
_is_preorder":false,"enable_console_debug":false,"inline_form_enabled":false,"inline_form_selector":null,"inline_form_selector_type":"afterend","storefront_form_prefill_customer":true,"storefront_form_show_image":false,"storefront_form_text_color":"#202223","storefront_form_background_color":"#FFFFFF","storefront_form_border_radius":0,"market_setup_type":"single_market","shopify_app_id":5940125,"preorder_progress_bar_insert_selector":null,"preorder_progress_bar_insert_selector_type":"beforebegin","countdown_timer_insert_selector":null,"countdown_timer_insert_selector_type":"afterend","cache":true,"cached_at":"2026-01-08T16:12:13.364Z","multi_language_enabled":false,"translation_locale":"en"};window._RestockRocketConfig.cachedPreorderVariantIds = {"preorder_variant_ids":[42167799447778,43916521013474,43934694998242,43934695031010,43934695620834,43935975440610,43935975473378,43935989399778,43935989432546,43935990284514,43935994118370,43935995625698,43935995855074,43936000835810,43936003195106,43936003227874,439
36008012002,43936008044770,43936022757602,43936022790370,43936022823138,43936022855906,43936056115426,43936061030626,43936064930018,43936070631650,43936078037218,43936078069986,43936088195298,43936093470946,43936101138658,43936107266274,43936124076258,43936124109026,43936124141794,43936124174562,43936129941730,43936129974498,43936130007266,43936142393570,43936142426338,43936142459106,43936152060130,43936152092898,43936152125666,43936193118434,43936250429666,43936255803618,43936266682594,43936266715362,43936293978338,43936294011106,43936316424418,43936316457186,43936320880866,43936320913634,43936320946402,43936327041250,43936327074018,43936327106786,43936331661538,43936332349666,43936333103330,43936351224034,43936353714402,43936362889442,43936362922210,43936388153570,43936389333218,43936395526370,43936398508258,43936401522914,43936408568034,43936414400738,43936700727522,43936706101474,43936706134242,43936706167010,43936706199778,43936706232546,43936706265314,43938308587746,43938308653282,43938308718818,43938308751586,43938308784354,43938308817122,43938322612450,43938322645218,43938322677986,43981336051938,43981336084706,43981336117474,43981336150242,43981345587426,43981345620194,43981345652962,43981345685730,43981357580514,43981357613282,43981362462946,43981362495714,43981362528482,43981369016546,43981369049314,43981374914786,43981374947554,43981374980322,43981392773346,43981392806114,43981392838882,43981392904418,43981392937186,43981695844578,43981695877346,43981695910114,43981695942882,43981986070754,43981987905762,43981987938530,44052906967266,44052907327714,44052907360482,44052907393250,44052907426018,44052907458786,44052907491554,44052909097186,44052909129954,44140279791842,44140279824610,44140279857378,44140279890146,44140279922914,44140292047074,44140292079842,44140292112610,44140293685474,44140302336226,44140302434530,44140302500066,44140302532834,44140302565602,44140302598370,44140302631138,44140302827746,44140302893282,44140302926050,44140306301154,44140315050210,44140317016290,44140321636578,44140335792
354,44140335825122,44140335857890,44140339953890,44140339986658,44140340150498,44140340248802,44140340281570,44140340543714,44140340707554,44140340740322,44140340773090,44140345065698,44140352438498,44140388155618,44140388188386,44140397756642,44140404441314,44140404474082,44155590508770,44155590541538,44155594211554,44155594244322,44155594277090,44155594309858,44155594342626,44155594375394,44155594440930,44155594473698,44155594506466,44195991847138,44195991945442,44329993437410,44329993470178,44329993502946,44329993535714,44329993568482,44957136584930,44957136781538,44957136945378,45068753961186,45068753993954,45069622640866,45069622903010,45069622968546,45069750730978,45069750763746,45353010921698,45353010954466,45353010987234,45353018261730,45353018294498,45353018327266,55569712382335,55569712415103,55569712447871,55569712480639,55570017616255,55570550194559,55570550227327,55604008976767,55638316908927,55638316941695,55638316974463,56220814967167,56220814999935,56220815032703,56270279606655,56270279639423,56270279672191,56314171064703,56314171097471,56398983725439,56398983758207,56398983790975,56399322251647,56565020721535,56565020754303,56565020787071],"updated_at":"2026-04-04T19:39:42Z","market_locations_enabled":false,"market_id":382140642,"preorder_location_filter_enabled":false,"preorder_location_filter_ids":[],"collection_id":null};window._RestockRocketConfig.cachedInStockVariantIds = { in_stock_variant_ids: [] };window._RestockRocketConfig.cachedOutOfStockVariantIds = { out_of_stock_variant_ids: [] };window._RestockRocketConfig.cachedVariantPreorderLimits = {"variant_preorder_limits":{},"updated_at":"2026-04-04T19:34:33Z","shopify_market_id":382140642,"market_locations_enabled":false};
window._RestockRocketConfig.cachedVariantPreorderLimitsMarketKey = "variant_preorder_limits_for_market_382140642";window._RestockRocketConfig.cachedVariantShippingTexts = {"variant_shipping_texts":{},"updated_at":"2026-04-04T19:34:33Z","shopify_market_id":382140642,"market_locations_enabled":false};
window._Restoc
kRocketConfig.cachedVariantShippingTextsMarketKey = "variant_shipping_texts_for_market_382140642";window._RestockRocketConfig.sellingPlans = [{"shopify_selling_plan_group_id":98590196095,"shopify_selling_plan_id":713071886719,"enabled":true,"variant_ids":[55569712382335,55569712415103,55569712480639,55570017616255,55570017550719,55569712447871,55570017583487],"product_variants_source":"custom","name":"Preorder","preorder_button_text":"Preorder","preorder_button_description":"Note: This is a preorder. Items will ship based on the estimated delivery date.","preorder_button_description_background_color":"#ebebeb","preorder_button_description_text_color":"#000000","preorder_button_description_border_radius":10,"preorder_button_description_show_quantity_limit":false,"preorder_button_description_quantity_limit_suffix":" units available for preorder","preorder_button_description_shipping_text_prefix":"Shipping: ","delivery_exact_time":null,"delivery_after_n_intervals":null,"delivery_at":"2025-07-26T09:20:18.169Z","delivery_type":"asap","quantity_limit_text":"{{ quantity }} units available for preorder","preorder_button_description_show_shipping":true,"preorder_button_description_icons_enabled":true,"preorder_shipping_text":"Shipping: {{ date }}","shipping_applies_to_all_products":true,"shipping_text":"Estimated to ship within 2 months","payment_type":"full","billing_checkout_charge_type":"percentage","billing_checkout_charge_amount":null,"billing_checkout_charge_percentage":"100.0","pricing_type":"no_discount","pricing_amount":null,"pricing_percentage":null,"discount_text":"Save {{ discount }}","billing_title":"Full payment","billing_description":null,"enable_billing_widget":false,"inventory_provider":"stoq","preorder_badge_enabled":false,"preorder_badge_text":"Preorder","preorder_badge_text_color":"#FFFFFF","preorder_badge_background_color":"#000000","preorder_discounted_price_enabled":null,"payment_line_item_property_enabled":false,"shipping_line_item_property_enabled":true,"custom_line_item_property_text":null,"preor
der_button_text_color":"#ffffff","preorder_button_background_color":"#565557","preorder_button_colors_enabled":true,"markets_enabled":false,"market_id":13779632354,"shopify_market_ids":[],"use_shopify_selling_plan":true,"use_simplified_shipping_text":false,"translations":{},"payment_options":[{"billing_type":"no_remaining_balance","billing_checkout_charge_type":"percentage","billing_checkout_charge_amount":null,"billing_checkout_charge_percentage":"100.0","billing_at":"2025-07-26T09:20:38.472Z","billing_after_n_intervals":7,"billing_after_interval_type":"day","pricing_type":"no_discount","pricing_amount":null,"pricing_percentage":null,"billing_title":"Full payment","billing_description":null,"discount_text":"Save {{ discount }}","shopify_selling_plan_id":713071886719,"is_default":true,"type":"full","translations":{}}],"require_preorder_acknowledgement":false,"preorder_acknowledgement_text":"I acknowledge and agree to the preorder terms and conditions for this product.","disable_button_until_acknowledged":fals
e,"preorder_min_quantity":null,"preorder_max_quantity":null,"countdown_timer_enabled":false,"countdown_timer_style":"text","countdown_timer_text_color":"#000000","countdown_timer_background_color":"#f5f5f5","countdown_timer_border_radius":8,"countdown_timer_format":"DHMS","countdown_timer_use_schedule_dates":true,"countdown_timer_custom_start_date":null,"countdown_timer_custom_end_date":null,"countdown_timer_starts_text":null,"countdown_timer_ends_text":null,"schedule_offer":false,"schedule_start_date":null,"schedule_end_date":null,"updated_at":"2025-08-19T10:05:43.042Z","allow_mixed_cart":true,"mixed_cart_error_message":"Preorders must be purchased separately from regular items. Please complete your current order first, or clear your cart to continue.","b2b_enabled":true,"preorder_progress_bar_enabled":false,"preorder_progress_bar_text":"{{ sold }} of {{ total }} claimed","preorder_progress_bar_fill_color":"#000000","preorder_progress_bar_background_color":"#e5e5e5","preorder_progress_bar_text_color":"#FFFFF
F","preorder_progress_bar_border_radius":4,"preorder_progress_bar_show_percentage":false}];(function() {
const cachedData = {"plans":[{"shopify_selling_plan_group_id":98590196095,"shopify_selling_plan_id":713071886719,"enabled":true,"variant_ids":[55569712382335,55569712415103,55569712480639,55570017616255,55570017550719,55569712447871,55570017583487],"product_variants_source":"custom","name":"Preorder","preorder_button_text":"Preorder","preorder_button_description":"Note: This is a preorder. Items will ship based on the estimated delivery date.","preorder_button_description_background_color":"#ebebeb","preorder_button_description_text_color":"#000000","preorder_button_description_border_radius":10,"preorder_button_description_show_quantity_limit":false,"preorder_button_description_quantity_limit_suffix":" units available for preorder","preorder_button_description_shipping_text_prefix":"Shipping: ","delivery_exact_time":null,"delivery_after_n_intervals":null,"delivery_at":"2025-07-26T09:20:18.169Z","delivery_type":"asap","quantity_limit_text":"{{ quantity }} units available for preorder","preorder_button_description_show_shipping":true,"preorder_button_description_icons_enabled":true,"preorder_shipping_text":"Shipping: {{ date }}","shipping_applies_to_all_products":true,"shipping_text":"Estimated to ship within 2 months","payment_type":"full","billing_checkout_charge_type":"percentage","billing_checkout_charge_amount":null,"billing_checkout_charge_percentage":"100.0","pricing_type":"no_discount","pricing_amount":null,"pricing_percentage":null,"discount_text":"Save {{ discount }}","billing_title":"Full payment","billing_description":null,"enable_billing_widget":false,"inventory_provider":"stoq","preorder_badge_enabled":false,"preorder_badge_text":"Preorder","preorder_badge_text_color":"#FFFFFF","preorder_badge_background_color":"#000000","preorder_discounted_price_enabled":null,"payment_line_item_property_enabled":false,"shipping_line_item_property_enabled":true,"custom_line_item_property_text":null,"preorde
r_button_text_color":"#ffffff","preorder_button_background_color":"#565557","preorder_button_colors_enabled":true,"markets_enabled":false,"market_id":13779632354,"shopify_market_ids":[],"use_shopify_selling_plan":true,"use_simplified_shipping_text":false,"translations":{},"payment_options":[{"billing_type":"no_remaining_balance","billing_checkout_charge_type":"percentage","billing_checkout_charge_amount":null,"billing_checkout_charge_percentage":"100.0","billing_at":"2025-07-26T09:20:38.472Z","billing_after_n_intervals":7,"billing_after_interval_type":"day","pricing_type":"no_discount","pricing_amount":null,"pricing_percentage":null,"billing_title":"Full payment","billing_description":null,"discount_text":"Save {{ discount }}","shopify_selling_plan_id":713071886719,"is_default":true,"type":"full","translations":{}}],"require_preorder_acknowledgement":false,"preorder_acknowledgement_text":"I acknowledge and agree to the preorder terms and conditions for this product.","disable_button_until_acknowledged":false,
"preorder_min_quantity":null,"preorder_max_quantity":null,"countdown_timer_enabled":false,"countdown_timer_style":"text","countdown_timer_text_color":"#000000","countdown_timer_background_color":"#f5f5f5","countdown_timer_border_radius":8,"countdown_timer_format":"DHMS","countdown_timer_use_schedule_dates":true,"countdown_timer_custom_start_date":null,"countdown_timer_custom_end_date":null,"countdown_timer_starts_text":null,"countdown_timer_ends_text":null,"schedule_offer":false,"schedule_start_date":null,"schedule_end_date":null,"updated_at":"2025-08-19T10:05:43.042Z","allow_mixed_cart":true,"mixed_cart_error_message":"Preorders must be purchased separately from regular items. Please complete your current order first, or clear your cart to continue.","b2b_enabled":true,"preorder_progress_bar_enabled":false,"preorder_progress_bar_text":"{{ sold }} of {{ total }} claimed","preorder_progress_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}],"disabled_plan_ids":[713813721471,713176482175],"cached_at":"2026-02-18T08:36:42Z"};
if (cachedData && typeof cachedData === 'object' && cachedData.cached_at) {
// Find the maximum updated_at from all items in old array
const oldPlans = window._RestockRocketConfig.sellingPlans;
const maxUpdatedAt = Array.isArray(oldPlans) && oldPlans.length > 0
? oldPlans.reduce(function(max, plan) {
// Parse dates for proper comparison (handles mixed ISO formats)
if (plan.updated_at) {
const planDate = new Date(plan.updated_at);
const maxDate = max ? new Date(max) : null;
return (!maxDate || (planDate && !isNaN(planDate) && planDate > maxDate)) ? plan.updated_at : max;
}
return max;
}, '')
: null;
// Use cached if old array is empty/has no timestamps, or cached is newer
// Parse dates for comparison to handle format differences (+00:00 vs .000Z)
const cachedDate = new Date(cachedData.cached_at);
const maxDate = maxUpdatedAt ? new Date(maxUpdatedAt) : null;
const useCached = !maxUpdatedAt || (cachedDate && !isNaN(cachedDate) && (!maxDate || cachedDate > maxDate));
if (useCached) {
if (Array.isArray(cachedData.plans)) {
window._RestockRocketConfig.sellingPlans = cachedData.plans;
// Only use disabled_plan_ids when using cached plans
window._RestockRocketConfig.disabledSellingPlanIds = cachedData.disabled_plan_ids || [];
console.debug('[RR] Using selling plans from cachedSellingPlans (cached_at: ' + cachedData.cached_at + ')');
}
} else {
// When using old format (stale cache), don't trust disabled_plan_ids
window._RestockRocketConfig.disabledSellingPlanIds = [];
console.debug('[RR] Using selling plans from old format (max upda
ted_at: ' + maxUpdatedAt + ')');
}
}
})();window._RestockRocketConfig.enabledNotifyMeVariantIds = [];window._RestockRocketConfig.disabledNotifyMeVariantIds = [];window._RestockRocketConfig.backInStockTemplates = [];window._RestockRocketConfig.restockNotes = {};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":8677993742562,"title":"Ortlieb Bike Shopper","handle":"ortlieb-bike-shopper","description":"\u003cp\u003e \u003c\/p\u003e\n\u003cp\u003eYour spacious one-click shopping bag: the Bike-Shopper with QL2.1 system can be quickly attached to and removed from your rack. The flexible market and shopping bag remains stable - also on bumpy roads. The adjustable carrying straps allow it to be carried comfortably on your shoulder (adjusted by velcro) and will not be in the way during biking. A waterproof Quick-Seal closure provides protection from rain. Occasional use of ORTLIEB lubricant will keep the closure running smoothly.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eFabric: PS33\u003c\/li\u003e\n\u003cli\u003eFeatures: QL2.1\u003c\/li\u003e\n\u003cli\u003eHeight: 42cm\u003c\/li\u003e\n\u003cli\u003eWidth: 23cm\u003c\/li\u003e\n\u003cli\u003eUpper width: 32cm\u003c\/li\u003e\n\u003cli\u003eDepth: 17cm\u003c\/li\u003e\n\u003cli\u003eVolume: 20L\u003c\/li\u003e\n\u003cli\u003eWeight: 860g\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c!----\u003e","published_at":"2024-08-16T12:05:52+01:00","created_at":"2024-08-16T12:05:52+01:00","vendor":"ortlieb","
type":"Apparel \u0026 Accessories","tags":["Bike Packing","pannier","spo-cs-disabled","spo-default","spo-disabled","spo-notify-me-disabled"],"price":9000,"price_min":9000,"price_max":9000,"available":true,"price_varies":false,"compare_at_price":null,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":45820624994530,"title":"Blue","option1":"Blue","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Ortlieb Bike Shopper - Blue","public_title":"Blue","options":["Blue"],"price":9000,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[]},{"id":45820625027298,"title":"Black","option1":"Black","option2":null,"option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Ortlieb Bike Shopper - Black","public_title":"Black","options":["Black"],"price":9000,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[]}],"images":["\/\/projektride.co.uk\/cdn\/shop\/files\/21229.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21230.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21231.jpg?v=1723806326","\/\/projektride.co.uk\/cdn\/shop\/files\/21232.jpg?v=1723806326","\/\/projektride.co.uk\/cdn\/shop\/files\/21233.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21234.jpg?v=1723806326","\/\/projektride.co.uk\/cdn\/shop\/files\/21235.jpg?v=1723806326","\/\/projektride.co.uk\/cdn\/shop\/files\/21236.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21238.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21239.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21240.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21241.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21242.jpg?v=1723806327","\/\/projektride.co.uk
\/cdn\/shop\/files\/21243.jpg?v=1723806326","\/\/projektride.co.uk\/cdn\/shop\/files\/21244.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21245.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21246.jpg?v=1723806327","\/\/projektride.co.uk\/cdn\/shop\/files\/21247.jpg?v=1723806327"],"featured_image":"\/\/projektride.co.uk\/cdn\/shop\/files\/21229.jpg?v=1723806327","options":["Color"],"media":[{"alt":null,"id":34467991584994,"position":1,"preview_image":{"aspect_ratio":1.0,"height":1000,"width":1000,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21229.jpg?v=1723806327"},"aspect_ratio":1.0,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21229.jpg?v=1723806327","width":1000},{"alt":null,"id":34467991617762,"position":2,"preview_image":{"aspect_ratio":1.0,"height":1000,"width":1000,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21230.jpg?v=1723806327"},"aspect_ratio":1.0,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\
,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21244.jpg?v=1723806327","width":1000},{"alt":null,"id":34467992076514,"position":16,"preview_image":{"aspect_ratio":1.0,"height":1000,"width":1000,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21245.jpg?v=1723806327"},"aspect_ratio":1.0,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21245.jpg?v=1723806327","width":1000},{"alt":null,"id":34467992109282,"position":17,"preview_image":{"aspect_ratio":1.0,"height":1000,"width":1000,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21246.jpg?v=1723806327"},"aspect_ratio":1.0,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21246.jpg?v=1723806327","width":1000},{"alt":null,"id":34467992142050,"position":18,"preview_image":{"aspect_ratio":1.0,"height":1000,"width":1000,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/21247.jpg?v=1723806327"},"aspect_ratio":1.0,"height":1000,"media_type":"image","src":"\/\/projektride
.co.uk\/cdn\/shop\/files\/21247.jpg?v=1723806327","width":1000}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003e \u003c\/p\u003e\n\u003cp\u003eYour spacious one-click shopping bag: the Bike-Shopper with QL2.1 system can be quickly attached to and removed from your rack. The flexible market and shopping bag remains stable - also on bumpy roads. The adjustable carrying straps allow it to be carried comfortably on your shoulder (adjusted by velcro) and will not be in the way during biking. A waterproof Quick-Seal closure provides protection from rain. Occasional use of ORTLIEB lubricant will keep the closure running smoothly.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eFabric: PS33\u003c\/li\u003e\n\u003cli\u003eFeatures: QL2.1\u003c\/li\u003e\n\u003cli\u003eHeight: 42cm\u003c\/li\u003e\n\u003cli\u003eWidth: 23cm\u003c\/li\u003e\n\u003cli\u003eUpper width: 32cm\u003c\/li\u003e\n\u003cli\u003eDepth: 17cm\u003c\/li\u003e\n\u003cli\u003eVolume: 20L\u003c\/li\u003e\n\u003cli\u003eW
eight: 860g\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c!----\u003e"};
window._RestockRocketConfig.variantsInventoryPolicy = {45820624994530 : "deny",45820625027298 : "deny",};
window._RestockRocketConfig.variantsInventoryQuantity = {45820624994530 : parseInt("1"),45820625027298 : parseInt("1"),};
window._RestockRocketConfig.variantsPreorderCount = {45820624994530 : parseInt(""),45820625027298 : parseInt(""),};
window._RestockRocketConfig.variantsPreorderCountForMarket = {45820624994530 : null,45820625027298 : null,};
window._RestockRocketConfig.variantsPreorderMaxCount = {45820624994530 : parseInt(""),45820625027298 : parseInt(""),};
window._RestockRocketConfig.variantsPreorderMaxCountForMarket = {45820624994530 : null,45820625027298 : null,};
window._RestockRocketConfig.variantsShippingText = {45820624994530 : "",45820625027298 : "",};
window._RestockRocketConfig.variantsShippingTextForMarket = {45820624994530 : null,45820625027298 : null,};
window._RestockRocketConfig.selec
ted_variant_id = 45820624994530;
window._RestockRocketConfig.selected_variant_available = window._RestockRocketConfig.product.variants.find(function(variant) { return variant.id == window._RestockRocketConfig.selected_variant_id }).available;window._RestockRocketConfig.scriptUrlProduct = 'https://cdn.shopify.com/extensions/019d4564-8f2b-76f2-bacb-5853de1a7cf8/restockrocket-1-475/assets/restockrocket-product.js'
window._RestockRocketConfig.scriptUrlCollection = 'https://cdn.shopify.com/extensions/019d4564-8f2b-76f2-bacb-5853de1a7cf8/restockrocket-1-475/assets/restockrocket-collection.js'
window._RestockRocketConfig.scriptHost = window._RestockRocketConfig.scriptUrlProduct.substring(0, window._RestockRocketConfig.scriptUrlProduct.lastIndexOf('/') + 1)
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
< 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
< 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 ||
!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) {
// No matching locale has translations; drop payload to save memory
console.debug('STOQ - No matching locale for translations. Available:', Object.keys(translations || {}));
delete settings.translations;
return settings;
}
console.debug(`STOQ - Applying translations for normalized locale: ${normalizedLocale} (original: ${window._RestockRocketConfig.locale})`);
const translatedFields = translations[normalizedLocale];
if (translatedFields && typeof 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) {
// Setup listener regardless - updateCartSellingPlans has its own guards
// This ensures cleanup happens even when preorders are disabled globally
// Listen for stoq:inventory-data-loaded event dispatched by api.js
window.addEventListener('stoq:inventory-data-loaded', function(event) {
console.debug('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);
});
}
});
}
// First try to get settings from metafields with expiry check
const cachedSettings = window._RestockRocketConfig.cachedSettings;
const validCachedSettings = cachedSettings ? checkSettingsExpiry(cachedSettings) : null;
if (validCachedSettings) {
console.debug('STOQ - using cached settings');
initializeScripts(validCachedSettings);
} else {
console.debug('STOQ - fetching fresh settings');
const headers = {
'X-Shopify-Shop-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 settings as fallback');
initializeScripts(cac
hedSettings);
} else {
console.error('STOQ - failed to load settings:', error);
}
})
.catch(function(e) {
console.error(e)
})
}
function initializeScripts(settings) {
settings = applyTranslations(settings);
window._RestockRocketConfig.settings = settings;
console.debug(`STOQ - settings configured for ${window._RestockRocketConfig.pageType}`);
// 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);
})
if(window._RestockRocketConfig.pageType === 'collection' && (settings.show_button_on_collection || settings.preorder_collection_enabled)) {
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);
} else {
console.debug(`STOQ - no scripts enab