PageSourceSearch

https://petarmor.com/a/sos/widget.js

js petarmor.com collected 2026-09-24 22:20:29 UTC 6,352 bytes, 129 lines download raw bytes

1(function () {
2  var MODE = "live";
3  // The CHECKOUT capability, resolved server-side. Gates the cart UI only; the
4  // concierge has its own switch below.
5  var SHOW_CHECKOUT = true;
6  try {
7    var BC_ROUTE_PATH = "/a/sos";
8    if (BC_ROUTE_PATH && !window.__BC_ROUTE_PATH__) {
9      window.__BC_ROUTE_PATH__ = BC_ROUTE_PATH;
10    }
11    var BC_IDENTITY = null;
12    if (BC_IDENTITY) {
13      window.__BC_BOOTSTRAP__ = Object.assign({}, BC_IDENTITY, window.__BC_BOOTSTRAP__ || {});
14    }
15  } catch (e) {}
16  var FALLBACK_ID = 'bc-ask-us-fallback';
17  function previewMarked() {
18    try {
19      var v = new URLSearchParams(window.location.search).get('bc-preview');
20      if (v === '1') { window.localStorage.setItem('__bc_widget_preview__', '1'); return true; }
21      if (v === '0') { window.localStorage.removeItem('__bc_widget_preview__'); return false; }
22      return window.localStorage.getItem('__bc_widget_preview__') === '1';
23    } catch (e) { return false; }
24  }
25  function unpublishedTheme() {
26    try {
27      var role = window.__BC_THEME_ROLE__ || (window.Shopify && window.Shopify.theme && window.Shopify.theme.role);
28      return Boolean(role) && role !== 'main';
29    } catch (e) { return false; }
30  }
31  // Read the marker BEFORE gating: a merchant who clicks the preview link
32  // while the widget is still off must have this browser armed, so the widget
33  // appears the moment the mode becomes preview — without a second click.
34  var marked = previewMarked();
35  // The THEME EDITOR's preview always renders, whatever the rollout mode:
36  // Shopify stamps designMode there, only the merchant is looking, and a
37  // merchant who just toggled the embed on and sees nothing concludes the app
38  // is broken (found live 2026-08-20). The editor previews the LIVE theme, so
39  // the unpublished-theme allowance does not cover it, and the editor iframe
40  // cannot see this browser's preview marker (partitioned storage).
41  function editorPreview() {
42    try { return !!(window.Shopify && window.Shopify.designMode); } catch (e) { return false; }
43  }
44  // WHAT THE SWITCH GATES (changed 2026-09-02). NOTE: no backticks in this
45  // comment - it lives inside the generated-JS template literal.
46  //
47  // "off" still loads NOTHING. It is the merchant kill switch and the safe
48  // default a store sits at while it is still being set up, and a self-serve
49  // store has no other Brandclub code on the page to keep alive.
50  //
51  // "preview" now LOADS the bundle for everyone and only withholds the
52  // CONCIERGE. The bundle is one file carrying the cart, Add to bag, the
53  // profile icon AND the concierge, so returning here took the whole storefront
54  // integration down with the chat - which made "publish the theme, keep the
55  // cart, show the concierge to nobody yet" impossible to express. That is
56  // precisely the state a brand with an existing gated rollout (PetArmor) needs
57  // in order to cut over. The admin page copy already promises this reading:
58  // "The concierge is hidden from everyone."
59  //
60  // "live" / "preview" now differ for the CONCIERGE only: the cart follows the
61  // CHECKOUT capability (SHOW_CHECKOUT above), so "publish the theme, keep the
62  // cart, show the concierge to nobody yet" is expressible (Plan 16 item 2).
63  //
64  // NOTE the asymmetry that remains, and is intended: at "off" the store loses
65  // the cart too, because "off" is the merchant KILL SWITCH — one setting that
66  // takes every trace of us off the storefront. A merchant who wants the cart
67  // without the chat sets "preview", not "off".
68  if (MODE === 'off' && !editorPreview()) return;
69  var showConcierge = editorPreview() || MODE === 'live' || marked || unpublishedTheme();
70
71  var src = "https://app-stackline-dtc.shopperos.app/bc-checkout-shop-app/bc-checkout-shop-app.js" || window.__BC_WIDGET_SCRIPT_URL__;
72  if (!src) return;
73  var fb = window.__BC_WIDGET_FALLBACK__ || {};
74
75  function ensureFallback() {
76    // The fallback IS a concierge entry point, so it obeys the same switch the
77    // bubble does. Without this, a store in preview mode would show every
78    // shopper an "Ask us" link the moment the bundle failed to load.
79    if (!showConcierge) return;
80    if (document.getElementById(FALLBACK_ID)) return;
81    if (window.BCCheckoutBar && typeof window.BCCheckoutBar.renderBarScript === 'function') return;
82    var a = document.createElement('a');
83    a.id = FALLBACK_ID;
84    a.href = fb.path || '/a/sos/concierge';
85    a.className = 'bc-ask-us bc-ask-us--' + (fb.position === 'left' ? 'left' : 'right');
86    a.setAttribute('aria-label', fb.label || 'Ask us');
87    a.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">' +
88      '<path d="M12 3C7.03 3 3 6.58 3 11c0 2.06.9 3.94 2.37 5.37L4.5 20.5l4.42-1.47c.97.31 2.01.47 3.08.47 ' +
89      'c4.97 0 9-3.58 9-8s-4.03-8.5-9-8.5Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>
89' +
90      '<span></span>';
91    a.querySelector('span').textContent = fb.label || 'Ask us';
92    if (document.body) document.body.appendChild(a);
93  }
94
95  function mount() {
96    if (window.BCCheckoutBar && typeof window.BCCheckoutBar.renderBarScript === 'function') {
97      var link = document.getElementById(FALLBACK_ID);
98      if (link) link.remove();
99      // conciergeControlled is the DEPRECATED flag, still sent so a bundle copy
100      // cached on the CDN keeps working; mountSource is what a current bundle
101      // reads. showConcierge carries the switch decision made above - the
102      // loader owns it because only the loader knows the store mode and whether
103      // THIS browser is a marked previewer.
104      window.BCCheckoutBar.renderBarScript({
105        conciergeControlled: true,
106        mountSource: 'app-proxy',
107        showConcierge: showConcierge,
108        showCheckout: SHOW_CHECKOUT,
109      });
110      return true;
111    }
112    return false;
113  }
114
115  var script = document.createElement('script');
116  script.src = src;
117  script.defer = true;
118  script.onload = function () {
119    if (mount()) return;
120    var tries = 0;
121    var timer = setInterval(function () {
122      tries += 1;
123      if (mount()) { clearInterval(timer); return; }
124      if (tries > 20) { clearInterval(timer); ensureFallback(); }
125    }, 250);
126  };
127  script.onerror = ensureFallback;
128  (document.head || document.documentElement).appendChild(script);
129})();

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.