1(function () { 2 window._ReStockConfig = window._ReStockConfig || {}; 3 var _ReStockConfig = window._ReStockConfig; 4 5 var metafieldConfigData = _ReStockConfig._metafields ? _ReStockConfig._metafields.sdkConfig : null; 6 var metafieldPreOrderData = _ReStockConfig._metafields ? _ReStockConfig._metafields.preOrderConfig : null; 7 var metafieldWishlistData = _ReStockConfig._metafields ? _ReStockConfig._metafields.wishlistConfig : undefined; 8 var metafieldFlagsData = _ReStockConfig._metafields ? _ReStockConfig._metafields.featureFlags : null; 9 10 delete window._ReStockConfig._metafields; 11 12 function createRestockScript() { 13 const restockSdkElement = document.createElement('script'); 14 restockSdkElement.setAttribute('defer', 'defer'); 15 restockSdkElement.src = "https://cdn.notify-me.io/sdk.js"; 16 document.body.appendChild(restockSdkElement); 17 } 18 19 function processNotifyMeConfigData(configData) { 20 if (!configData.app_enabled) { 21 return; 22 } 23 if (configData.is_suspended) { 24 return; 25 } 26 27 _ReStockConfig = { ..._ReStockConfig, ...configData }; 28 window._ReStockConfig = _ReStockConfig; 29 30 if (_ReStockConfig.wishlist?.is_service_active) { 31 createRestockScript(); 32 return; 33 } 34 35 if (['collection', 'list-collections', 'search', 'page'].includes(_ReStockConfig.templateName)) { 36 const collectionDisplayMode = configData.ui_style?.notify_me_styles?.find(config => config.page === 'COLLECTION_PAGE')?.inline_display_mode; 37 const preOrderCollectionDisplayMode = configData.pre_order?.collection_page?.ui_styles?.display_mode; 38 39 if ((!configData.is_back_in_stock_active || collectionDisplayMode === 'NOT_DISPLAYED') && 40 (!configData.pre_order?.is_service_active || preOrderCollectionDisplayMode === 'NOT_DISPLAYED')) { 41 return; 42 } 43 } 44 45 if (_ReStockConfig.templateName === 'index') { 46 const landingDisplayMode = configData.ui_style?.notify_me_styles?.find(config => config.page === 'LANDING_PAGES')?.inline_display_mode; 47 const preOrderLandingDisplayMode = configData.pre_order?.landing_page?.ui_styles?.display_mode; 48 49 if ((!configData.is_back_in_stock_active || landingDisplayMode === 'NOT_DISPLAYED') && 50 (!configData.pre_order?.is_service_active || preOrderLandingDisplayMode === 'NOT_DISPLAYED')) { 51 return; 52 } 53 } 54 55 createRestockScript(); 56 } 57 58 function hashDomain(domain) { 59 let hash = 5381; 60 for (let i = 0; i < domain.length; i++) { 61 hash = ((hash << 5) + hash + domain.charCodeAt(i)) >>> 0; 62 } 63 return hash; 64 } 65 66 function assignGroup(shopifyDomain) { 67 const DOBBY_USAGE_PERCENTAGE = 0; 68 if (DOBBY_USAGE_PERCENTAGE <= 0) { 69 return "A"; 70 } else if (DOBBY_USAGE_PERCENTAGE >= 100) { 71 return "B"; 72 } 73 const hashValue = hashDomain(shopifyDomain); 74 const normalized = (hashValue / 0x100000000) * 100; 75 return normalized <= DOBBY_USAGE_PERCENTAGE ? "B" : "A"; 76 } 77 78 try { 79 80 try { 81 const searchParams = new URLSearchParams(window.location.search); 82 const shopDomain = searchParams.get('SHOP_DOMAIN') || window.Shopify?.shop || window.location.host; 83 84 const abTestGroup = assignGroup(shopDomain); 85 window._ReStockConfig.ab_test_group = abTestGroup; 86 87 if (abTestGroup === "B") { 88 const dobbyApiUrl = `https://dobby.notify-me.app/sdk/${shopDomain}`; 89 90 fetch(dobbyApiUrl) 91 .then(response => { 92 if (!response.ok) { 93 throw new Error(`Dobby API returned status ${response.status}`); 94 } 95 return response.json(); 96 }) 97 .then(data => { 98 const wishlistConfig = data.wishlist ?? null; 99 100 const { wishlist, ...sdkConfig } = data; 101 102 if (!sdkConfig || !sdkConfig.shop_id) { 103 throw new Error('Invalid Dobby API response'); 104 } 105 106 window._ReStockConfig.wishlist = wishlistConfig !== null ? wishlistConfig : (metafieldWishlistData ?? undefined); 107 108 processNotifyMeConfigData(sdkConfig); 109 }) 110 .catch(error => { 111 window._ReStockConfig.wishlist = metafieldWishlistData ?? undefined; 112 window._ReStockConfig.pre_order = metafieldPreOrderData; 113 window._ReStockConfig.feature_flags = metafieldFlagsData; 114 115 if (metafieldConfigData && metafieldConfigData.shop_id) { 116 processNotifyMeConfigData(metafieldConfigData); 117 } else { 118 createRestockScript(); 119 } 120 }); 121 } else { 122 const hasSdkMetafield = metafieldConfigData && metafieldConfigData.shop_id; 123 const hasPreOrderMetafield = metafieldPreOrderData && typeof metafieldPreOrderData === 'object' && Object.keys(metafieldPreOrderData).length > 0; 124 const hasFlagsMetafield = metafieldFlagsData && typeof metafieldFlagsData === 'object'; 125 126 const fallbackApiUrl = `https://api.notify-me.app/sdk/${shopDomain}`; 127 const preOrderFallbackApiUrl = `https://api.notify-me.app/pre-order/sdk/${shopDomain}`; 128 const flagsFallbackApiUrl = `https://api.notify-me.app/feature-flags/sdk/${shopDomain}`; 129 130 const fetchSdkConfig = () => { 131 return fetch(fallbackApiUrl) 132 .then(response => { 133 if (!response.ok) throw new Error(`SDK API returned status ${response.status}`); 134 return response.json(); 135 }) 136 .then(data => { 137 const { wishlist, ...sdkConfig } = data; 138 if (!sdkConfig || !sdkConfig.shop_id) throw new Error('Invalid SDK API response'); 139 return { sdkConfig, wishlistConfig: wishlist ?? null }; 140 }); 141 }; 142 143 const fetchPreOrderConfig = () => { 144 return fetch(preOrderFallbackApiUrl) 145 .then(response => { 146 if (!response.ok) throw new Error(`Pre-order API returned status ${response.status}`); 147 return response.json(); 148 }) 149 .then(data => { 150 return data; 151 }); 152 }; 153 154 const fetchFlagsConfig = () => { 155 return fetch(flagsFallbackApiUrl) 156 .then(response => { 157 if (!response.ok) throw new Error(`Flags API returned status ${response.status}`); 158 return response.json(); 159 }); 160 }; 161 162 const sdkPromise = hasSdkMetafield 163 ? Promise.resolve({ sdkConfig: metafieldConfigData, wishlistConfig: null })
164 : fetchSdkConfig().catch(err => { 165 return null; 166 }); 167 168 const preOrderPromise = hasPreOrderMetafield 169 ? Promise.resolve(metafieldPreOrderData) 170 : fetchPreOrderConfig().catch(err => { 171 return null; 172 }); 173 174 const flagsPromise = hasFlagsMetafield 175 ? Promise.resolve(metafieldFlagsData) 176 : fetchFlagsConfig().catch(err => { 177 return null; 178 }); 179 180 Promise.all([sdkPromise, preOrderPromise, flagsPromise]) 181 .then(([sdkResult, preOrderConfig, flagsConfig]) => { 182 if (sdkResult) { 183 window._ReStockConfig.wishlist = sdkResult.wishlistConfig !== null 184 ? sdkResult.wishlistConfig 185 : (metafieldWishlistData ?? undefined); 186 const combinedConfig = { ...sdkResult.sdkConfig, pre_order: preOrderConfig, feature_flags: flagsConfig }; 187 processNotifyMeConfigData(combinedConfig); 188 } else { 189 window._ReStockConfig.wishlist = metafieldWishlistData ?? undefined; 190 window._ReStockConfig.pre_order = preOrderConfig; 191 window._ReStockConfig.feature_flags = flagsConfig; 192 createRestockScript(); 193 } 194 }); 195 } 196 } 197 catch (e) { 198 window._ReStockConfig.wishlist = metafieldWishlistData ?? undefined; 199 window._ReStockConfig.pre_order = metafieldPreOrderData; 200 window._ReStockConfig.feature_flags = metafieldFlagsData; 201 202 if (metafieldConfigData && metafieldConfigData.shop_id) { 203 processNotifyMeConfigData(metafieldConfigData); 204 } else { 205 createRestockScript(); 206 } 207 } 208 } catch (error) { 209 createRestockScript(); 210 } 211})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.