Postage is free on orders over £50. Orders under £50, our postage charge is £3.99.
Disc Trucker enjoys the same reputation as Long Haul Trucker: It’s one of the best-riding and most value-packed drop bar touring bikes out there. Sometimes, however, a combination of load, climate, and terrain demands a bit more braking performance than a standard rim-brake LHT can provide.We also have a physical store, if you are local please pop in -
ProjektRide Bike Shop Edinburgh
That’s where the newly redesigned Disc Trucker comes in. Packing reliable stopping power and a horde of useful mounting points, shortened chainstays up the Disc Trucker’s stiffness and maneuverability around corners. Add in improved fit and handling under load, plus captured thru-axles for tool-free removal and installation, and the Disc Trucker is ready to help you meet — or dodge — your daily obligations. 82 Newington Road, EH91QN, Edinburgh.
Dynamo routing on the fork, plus three-pack mounts on the blade and every braze-on you’ll ever need for racks,mudguards, water bottle cages, and more
12mm thru-axles for a stiffer feel and increased stability when fully loaded
Shortened seat tube and slightly sloped top tube for improved stand-over clearance, plus increased stack height for a more upright and comfortable riding position on those long hauls
Flat-mount disc brake mounts
Frame sizes 42–56cm are available for 26” diameter wheels, while frame sizes 56–64cm are available for 700c diameter wheels
Clearance for 26” x 2.1” tyres with or without mudguards, or 700c x 47mm with or without mudguards
You May Also Like
Thanks for considering ProjektRide for your next purchase. All bikes are fully assembled and test rode before leaving our bike shop in Edinburgh. Please allow 5-7 days for bicycle delivery although we aim to post bikes out the same day.
Buy, sell and ride in confidence on ProjektRide’s premium bikes
SURLY BIKES
BUILT TO LAST
Contact Us
Blog
Track Service Progress
Building Your Bike From the Box
QUESTIONS AND ANSWERS
Insure Your Bike
Privacy Policy
Cookie Policy
Due to the increased demand, the best way to get your hand on a Surly bike is to call us to check the availability on the model and build kit you are looking for. Some models can be pre-ordered and reserved for when
they come into stock.Terms of Service
When you buy a Surly from ProjektRide, we give you free running in service.Servicing
Sulry bikes are super well built although if you were to have any issues, Surly offer a 3 year warranty on all frames which can be processed from ourselves.
Book a Service
Workshop Prices
We love custom building these Surlys. Get in touch with the team to find out more about custom building your dream Surly. Please check out some of our custom builds:
https://projektride.co.uk/pages/custom-buildsCycle to Work
Please get in touch with a member of the team either by phone (EH9 1QN01313745324[email protected]) or email (
[email protected]
) where on of the team will be more than happy to help.
ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" rowspan=\"1\" scope=\"row\"\u003eKickstand\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003ePletscher Comp Flex 18\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" rowspan=\"1\" scope=\"row\"\u003eCargo rack\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003e\u003ca data-v-05762449=\"\" href=\"https:\/\/www.trekbikes.com\/gb\/en_GB\/p\/W5284844\"\u003eMIK-compatible alloy rear rack, maximum load 25 kg\u003c\/a\u003e\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" rowspan=\"2\" scope=\"row\"\u003e*Mudguard\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003e\n\u003cspan data-v-05762449=\"\"\u003eSize:\u003c\/span\u003e\u003cspan\u003e \u003c\/span\u003eM, L, XL\u003cbr data-v-05762449=\"\"\u003e\u003ca data-v-05762449=\"\" href=\"https:\/\/www.trekbikes.com\/gb\/en_GB\/p\/W598121\"\u003eSKS plastic, rear\u003c\/a\u003e\n\u003c\/td\u003e\n\
u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003ctd data-v-05762449=\"\"\u003e\n\u003cspan data-v-05762449=\"\"\u003eSize:\u003c\/span\u003e\u003cspan\u003e \u003c\/span\u003eM, L, XL\u003cbr data-v-05762449=\"\"\u003e\u003ca data-v-05762449=\"\" href=\"https:\/\/www.trekbikes.com\/gb\/en_GB\/p\/W1051529\"\u003eSKS plastic, front\u003c\/a\u003e\n\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv data-v-5bd42f3c=\"\" data-v-05762449=\"\" id=\"pdl-collapse-item-g5hple\" name=\"218\" class=\"pdl-collapse-item is-active\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" role=\"tab\" aria-controls=\"pdl-collapse-content-g5hple\" aria-describedby=\"pdl-collapse-content-g5hple\" class=\"\" aria-expanded=\"true\" qaid=\"\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" class=\"flex items-center flex-grow\"\u003eWeight\u003c\/div\u003e\n\u003cbutton data-v-5bd42f3c=\"\" id=\"pdl-collapse-head-g5hple\" type=\"button\" class=\"pdl-collapse-item__header is-active flex-row-reverse items-center\" tabindex=\"0\"\u003e\u003csvg data-v-1e7396ba=\"\" data-v-5bd42f3c=\"\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentcolor\" aria-hidden=\"true\" role=\"presentation\" class=\"pdl-collapse-item__icon pdl-icon pdl-icon--size-24 is-active\" qaid=\"\"\u003e\u003cpath d=\"M0 0h24v24H0z\" fill=\"none\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv data-v-5bd42f3c=\"\" id=\"pdl-collapse-content-g5hple\" role=\"tabpanel\" aria-labelledby=\"pdl-collapse-head-g5hple\" class=\"pdl-collapse-item__wrap\" data-old-padding-top=\"\" data-old-padding-bottom=\"\" data-old-overflow=\"\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" class=\"pdl-collapse-item__content\"\u003e\n\u003ctable data-v-05762449=\"\" aria-label=\"Specifications\" class=\"sprocket__table spec\"\u003e\n\u003ctbod
y data-v-05762449=\"\"\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" scope=\"row\"\u003eWeight\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003eM - 21.90 kg \/ 48.29 lbs (excluding battery)\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" scope=\"row\"\u003eWeight limit\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003eThis bike has a maximum total weight limit (combined weight of bicycle, rider and cargo) of 136 kg (300 lb).\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"mb-1\"\u003e\n\u003cp\u003eWe reserve the right to make changes to the product information contained on this site at any time without notice, including with respect to equipment, specifications, models, colours, materials and pricing. Due to supply chain issues, compatible parts may be substituted at any time without notice. The prices shown are the manufacturer's suggested retail prices.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"mb-1\"\u003e\n\u003cp\u003eBike and frame weights are based on pre-production painted frames at time of publication. Weights may vary in final production.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003cp\u003e \u003c\/p\u003e\n\u003c!----\u003e","published_at":"2024-10-10T15:19:26+01:00","created_at":"2024-08-17T14:35:54+01:00","vendor":"Trek","type":"bike","tags":["Allant","electric"],"price":351500,"price_min":351500,"price_max":351500,"available":true,"price_varies":false,"compare_at_price":370000,"compare_at_price_min":370000,"compare_at_price_max":370000,"compare_at_price_varies":false,"variants":[{"id":45823229001954,"title":"Medium \/ Black","option1":"Medium","option2":"Black","option3":null,"sku":"5294611","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Trek Allant+ 7 Gen 2 - Medium \/ Black","public_title":"Medium \/ Black","opt
ions":["Medium","Black"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":45823229034722,"title":"Medium \/ Blue","option1":"Medium","option2":"Blue","option3":null,"sku":"5294614","requires_shipping":true,"taxable":true,"featured_image":null,"available":false,"name":"Trek Allant+ 7 Gen 2 - Medium \/ Blue","public_title":"Medium \/ Blue","options":["Medium","Blue"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":45823229067490,"title":"Large \/ Black","option1":"Large","option2":"Black","option3":null,"sku":"5294612","requires_shipping":true,"taxable":true,"featured_image":null,"available":false,"name":"Trek Allant+ 7 Gen 2 - Large \/ Black","public_title":"Large \/ Black","options":["Large","Black"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":45823229100258,"title":"Large \/ Blue","option1":"Large","option2":"Blue","option3":null,"sku":"5294615","requires_shipping":true,"taxable":true,"featured_image":null,"available":false,"name":"Trek Allant+ 7 Gen 2 - Large \/ Blue","public_title":"Large \/ Blue","options":["Large","Blue"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":45823229133026,"title":"Extra Large \/ Black","option1":"Extra Large","option2":"Black","option3":null,"sku":"5294613","requires_shipping":true,"taxable":true,"featured_image":null,"available":false,"name":"Trek Allant+ 7 Gen 2 - Extra Large \/ Black","public_title":"Extra
Large \/ Black","options":["Extra Large","Black"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}},{"id":45823229165794,"title":"Extra Large \/ Blue","option1":"Extra Large","option2":"Blue","option3":null,"sku":"5294616","requires_shipping":true,"taxable":true,"featured_image":null,"available":true,"name":"Trek Allant+ 7 Gen 2 - Extra Large \/ Blue","public_title":"Extra Large \/ Blue","options":["Extra Large","Blue"],"price":351500,"weight":0,"compare_at_price":370000,"inventory_management":"shopify","barcode":null,"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-A-Primary.webp?v=1723901651","\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-B-Primary.webp?v=1723901653"],"featured_image":"\/\/pr
ojektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-A-Primary.webp?v=1723901651","options":["Size","Color"],"media":[{"alt":null,"id":34471601242338,"position":1,"preview_image":{"aspect_ratio":1.333,"height":1440,"width":1920,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-A-Primary.webp?v=1723901651"},"aspect_ratio":1.333,"height":1440,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-A-Primary.webp?v=1723901651","width":1920},{"alt":null,"id":34471601307874,"position":2,"preview_image":{"aspect_ratio":1.333,"height":1440,"width":1920,"src":"\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-B-Primary.webp?v=1723901653"},"aspect_ratio":1.333,"height":1440,"media_type":"image","src":"\/\/projektride.co.uk\/cdn\/shop\/files\/AllantPlus7Men-24-41029-B-Primary.webp?v=1723901653","width":1920}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cspan\u003e\u00
3cmeta charset=\"utf-8\"\u003eThe Allant+ 7 is an award-winning e-bike built for riders and commuters who want a stylish, durable e-bike with the added road-smoothing benefits of a suspension fork. The powerful and connected Bosch smart system, quality parts and a wealth of thoughtful design details make this electric bike a great solution for getting around town every day\u003c\/span\u003e\u003c\/p\u003e\n\u003cdiv role=\"tablist\" aria-multiselectable=\"true\" class=\"pdl-collapse pdp-spec-collapse\" qaid=\"pdp-spec-collapse\"\u003e\n\u003cp\u003e*Please note – spec applies to all sizes unless listed separately\u003c\/p\u003e\n\u003cdiv data-v-5bd42f3c=\"\" data-v-05762449=\"\" id=\"pdl-collapse-item-vhfkao\" name=\"200\" class=\"pdl-collapse-item is-active\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" role=\"tab\" aria-controls=\"pdl-collapse-content-vhfkao\" aria-describedby=\"pdl-collapse-content-vhfkao\" class=\"\" aria-expanded=\"true\" qaid=\"\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" class=\"flex items-center flex-grow\"\u003eFrameset\u003c\/div\u003e\n\u003cbutton data-v-5bd42f3c=\"\" id=\"pdl-collapse-head-vhfkao\" type=\"button\" class=\"pdl-collapse-item__header is-active flex-row-reverse items-center\" tabindex=\"0\"\u003e\u003csvg data-v-1e7396ba=\"\" data-v-5bd42f3c=\"\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentcolor\" aria-hidden=\"true\" role=\"presentation\" class=\"pdl-collapse-item__icon pdl-icon pdl-icon--size-24 is-active\" qaid=\"\"\u003e\u003cpath d=\"M0 0h24v24H0z\" fill=\"none\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv data-v-5bd42f3c=\"\" id=\"pdl-collapse-content-vhfkao\" role=\"tabpanel\" aria-labelledby=\"pdl-collapse-head-vhfkao\" class=\"pdl-collapse-item__wrap\" data-old-padding-top=\"\" data-old-padding-bottom=\"\" data-old-overflow=\"\"\u003e\n\u003cdiv data-v-5bd42f3c=\"\" class=\"p
dl-collapse-item__content\"\u003e\n\u003ctable data-v-05762449=\"\" aria-label=\"Specifications\" class=\"sprocket__table spec\"\u003e\n\u003ctbody data-v-05762449=\"\"\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" rowspan=\"1\" scope=\"row\"\u003eFrame\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003eHigh-performance hydroformed e-bike frame, Removable Integrated Battery, Motor Armor, internal cable routing, post-mount disc\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" rowspan=\"1\" scope=\"row\"\u003eFork\u003c\/th\u003e\n\u003ctd data-v-05762449=\"\"\u003e\u003ca data-v-05762449=\"\" href=\"https:\/\/www.trekbikes.com\/gb\/en_GB\/p\/W5277882\"\u003eSR Suntour XCR32, coil spring, preload adjuster, lockout,100 mm QR, 63 mm travel\u003c\/a\u003e\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr data-v-05762449=\"\"\u003e\n\u003cth data-v-05762449=\"\" scope=\"row\"\u003eMax compatible fork travel\u003c\/th\u003e\n\u003ctd data-v-
<
handle>-<
version>/assets/...
// Trailing digits (e.g. ".../restockrocket-1-521/assets/" -> "521"). Kept numeric to
// match ParseStoqData, so funnel app_version lines up with the order-attribution
// app_version. Reflects the ACTUAL deployed build. This is the SINGLE source of the
// parsed version — preorder.js getAppVersion() reads it back off config rather than
// re-parsing, so the regex lives in exactly one place.
try {
const _stoqVersionMatch = window._RestockRocketConfig.scriptHost.match(/(\d+)\/?(?:assets\/?)?$/);
window._RestockRocketConfig.appVersion = (_stoqVersionMatch && _stoqVersionMatch[1]) || '';
} catch (e) {
window._RestockRocketConfig.appVersion = '';
}
const SETTINGS_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds
const LIQUID_CACHE_MAX_AGE = 15 * 60; // 15 minutes in seconds
// Calculate Liquid cache freshness once at initialization
const liquidRenderedAt = window._RestockRocketConfig.liquidRenderedAt;
// Validate timestamp and calculate ca
che age
if (!liquidRenderedAt || typeof liquidRenderedAt !== 'number' || isNaN(liquidRenderedAt)) {
console.debug('STOQ - Invalid or missing liquidRenderedAt timestamp, assuming fresh');
window._RestockRocketConfig.isLiquidCacheFresh = true;
window._RestockRocketConfig.liquidCacheAge = null;
} else {
const now = Math.floor(Date.now() / 1000); // Current time in seconds
const liquidCacheAge = now - liquidRenderedAt; // Age in seconds
// Surfaced into funnel events: a stale cache means the app rendered with
// outdated inventory/selling-plan data — a real "had the opportunity but
// failed" cause. Negative (client clock ahead) clamps to 0.
window._RestockRocketConfig.liquidCacheAge = Math.max(0, liquidCacheAge);
// Handle client clock ahead of server
if (liquidCacheAge
<
0) {
console.debug(`STOQ - Client clock appears ahead of server by ${Math.abs(Math.round(liquidCacheAge / 60))} minutes, assuming cache fresh`);
window._RestockRocketConfig.isLiquidCacheFresh = true;
} else if (liquidCacheAge
<
= 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 ba
ckfill 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 customer 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 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-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