On stores running the current sdk.pop-convert.com/sdk.js, any browser whose localStorage.__pc__closed holds a bare timestamp — written by an older build — hits an uncaught TypeError at the top level of the SDK module. Module evaluation stops, window.pc and window.triggerPC are never created, and no campaign can ever display for that visitor again. It is silent and permanent: the current build reads the value but never overwrites or repairs it.
Error
Uncaught TypeError: gn(...).concat is not a function at mr
Cause
gn(key, 'local') returns JSON.parse(localStorage['pc' + key] || '[]'), and mr(key) chains .concat() across the local, session and page stores. mr("submitted") and mr("closed") are called at module top level, outside any try/catch:
const qd = mr("submitted"), Gd = mr("closed");
for (const e of qd) Gd.some(t => t.id === e.id) || Rc("closed", "local", e);
Every write in the current build stores an array of { id, closedAt: <ISO string> } records, so the shape is normally fine. But older data of the form localStorage['__pc__closed'] = "1789830921791" parses to a number, which has no .concat.
Impact
listAll("closed") is also what the display-eligibility check calls, so the failure sits directly on the path that decides whether a campaign shows. Confirmed by A/B on a live storefront, same page, only that one storage value differing:
key absent → console clean, window.triggerPC is a function, window.pc holds the campaign, window.injectFontFromCss is a function
key = 1789830921791 → TypeError, and all three are undefined, while the sdk.js script tag is present in both cases
Merchants cannot see this — it lives in individual shoppers' browsers, affects only returning visitors who dismissed a popup under the older build, and produces no console output in the merchant's own browser unless they happen to be one of them.
Reproduce
On a store with the SDK installed, run localStorage.setItem('__pc__closed', '1789830921791')
Reload any page
Console shows the TypeError; typeof window.triggerPC is "undefined"; no campaign renders
localStorage.removeItem('__pc__closed') and reload — everything works again
Suggested fix
Make gn() defensive, e.g. const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : [];, and/or wrap the top-level mr("submitted") / mr("closed") migration block in a try/catch that resets the key. Either would let affected browsers self-heal instead of staying dead indefinitely.
Workaround in use
We now sanitise pc* / pcwindow* keys in our theme before loading the SDK, dropping any whose value doesn't parse to an array.