Sierra Leone (SLLLe)
Header Image
Slovakia (EUR€)
Spain (EUR€)
St. Helena (SHP£) Western Sahara (MADد.م.)

Hope Conventional HeadsetZimbabwe (USD$)

Color
de.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.39.png?v=1738415388","variant_ids":[55060180337023]},"available":true,"name":"Hope RX Stem - Silver \/ 80mm","public_title":"Silver \/ 80mm","options":["Silver","80mm"],"price":11500,"weight":0,"compare_at_price":null,"inventory_management":null,"barcode":"","featured_media":{"alt":null,"id":64079611003263,"position":6,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.39.png?v=1738415388"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":55060180369791,"title":"Red \/ 80mm","option1":"Red","option2":"80mm","option3":null,"sku":"","requires_shipping":true,"taxable":true,"featured_image":{"id":73217830683007,"product_id":14928150921599,"position":7,"created_at":"2025-02-01T13:10:11+00:00","updated_at":"2025-02-01T13:10:16+00:00","alt":null,"width":2412,"height":1780,"src":"\/\/projektride.co.uk\/cd n\/shop\/files\/Screenshot2025-02-01at13.10.06.png?v=1738415416","variant_ids":[55060180369791]},"available":true,"name":"Hope RX Stem - Red \/ 80mm","public_title":"Red \/ 80mm","options":["Red","80mm"],"price":11500,"weight":0,"compare_at_price":null,"inventory_management":null,"barcode":"","featured_media":{"alt":null,"id":64079614443903,"position":7,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.10.06.png?v=1738415416"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/projektride.co.uk\/cdn\/shop\/files\/blue_stem_2_blk_1.jpg?v=1738415341","\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.08.png?v=1738415356","\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.15.png?v=1738415364","\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.23.png?v=1738415371","\/\/projektride.co.uk\/cdn\/s
hop\/files\/Screenshot2025-02-01at13.09.31.png?v=1738415380","\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.39.png?v=1738415388","\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.10.06.png?v=1738415416"],"featured_image":"\/\/projektride.co.uk\/cdn\/shop\/files\/blue_stem_2_blk_1.jpg?v=1738415341","options":["Color","Length"],"media":[{"alt":null,"id":64079606186367,"position":1,"preview_image":{"aspect_ratio":1.5,"height":1000,"width":1500,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/blue_stem_2_blk_1.jpg?v=1738415341"},"aspect_ratio":1.5,"height":1000,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/blue_stem_2_blk_1.jpg?v=1738415341","width":1500},{"alt":null,"id":64079607464319,"position":2,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.08.png?v=1738415356"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/sho p\/files\/Screenshot2025-02-01at13.09.08.png?v=1738415356","width":2412},{"alt":null,"id":64079608447359,"position":3,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.15.png?v=1738415364"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.15.png?v=1738415364","width":2412},{"alt":null,"id":64079609266559,"position":4,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.23.png?v=1738415371"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.23.png?v=1738415371","width":2412},{"alt":null,"id":64079610577279,"position":5,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.31.png?v=173841
5380"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.31.png?v=1738415380","width":2412},{"alt":null,"id":64079611003263,"position":6,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.39.png?v=1738415388"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.09.39.png?v=1738415388","width":2412},{"alt":null,"id":64079614443903,"position":7,"preview_image":{"aspect_ratio":1.355,"height":1780,"width":2412,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.10.06.png?v=1738415416"},"aspect_ratio":1.355,"height":1780,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/Screenshot2025-02-01at13.10.06.png?v=1738415416","width":2412}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cdiv class=\"main-indented\" \u003e\n\u003cdiv class=\"row\"\u003e\n\u003cdiv class=\"product-listing center-wrap\"\u003e\n\u003cdiv class=\"new-page-intro-section\"\u003e\n\u003cdiv class=\"product-intro-right\"\u003e\n\u003ch5\u003eIntroducing the RX Stem, a new addition to our line up designed for both gravel and cross-country (XC). Complementing our existing XC stems, the RX offers a more aggressive, race-focused geometry with an 80mm length and a -15 degree rise\u003c\/h5\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003ch5\u003e\/\/ Available in 80mm, -15° rise\u003cbr\u003e\/\/ CNC machined from 2014-T6 aluminium\u003cbr\u003e\/\/ Titanium bolt upgrade kit available\u003cbr\u003e\/\/ Available in black, silver, bronze, red, blue, orange \u0026amp; purple\u003cbr\u003e\/\/ Proudly Designed, Tested and Manufactured in Barnoldswick, UK\u003cbr\u003e\n\u003c\/h5\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e"}; window._RestockRocketConfig.variantsInventoryPolicy = {55060180205951 : "deny",55060180238719 : "deny",55060180271487 : "deny",55060180304255 : "deny",55060180337023 : "deny",55060180369791 : "deny",}; window._RestockRocketConfig.variantsInventoryQuantity = {55060180205951 : parseInt("0"),55060180238719 : parseInt("0"),55060180271487 : parseInt("0"),55060180304255 : parseInt("0"),55060180337023 : parseInt("0"),55060180369791 : parseInt("0"),}; window._RestockRocketConfig.variantsPreorderCount = {55060180205951 : parseInt(""),55060180238719 : parseInt(""),55060180271487 : parseInt(""),55060180304255 : parseInt(""),55060180337023 : parseInt(""),55060180369791 : parseInt(""),}; window._RestockRocketConfig.variantsPreorderCountForMarket = {55060180205951 : null,55060180238719 : null,55060180271487 : null,55060180304255 : null,55060180337023 : null,55060180369791 : null,}; window._RestockRocketConfig.variantsPreorderMaxCount = {55060180205951 : parseInt(""),55060180238719 : parseInt(""),55060180271487 : parseInt(""),55060180304255 : parseInt(""),55060180337023 : pars eInt(""),55060180369791 : parseInt(""),}; window._RestockRocketConfig.variantsPreorderMaxCountForMarket = {55060180205951 : null,55060180238719 : null,55060180271487 : null,55060180304255 : null,55060180337023 : null,55060180369791 : null,}; window._RestockRocketConfig.variantsShippingText = {55060180205951 : "",55060180238719 : "",55060180271487 : "",55060180304255 : "",55060180337023 : "",55060180369791 : "",}; window._RestockRocketConfig.variantsShippingTextForMarket = {55060180205951 : null,55060180238719 : null,55060180271487 : null,55060180304255 : null,55060180337023 : null,55060180369791 : null,}; window._RestockRocketConfig.selected_variant_id = 55060180205951; 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/019ecfe3-4ce2-7592-b7ce-9ed4a1b98version>/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 < = 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 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 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') // Fire stoq_initialized once per page load so the funnel pipeline has a definitive // "our code ran on this page" signal independent of any cus
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; Shopify?.analytics?.publish?.('stoq_initialized', { cart_token: _stoqInitConfig.cartToken || '', page_url: window.location.href, page_type: _stoqInitConfig.pageType || '', shop_domain: _stoqInitConfig.shop || '', market_id: _stoqInitConfig.marketId || '', detected_variant_ids: _stoqDetectedVariantIds, selected_variant_id: _stoqSele ctedVariantId || '', liquid_rendered_at: _stoqInitConfig.liquidRenderedAt || 0, app_version: _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); } 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:', normalizedL ocale); } 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 update
d 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-Sche ma-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('STOQ - failed to load settings:', error); } }) .catch(function(e) { console.error(e) }) } function fetchEmbedConfig(endpoint, apply) { return fet
ch( `${window._RestockRocketConfig.host}/api/v1/embed/${endpoint}.json`, { headers: { 'X-Shopify-Shop-Domain': window._RestockRocketConfig.shop || window.Shopify.shop, 'ngrok-skip-browser-warning': 'skip' } } ) .then(function(response) { if (!response.ok) throw new Error(`Failed to fetch ${endpoint}`); return response.json(); }) .then(function(data) { try { apply(data); } catch (applyError) { // Apply failures are programming bugs (e.g. response shape changed // server-side and the assignment threw). Surface them as console.error // so they're visible in browser logs, then re-throw to fall through // to the same Liquid-cached fallback as a fetch failure. console.error('STOQ - apply failed for ' + endpoint + ':', applyError); throw applyError; } }) .catch(function(error) { console.debug(`STOQ - using cached ${endpoint}:`, error.message); } ); } 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
Reliable and durable. Our conventional headset is designed to fit the standard 1 1/8" fork steerer. The headset uses custom made, replaceable stainless steel bearings to resist corrosion.

Key Features

// Replaceable stainless steel bearings (resist corrosion)
// Split crown race for easy installation and removal
// Comes complete with our Head Doctor top cap
// Multiple seals to keep out the elements
// Conventional headset is designed to fit standard frames and 1 1/8" fork steerers
// Headset uses custom made, replaceable stainless steel bearings to resist corrosion
//The cups, taper ring and crown race (which is split for easy installation and removal) are all machined from 2014 T6 aluminium
// Sealing is achieved through an adjustable taper ring cover and integrated rubber seal
//Available in: black, silver, red, blue, purple and orange
//Weight: 120g,[

Frequently Asked Questions

  • Please get in touch with a member of the team either by phone (01313745324) or email ([email protected]) where on of the team will be more than happy to help.

    ProjektRide Bike Shop Edinburgh

  • 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 -

    ProjektRide Bike Shop Edinburgh

    82 Newington Road, EH91QN, Edinburgh.