Header Image
See More

ine_item_property_enabled":false,"shipping_line_item_property_enabled":true,"custom_line_item_property_text":null,"preorder_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":"
_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,714631872895],"cached_at":"2026-04-09T09:16:46Z"}; 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; }
window._RestockRocketConfig.disabledSellingPlanIds = []; console.debug('[RR] Using selling plans from old format (max updated_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 = {" ng_plan_groups":[],"content":"\u003cmeta charset=\"utf-8\"\u003e\n\u003cp data-mce-fragment=\"1\"\u003eMuc-Off Dry Chain Lube is a durable, deep penetrating Chain Lubricant and oil that’s formulated to hold up in extreme conditions that would destroy ordinary chain lubes. Muc-Off Dry Lube is a highly versatile, dry weather chain oil t\u003c\/p\u003e\n\u003cp data-mce-fragment=\"1\"\u003ehat has state of the art penetrative qualities to ensure that the lube is driven deep into each chain link’s core. And there’s no need to worry because Muc-Off Dry Lube is *biodegradable, so it’s safe for you, your bike and the planet.\u003c\/p\u003e\n\u003cp data-mce-fragment=\"1\"\u003e*Only contents are biodegradable.\u003c\/p\u003e\n\u003cp data-mce-fragment=\"1\"\u003e120ml\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eIdeal for MTB, Road \u0026amp; Cyclocross\u003c\/li\u003e\n\u003cli\u003eWax based formula excels in dry, dusty conditions\u003c\/li\u003e\n\u003cli\u003eAdded protection against contaminants\u003c\ on + fetchEmbedConfig calls below route to the same host as the // rest of the extension's API traffic instead of staying on the baked host. window._RestockRocketConfig.host = (window._RestockRocketConfig.cachedSettings && window._RestockRocketConfig.cachedSettings.api_host) || 'https://app.restockrocket.io' // Deployed extension build number, read from the CDN asset host Shopify generates: // https://cdn.shopify.com/extensions/Poland (PLNzł) uuid>/ < translation data in metafield // Metafield hasn't been backfilled yet - force refresh console.debug('STOQ - multi-language enabled but no translation data in cache, fetching fresh'); return null; } // Translations object exists in metafield - cache is valid // If current locale isn't translated, applyTranslations will gracefully use default locale from base fields if (window._RestockRocketConfig.normalizedLocale && !Object.prototype.hasOwnProperty.call(settings.translations, window._RestockRocketConfig.normalizedLocale)) { console.debug('STOQ - locale not explicitly translated, will use default language from cache'); } // Don't return null - continue using cache even for untranslated locales } const updatedAt = new Date(settings.updated_at); if (isNaN(updatedAt.getTime())) { console.debug('STOQ - Invalid updated_at date format in settings'); return null; } const
<
tomer interaction. // Detected variants: the variants present in this page's Liquid context (product page has them; // collection/index/etc. don't expose variants from Liquid). Used to disambiguate "embed didn't // load" vs "embed loaded but the variant wasn't a preorder/BIS candidate" in order debug. 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; // Per-session page-load counter, incremented here in the INLINE code so it exists // even when the deferred bundle never runs. Paired with stoq_bundle_ready's // page_load_seq, it tells order-debug which page load an add fired on (and whether // the bundle had loaded on that load). var _stoqPageSeq = 0; try { _stoqPageSeq = (parseInt(window.sessiRéunion (EUR€) : _stoqInitConfig.appVersion || '', liquid_cache_age: _stoqInitConfig.liquidCacheAge, // Selected variant's stock posture as our app saw it at render — explains // whether we *should* have treated it as a preorder candidate. inventory_policy: (_stoqInitConfig.variantsInventoryPolicy || {})[_stoqSelectedVariantId] || '', inventory_quantity: (_stoqInitConfig.variantsInventoryQuantity || {})[_stoqSelectedVariantId], }); } catch (e) { console.debug('STOQ - stoq_initialized publish failed:', e); } // STOQ-1595: publish stoq_accelerated_checkout_clicked for every accelerated-checkout // click (Buy Now / dynamic checkout / Shop Pay installments) on ALL surfaces, before our // bundle loads, via one delegated capture-phase listener (catches late-rendered buttons). // Only on shops with preorders configured (shared `preordersConfigured` signal from the // derivation block above) — nothing to bypass otherwise. variant_id is read per-clicked-button // from its fo
(vidEl && vidEl.value) || _sqTrack.selected_variant_id || ''; // The enabled STOQ selling plan the clicked variant belongs to (if any), found once and // reused for in_enabled_plan / enrolled_plan_id / enrolled_plan_provider below. var _sqVidNum = Number(variantId); var _sqPlan = null; // Array.isArray guard (not `|| []`) so a truthy non-array sellingPlans can't throw and // silently drop the whole publish. var _sqPlans = Array.isArray(_sqTrack.sellingPlans) ? _sqTrack.sellingPlans : []; _sqPlans.forEach(function (pl) { if (!_sqPlan && pl && pl.enabled && Array.isArray(pl.variant_ids) && pl.variant_ids.indexOf(_sqVidNum) !== -1) { _sqPlan = pl; } }); Shopify?.analytics?.publish?.('stoq_accelerated_checkout_clicked', { variant_id: variantId, product_id: (_sqTrack.product && _sqTrack.product.id) || '', channel: channel, market_id: _sqTrac
er_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 && _sqTrack.cachedPreorderVariantIds.preorder_variant_ids); })(), // Narrow, authoritative preorder signal: enrolled in an ENABLED STOQ selling plan // (is_preorder_variant above is the broad OOS+continue heuristic — non-STOQ too). in_enabled_plan: !!_sqPlan, // In-stock preorder signal: enrolled but currently IN STOCK (in the inStockVariantIds // set, not the OOS preorderVariantIds set). Same live-OR-cached pattern as // is_preorder_variant. is_preorder_variant OR is_instock_variant = "should sell via // the plan" regardless of stock, so an in-stock preorder bypass is detectable too. is_ _at_click: !!(document.documentElement && document.documentElement.classList.contains('stoq-buy-now-pending')), }, }); } catch (err) { /* never break checkout */ } }, true); } } catch (e) { /* fail open */ } 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; Romania (RONLei)
// 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); }); } }); } // ---- Live settings via the Storefront API (additive, does not gate init) ---- // The inli
<
"settings") { value } } }'; fetch( `https://${cfg.shop}/api/2025-07/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': cfg.storefrontAccessToken, }, body: JSON.stringify({ query: query, variables: { namespace: cfg.metafieldNamespace } }), } ) .then(function(response) { if (!response.ok) { throw new Error('Storefront API HTTP ' + response.status); } return response.json(); }) .then(function(body) { if (body && body.errors && body.errors.length) { throw new Error('Storefront API errors: ' + body.errors.map(function(e) { return e && e.message; }).join(', ')); } const value = body && body.data && body.data.shop && body.data.shop.metafield && body.data.shop.metafield.value; if (!value) { throw new Error('Storefront API returned no settings metafield value'); } cfg.sto
p' }; 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(cachedSettings); } else { console.error('SEssentialsRwanda (RWFFRw) Accessories
MaintenanceSenegal (XOFFr) Serbia (RSDРСД) Sell Your Bike
Seychelles (GBP£)
Contact Us
FinanceSierra Leone (SLLLe)
Slovakia (EUR€)

Go to the market. Go to the beach. Go get coffee. The Townie® Go! 5i is an easy-to-use, fun-to-ride, pedal assist e-bike with surprising power that’ll make you want to go on forever. With the Bosch Active Line Plus System and Electra's Flat Foot Technology®, climb hills and shorten distances with ease. It’s impossible not to smile while riding a Townie Go!

Slovenia (EUR€)

*Please note – spec applies to all sizes unless listed separately

Log in
Somalia (GBP£)
Frameset
Create account South Africa (GBP£)
South Sudan (GBP£) Search Spain (EUR€) Country St. Helena (SHP£) GBP£ Sudan (GBP£) Åland Islands (EUR€)
Frame 6061-T6 aluminium with patented Flat Foot Technology®
Fork Hi-ten steel unicrown, straight/tapered leg
Svalbard & Jan Mayen (GBP£)
Albania (ALLL)
Sweden (SEKkr)
Algeria (DZDد.ج)
Andorra (EUR€) Armenia (AMDդր.) Belarus (GBP£) Bosnia & Herzegovina (BAMКМ)
Angola (GBP£)
Ascension Island (SHP£)
Austria (EUR€)
Belgium (EUR€)
Benin (XOFFr)
Botswana (BWPP)
British Indian Ocean Territory (USD$)
Bulgaria (EUR€)
Burkina Faso (XOFFr) Burundi (BIFFr) Cameroon (XAFCFA) Cape Verde (CVE$) Shop All Central African Republic (XAFCFA) Chad (XAFCFA) Comoros (KMFFr)
Computer Bosch Purion
Motor Bosch Active Line Plus, 250 watt, 50 Nm, 25 km/h (15.5 mph), 32 km/h for New Zealand
Congo - Brazzaville (XAFCFA)
Drivetrain
Congo - Kinshasa (CDFFr)
Côte d’Ivoire (XOFFr) Cyprus (EUR€) Djibouti (DJFFdj) Equatorial Guinea (XAFCFA) Eswatini (GBP£)
Croatia (EUR€)
Czechia (CZKKč)
Denmark (DKKkr.)
Egypt (EGPج.م)
Eritrea (GBP£)
Estonia (EUR€)
Ethiopia (ETBBr)
Faroe Islands (DKKkr.)
Open image lightbox
Finland (EUR€)
Components
France (EUR€)
Open image lightbox
French Southern Territories (EUR€) Gabon (XOFFr) Georgia (GBP£) Your total cost is made up of different daily rates — not one flat rate across all days. Collection for this hire is available from ProjektRide Edinburgh .izyloader.global { display:none !important; } span>Extra Small (Red)
*Saddle Size:Open image lightbox   26" wheel Gambia (GMDD)
Ergonomic w/shock-absorbing elastomers
Size:Open image lightbox  

The next few days are charged at a lower rate.
Later days are even cheaper.
. Click on the link to view location and opening hours.
document.addEventListener("DOMContentLoaded", function(event) { if(typeof izyrent_metafields !== "undefined"){ const target = document.querySelector("#izyrent"); const loaderDiv = document.createElement("div"); loaderDiv.className = "izyloader"; loaderDiv.innerHTML = ">"; target.parentNode.insertBefore(loaderDiv, target); } });
Size

Norway (GBP£)