Brands
OtherSee More
  • button type="submit" class="btn">Sort\u003e\u003cspan\u003eRST Volant 63mm\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"card grid-item\"\u003e\n\u003cdiv class=\"card-header pl-0 pr-0\" id=\"specheadingrims\"\u003e\n\u003cdiv class=\"btn btn-link pl-0 pr-0 text-center text-md-left collapsed text-uppercase\" aria-controls=\"specrims\" aria-expanded=\"true\" data-target=\"#specrims\" data-toggle=\"collapse\"\u003e\u003cstrong\u003eGrip Tape :\u003c\/strong\u003e\u003c\/div\u003e\n\u003cspan\u003e \u003c\/span\u003e\u003cspan\u003eRidgeback\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"card grid-item\"\u003e\n\u003cdiv class=\"card-header pl-0 pr-0\" id=\"specheadingrims\"\u003e\n\u003cdiv class=\"btn btn-link pl-0 pr-0 text-center text-md-left collapsed text-uppercase\" aria-controls=\"specrims\" aria-expanded=\"true\" data-target=\"#specrims\" data-toggle=\"collapse\"\u003e\u003cstrong\u003eHeadset :\u003c\/strong\u003e\u003c\/div\u003e\n\u003cspan\u003e \u003c\/span\u003e\u003cspan\u00
    > portdrive MD250S 250W 90Nm\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"card grid-item\"\u003e\n\u003cdiv class=\"card-header pl-0 pr-0\" id=\"specheadingrims\"\u003e\n\u003cdiv class=\"btn btn-link pl-0 pr-0 text-center text-md-left collapsed text-uppercase\" aria-controls=\"specrims\" aria-expanded=\"true\" data-target=\"#specrims\" data-toggle=\"collapse\"\u003e\u003cstrong\u003eMudguard :\u003c\/strong\u003e\u003c\/div\u003e\n\u003cspan\u003e \u003c\/span\u003e\u003cspan\u003eFitted\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"card grid-item\"\u003e\n\u003cdiv class=\"card-header pl-0 pr-0\" id=\"specheadingrims\"\u003e\n\u003cdiv class=\"btn btn-link pl-0 pr-0 text-center text-md-left collapsed text-uppercase\" aria-controls=\"specrims\" aria-expanded=\"true\" data-target=\"#specrims\" data-toggle=\"collapse\"\u003e\u003cstrong\u003ePedals :\u003c\/strong\u003e\u003c\/div\u003e\n\u003cspan\u003e \u003c\/span\u003e\u003cspan\u003eResin Metro\u0
    Header Image

    ets and an internal compression strap aid clean organisation for packing and unpacking. PVC free and sustainably made in Germany.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eFabric: PS21R\u003c\/li\u003e\n\u003cli\u003eHeight: 56cm\u003c\/li\u003e\n\u003cli\u003eWidth: 26cm\u003c\/li\u003e\n\u003cli\u003eDepth: 25cm\u003c\/li\u003e\n\u003cli\u003eVolume: 25L\u003c\/li\u003e\n\u003cli\u003eWeight: 1300g\u003c\/li\u003e\n\u003c\/ul\u003e","published_at":"2023-03-18T14:34:06+00:00","created_at":"2023-03-18T14:34:06+00:00","vendor":"ortlieb","type":"bags","tags":["Accessories","backpack","Bags and Transportation","Bike Packing","spo-cs-disabled","spo-default","spo-disabled","spo-notify-me-disabled"],"price":19500,"price_min":19500,"price_max":19500,"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":43936332349666,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"OR7★★ 100","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Ortlieb Atrack BP 25L","public_title":null,"options":["Default Title"],"price":19500,"weight":0,"compare_at_price":null,"inventory_management":"shopify","barcode":"","requires_selling_plan":false,"selling_plan_allocations":[]}],"images":["\/\/projektride.co.uk\/cdn\/shop\/products\/6882.jpg?v=1679150048","\/\/projektride.co.uk\/cdn\/shop\/products\/6884.jpg?v=1679150048","\/\/projektride.co.uk\/cdn\/shop\/products\/6879.jpg?v=1679150048","\/\/projektride.co.uk\/cdn\/shop\/products\/6878.jpg?v=1679150049","\/\/projektride.co.uk\/cdn\/shop\/products\/6880.jpg?v=1679150048","\/\/projektride.co.uk\/cdn\/shop\/products\/6881.jpg?v=1679150049","\/\/projektride.co.uk\/cdn\/shop\/products\/6883.jpg?v=1679150049"],"featured_image":"\/\/projektride.co.uk\/cdn\/shop\/products\/6882.jpg?v=1679150048","options":["Title"],"media":[{"alt":null,"id":31694944764130,"position":1,"preview_image":{"aspect_ratio":1.0,"height":768,"width":7★★★
    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 restockRocketScriptElem
    < ock-rocket-button-container:hover,.restock-rocket-button-float:hover,.restock-rocket-button:hover{opacity:.8}.restock-rocket-button{min-height:50px;margin-top:10px;margin-bottom:10px}.restock-rocket-button-collection{position:relative;font-size:13px;line-height:1;padding:7px;height:auto;z-index:3}.restock-rocket-wrapper{background-color:rgba(0,0,0,.5);z-index:123123123;width:100%;height:100%;overflow:auto;position:fixed;right:0;top:0;transition-property:all;transition-duration:.3s;display:flex;flex-direction:column;justify-content:center;}.restock-rocket-wrapper-inline{width:100%;height:100%;margin-top:20px}.restock-rocket-preorder-description{padding:10px 15px;margin-top:20px;display:flex;flex-direction:column;gap:10px;}.preorder-description-details{margin-bottom:0;display:flex;flex-direction:column;gap:10px;}.preorder-detail-item{display:flex;flex-direction:row;justify-content:start;gap:8px;align-items:center;}.restock-rocket-payment-widget{border:1px solid #ebebeb;margin-bottom:20px;}.restock-rocket-paymenIf you are looking for someone helpful and knowledgeable this is the place to go.
    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;}.restock-rocket-acknowledge-checkbox-label{flex:1;cursor:pointer;}.restock-rocket-preorder-countdown-timer{display:flex;flex-direction:column;align-items:center;padding:16px;margin:8px 0;font-family:inherit;}.restock-rocket-preorder-countdown-timer .countdown-header{font-size:16px;margin-bottom:6px;text-align:center}.restock-rocket-preorder-countdown-timer .countdown-units{display:flex;flex-wrap:wrap;gap:12px;justify-content:center}.restock-rocket-preorder-countdown-timer .countdown-unit{display:flex;flex-direction:column;align-items:center;gap:6px}.restock-rocket-preorder-countdown-timer .countdown-box{min-width:40px;padding:10px 6px;text-align:center;font-size:20px;line-height:1}.restock-rocket-preorder-countdown-timer .countdown-label{font-size:14px;font-weight:500;text-align:center;text-transfoExcellent service got a great bike in great condition even helped out with a few extras and provided the original receipt for lifetime guarantee on the frame.
    in-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;animation:.5s forwards slide}.restock-rocket-toast-left{left:0;transform:translateX(-100%);-webkit-transform:translateX(-100%);border-radius:0 10px 10px 0}.restock-rocket-toast-left.slide-out{-webkit-animation:.5s forwards slide-out-left;animation:.5s forwards slide-out-left}.restock-rocket-toast-right{right:0;transform:translateX(100%);-webkit-transform:translateX(100%);border-radius:10px 0 0 10px}.restock-rocket-toast-right.slide-out{-webkit-animation:.5s forwards slide-out-right;animation:.5s forwards slide-out-right}@keyframes slide{100%{transform:translateX(0)}}@-webkit-keyframes slide{100%{-webkit-transform:translateX(0)}}@keyframes slide-out-left{0%{transform:translateX(0)}100%{transform:translateX(-100%)}}@-webkit-keyframes slide-out-left{0%{-webkit-transform:translateX(0)}100%{-webkit-transform:trIain Orr
    ★★★★★
    I dropped my Specialized Vita for new brake pads and a service, the bike was ready for collection the same day and the price was reasonable! Bicycle feels brand new again and works amazing! Many thanks!!
    Heather Paterson ★★★★★

    Customer CareStaff are very kind and the price is relatively reasonable, also student can have 10% discount which it great :)

    The team's goal is to provide excellent service to ensure every customer has a great experience.William Gui

    Excellent friendly and efficient service. Great product knowledge and good value for money! Highly recommend

    Getting the Right BikeBen Ross

    We don’t do 'bikes for the masses', our key objective is to get you the correct bike for your unique riding profile.

    Quality Control

    Every bike that passes through our business receives the upmost care and attention, ensuring safety and reliability to every client.

    HAVE A QUESTION?
    We love chatting about your next bike adventure. Get in touch and we can go through the perfect bike along with any accessories needed to get you to your final destination. If you are local to our branch in Edinburgh, please pop in for a coffee and feel free to test ride the bikes in stock.
    GET IN TOUCH

    LOCATION & HOURS

    Edinburgh Bike Shop



    <
    a href="/pages/cycle-to-work-scheme" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/cyclescheme-logo_copy_360x.png?v=1635889213); width: 120px; padding-top: 57.2%;">

    <
    a href="/pages/cycle-to-work-scheme" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/bike_to_work-removebg-preview_360x.png?v=1635889127); width: 120px; padding-top: 84.3%;">

    recommended these guys by a passing cyclist when I had an embarrassing wardrobe+ bike mishap on my way home from work. Once that was sorted, they also spotted that my rear tyre was ripped and likely to catastrophically fail on me if I wasn't careful. They were speedy, kind and generous with their time and advice. Wouldn't hesitate to recommend them

    Lucy Gaunt
    < div class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/actlogo_360x.png?v=1635889127); width: 120px; padding-top: 65.5%;">

    ★★★★★Logo image

    We rented two gravel bikes to explore Scotland for nearly three weeks, and I couldn’t have been happier with the experience. The bikes came fully equipped with everything we could possibly need—repair kit, pannier bags, lock, spare tubes, and more. The team was incredibly welcoming and friendly, making the whole process seamless. There’s honestly nothing-

    < a href="https://projektride.co.uk/collections/bikes?filter.p.vendor=Brother,Brother+Cycles,Brothers+Cycles,brother+cycles" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/cropped-brother-cycles-leaf-logo_360x.png?v=1688813290); width: 120px; padding-top: 100.0%;">

    negative I could say; everything exceeded expectations. I can wholeheartedly recommend ProjectRide for anyone looking to rent a bike, and their many 5-star reviews are absolutely well deserved.ReplyLogo image

    Matias Hugentobler
    < a href="https://projektride.co.uk/search?q=muc-off&type=product" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2021-12-30_at_20.49.50_360x.png?v=1640897415); width: 150px; padding-top: 47.7%;">

    ★★★★★Logo image

    Absolutely fantastic bike shop. Always willing to help you out when you’re having a problem. Bought many bike components from them over the years and every time they go out of their way to fit them!

    Would recommend wholeheartedly for any biking needs!

    Max McMullon
    < div class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/genesis_logo_360x.png?v=1710022398); width: 120px; padding-top: 14.2%;">

    <
    a href="https://shopify.projektride.co.uk/collections/parts-components?filter.p.vendor=OneUp,oneup" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2021-12-30_at_20.54.49_360x.png?v=1640897703); width: 120px; padding-top: 50.5%;">

    Wim Lintermans<
    a href="https://shopify.projektride.co.uk/collections/bikes?filter.p.vendor=Surly,surly,Surly+Bikes,surly+bikes" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2022-02-06_at_16.13.48_360x.png?v=1644164045); width: 160px; padding-top: 55.8%;">

    Amazing service and quick turnaround! Dropped my bike off at 6:30pm (closing time) one day and it had been fully serviced and sorted out by the next morning! Top service and reasonable prices. Will come back here for all bike servicing needs in the future no doubt! Guys are incredibly knowledgeable also.<

    a href="https://www.cytech.training/" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2022-02-06_at_16.18.00_360x.png?v=1644164294); width: 120px; padding-top: 50.2%;">Christian Graham
    Logo image

    ★★★★★

    Logo image

    <★★★★★a href="https://shopify.projektride.co.uk/collections/all-products?filter.p.vendor=Hope,hope,HOPE" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2022-02-06_at_16.21.05_360x.png?v=1644164480); width: 160px; padding-top: 23.0%;">

    Antonio IglesiasLogo image
    < a href="https://www.straightcutdesign.com/" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2022-03-16_at_14.44.40_360x.png?v=1647443209); width: 170px; padding-top: 26.3%;">

    These guys are great! Super helpful, affordable, and friendly. They don't talk down to you as a woman which I always appreciate!Logo image

    Tiki Muir
    < a href="https://www.ortlieb.com/en_us/" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2022-07-06_at_22.44.45_360x.png?v=1657143901); width: 170px; padding-top: 32.4%;">

    ★★★★★Logo image

    Bikes are hard to come by at the moment. Andy and Dougie at ProjektRide were amazing in sourcing a frame and a build kit, then marrying them up to create a fantastic bike. They were really attentive to sizing and fitting, based on my riding style.

    Matt Wilkes
    < a href="https://projektride.co.uk/collections/bikes?filter.p.vendor=Kona,KONA,Kona+Bikes,kona" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/KonaLogoOrbitVertBlack_360x.png?v=1672678563); width: 120px; padding-top: 112.5%;">
    Logo image

    ★★★★★

    Friendly welcome, quick to help, reliable comms. Glad to have a local bike shop in Edinburgh who know what they're doing!

    Logo image

    ★★★★★

    I always get really friendly and helpful advice at ProjektRide and excellent results from any servicing they do. Highly recommended.

    Logo image

    ★★★★★

    Logo image

    <★★★★★a href="https://projektride.co.uk/search?type=product&q=benno" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2023-08-30_at_13.34.25_360x.png?v=1693401784); width: 120px; padding-top: 102.4%;">


    Moreover, he ensured the bike was in its best condition before handing over. Thanks a million!Logo image

    Laura Grieve
    < a href="https://projektride.co.uk/search?q=ESI&type=product" class="logo-list__slide-image" style="background-image: url(//projektride.co.uk/cdn/shop/files/Screenshot_2023-10-05_at_10.46.34_360x.png?v=1696499201); width: 120px; padding-top: 67.7%;">

    ★★★★★

    Top quality bike, top quality service - these are decent guys doing a great job. Thoroughly impressed with their knowledge and service. Recommend to anyone buying a bike - talk to them and they give you good advice.

    Mike Smith
    .site-footer { --bg: #1f2324; --text: #ffffff; --text-alpha-15: rgba(255, 255, 255, 0.15); --text-alpha-60: rgba(255, 255, 255, 0.6); --text-alpha-85: rgba(255, 255, 255, 0.85); } .footer-content__logo__image { width: 170px; }

    <


    Tel
    Email
    Logo image [email protected]
    Logo image © 2025,
    ProjektRide
    Logo image
    led":false,"push_allowed":false,"storefront_form_push_label":"Push","storefront_form_push_description":"Click 'Allow' to be notified via push notification","storefront_form_push_error":"Permission rejected! Please review notification settings and try again","storefront_font_family":"OpenSans","insert_button_after_selector_collection_type":"afterend","show_channel_selector":false,"storefront_form_empty_error":"Please fill in one or more of the options above","storefront_form_push_input":"Send notification to your browser","insert_button_after_selector_page":null,"show_button_on_page":false,"insert_button_after_selector_search":null,"show_button_on_search":false,"app_proxy_path_prefix":"/apps/restockrocket-production","collection_link_selector":"","index_link_selector":"","page_link_selector":"","search_link_selector":"","collection_check_link_visibility":true,"collection_buttons_container":null,"index_buttons_container":null,"page_buttons_container":null,"search_buttons_container":null,"extension_enable_url_vaLogo imageriant_detection":true,"extension_enable_value_variant_detection":true,"extension_value_variant_selector":"[name='id']","resubscribe_text":"This product is out of stock. Get notified when it's restocked again by entering your details below!","preorder_enabled":true,"preorder_buy_button_selector":null,"preorder_add_to_cart_button_selector":"","preorder_badge_selector":"","preorder_button_out_of_stock_text":"Out of stock","preorder_button_add_to_cart_text":"Add to cart","preorder_form_selector":"form[action*=\"/cart/add\"]","preorder_collection_enabled":false,"preorder_collection_form_selector":"form[action*=\"/cart/add\"]","preorder_collection_add_to_cart_button_selector":"form[action*=\"/cart/add\"] button","preorder_index_enabled":false,"preorder_index_form_selector":"form[action*=\"/cart/add\"]","preorder_index_add_to_cart_button_selector":"form[action*=\"/cart/add\"] button","preorder_page_enabled":false,"preorder_page_form_selector":"form[action*=\"/cart/add\"]","preorder_page_add_to_cart_button_selector":"form[action*=\"/cart/add\"] button","preorder_search_enabled":false,"preorder_search_form_selector":"form[action*=\"/cart/add\"]","preorder_search_add_to_cart_button_selector":"form[action*=\"/cart/add\"] button","preorder_collection_badge_selector":null,"preorder_index_badge_selector":null,"preorder_page_badge_selector":null,"preorder_search_badge_selector":null,"preorder_badge_selector_type":"afterend","preorder_collection_badge_selector_type":"afterend","preorder_button_child_selector":"span","preorder_button_disclaimer_insert_selector":"","preorder_button_disclaimer_insert_selector_type":"afterend","preorder_payment_insert_selector":"","preorder_payment_insert_selector_type":"afterend","preorder_price_container_selector":"","preorder_price_container_selector_insert_type":"afterend","preorder_terms_insert_selector":"","preorder_terms_insert_selector_type":"afterend","preorder_original_price_selector":"","preorder_price_format":"{{amount}} {{currency}}","show_badge_if_any_variant_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,"market_setup_type":"single_market","shopify_app_id":5940125,"cache":true,"cached_at":"2025-11-11T14:27:02.333Z","multi_language_enabled":false,"translation_locale":"en"};window._RestockRocketConfig.cachedPreorderVariantIds = {"preorder_variant_ids":[42167799447778,43590980075746,43916521013474,43934694998242,43934695031010,43934695620834,43935975440610,43935975473378,43935989399778,43935989432546,43935990284514,43935994118370,43935995625698,43935995855074,43936000835810,43936003195106,43936003227874,43936008012002,43936008044770,43936022757602,43936022790370,43936022823138,43936022855906,43936056115426,43936061030626,43936064930018,43936070631650,43936078037218,43936078069986,43936088195298,43936093470946,43936101138658,43936107266274,43936124076258,43936124109026,43936124141794,43936124174562,43936129941730,43936129974498,43936130007266,43936142393570,4
    3936142426338,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,43981 392904418,43981695844578,43981695877346,43981695910114,43981695942882,43981986070754,43981987905762,43981987938530,44052906967266,44052907327714,44052907360482,44052907393250,44052907426018,44052907458786,44052907491554,44052909097186,44052909129954,44140302827746,44140302893282,44140317016290,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,55569712447871,55569712480639,55569933074815,55570550194559,55570550227327,55604008976767,55638316908927,55638316941695,55638316974463,56220814999935,56220815032703,56270279606655,56270279639423,562702796
    nfig":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.scriptUrlProduct = 'https://cdn.shopify.com/extensions/019b1405-52e0-7e89-a6c1-1ac7fea6dd8f/restock-rocket-shopify-410/assets/restockrocket-product.js' window._RestockRocketConfig.scriptUrlCollection = 'https://cdn.shopify.com/extensions/019b1405-52e0-7e89-a6c1-1ac7fea6dd8f/restock-rocket-shopify-410/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 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(scriptULogo imagerl) { 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; } } // First try to get settings from metafields with expiry check const cachedSettings = window._RestockRocketConfig.ca chedSettings; 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 respon
    Logo image
    Logo image