Checklist
Postscript after Reject: what loaded on two Shopify stores
Postscript's SMS SDK on two Shopify stores with Osano: what loaded after Reject vs Accept, what an add-to-cart sent, and the setup steps.
In brief
On two Shopify stores with an Osano banner, Postscript's sdk.bundle.js stayed unloaded after Reject and loaded in the Accept run. The loader file has no consent check, so we infer the banner held it back, and the two stores stopped it at different steps. Store R added one item to the cart on every run and still sent no data request to Postscript. Not legal advice.
What we tested
Store K was captured on 2026-10-20, 10:55-10:57 UTC+8. Store R was captured on 2026-10-21, 09:39-09:43 UTC+8. Both exits were direct from the US with no proxy, recorded as US-VA. The browser was headless Chrome, a clean profile each run, en-US, timezone America/Los_Angeles. Each store had a Fresh run, a Reject run, and an Accept run.
Store K's Osano banner is labeled Accept / Deny Non-Essential. Home: banner, wait 4 seconds, click, wait 12 seconds, scroll. Then one product page, about 23 seconds, scroll. No add-to-cart. Store R's Osano banner is labeled Accept / Deny. Home used the same timing. The product page waited 8 seconds, then one add-to-cart, a 20 second wait, and about 10 seconds of scroll. No checkout. The first add-to-cart click timed out at 8 seconds. Escape closed the overlay, and the second click added the item. The cart held one item on every Store R run. The Postscript phone popup did not appear. We did not fill it or submit it.
Store K: the loader ran, the SDK did not
| Run | Loader GETs | sdk.bundle.js | POSTs | sdk.postscript.io host tally |
|---|---|---|---|---|
| Fresh | 2 (home 3547 ms, product) | 0 | 0 | 1 |
| Reject | 2 (home 3754 ms, product) | 0 | 0 | 1 |
| Accept | 2 (home 3178 ms, product) | 2 (home 6931 ms, product 27225 ms) | 0 | 3 |
The loader file is 2,211 bytes, fetched 2026-10-20. It has no consent check. It appends sdk.bundle.js.
We infer Osano stopped the second script from being inserted. The basis is that the loader itself contains no consent check, so the decision could not have come from Postscript's code.
| Run | Shopify currentVisitorConsent() | marketing / analytics / sale | Osano |
|---|---|---|---|
| Fresh | four empty strings | false / false / true | ESSENTIAL ACCEPT. STORAGE, MARKETING, PERSONALIZATION, ANALYTICS, OPT_OUT DENY. |
| Reject | marketing, analytics, preferences, sale_of_data all no | false / false / false | ESSENTIAL ACCEPT. STORAGE, MARKETING, PERSONALIZATION, ANALYTICS DENY. OPT_OUT ACCEPT. |
| Accept | four yes | true / true / true | ESSENTIAL, STORAGE, MARKETING, PERSONALIZATION, ANALYTICS ACCEPT. OPT_OUT DENY. |
ps_acorn_storefront_pixel_contract_v1 and ps_acorn_storefront_pixel_ready_v1 were in localStorage only on Accept.
Store R: nothing from Postscript until Accept, even with an add-to-cart
Each Store R run added one cart item. No run sent a data request to Postscript, including the 20 seconds after add-to-cart. Accept times in the table are milliseconds from the click mark.
| Run | Loader GETs | sdk.bundle.js | Data requests |
|---|---|---|---|
| Fresh | 0 | 0 | 0 |
| Reject | 0 | 0 | 0 |
| Accept | 2 (home -20 ms, product 20473 ms) | 2 (home 69 ms, product 20534 ms) | 0 |
The Accept home loader at -20 ms is within timing noise of the click mark. Here the loader never ran before Accept, so we infer Osano held back the loader tag itself. Same basis: the loader file is byte-identical to Store K's and has no consent check.
ps_acorn_storefront_pixel_contract_v1 and ps_acorn_storefront_pixel_ready_v1 were in localStorage on Fresh, Reject, and Accept. Fresh and Reject never requested sdk.postscript.io. We did not identify which script wrote the keys.
What we did not see
Six runs, and neither store's cookie list had a Postscript name.
No run sent a POST to Postscript. That includes Store R after add-to-cart. Postscript's developer docs describe page_view and add_to_cart as events fired for subscribers. The visitor was anonymous and did not subscribe, so subscriber events were not tested.
Both stores used Osano. A banner that leaves the tag in place could still load sdk.bundle.js after Reject. We did not capture that case. We did not check out. Attentive after Reject All on two Shopify stores records a different SMS app, on other stores, behind OneTrust.
Other requests after Reject
| Host | Requests |
|---|---|
| server.telemetry.services.yofi.ai | 10 |
| pcap.services.yofi.ai | 1 |
| api.seel.com | 3 |
| static.seel.com | 2 |
| rebuyengine.com | 4 |
| cdn.rebuyengine.com | 7 |
| cached.rebuyengine.com | 1 |
Fresh shows nearly the same counts (yofi 9, seel 3, rebuy 4).
Rebuy after Reject is another store's rebuyengine.com capture. Store letters are per-page labels.
| Host | POSTs |
|---|---|
| TikTok hosts | 100 |
| otlp-http-production.shopifysvc.com | 16 |
| www.google.com | 6 |
| graph.instagram.com | 6 |
| backend.alia-prod.com | 4 |
| apps.rokt-api.com | 3 |
| googleads.g.doubleclick.net | 3 |
| jointrybe.com | 2 |
| ct.pinterest.com | 2 |
| rebuyengine.com | 1 |
| alb.reddit.com | 1 |
| consent.api.osano.com | 1 |
| sessions.bugsnag.com | 1 |
| tattle.api.osano.com | 1 |
On Store R, after add-to-cart, Fresh and Reject match: otlp-http-production.shopifysvc.com 7, jointrybe.com 1, apps.rokt-api.com 1, ct.pinterest.com 1, googleads.g.doubleclick.net 1, tattle.api.osano.com 1. Accept keeps those and adds one www.facebook.com POST.
| Store | Fresh, no click | Reject | Accept |
|---|---|---|---|
| Store K, no add-to-cart | 31 hosts, 78 requests | 32 hosts, 92 requests | 60 hosts, 266 requests |
| Store R, with add-to-cart | 61 hosts, 884 requests | 64 hosts, 815 requests | 70 hosts, 1022 requests |
The two stores ran different paths, so their totals are not comparable. TikTok and Instagram embeds on the Store R home page account for most of Store R's requests.
Hosts only on Store R Accept: sdk.postscript.io, connect.facebook.net, www.facebook.com, fast.a.klaviyo.com, static-forms.klaviyo.com, static-tracking.klaviyo.com, mssdk.tiktokw.us, www.merchant-center-analytics.goog.
Hosts on Store R Reject that Fresh lacked: consent.api.osano.com, v16m.tiktokcdn-us.com, v19.tiktokcdn-us.com. Store K Reject added only consent.api.osano.com.
Shopify's consent value on Store R
We ran every capture from a US exit in Virginia. Shopify's Customer Privacy API docs say: "For regions that are configured to require consent, non-essential purposes are not allowed by default until consent is given. For other regions, the default behavior is to allow all processing purposes." So the empty strings and marketingAllowed() returning true on Store R may depend on where the visitor is. We did not test from another region, and we cannot see which regions Store R requires consent for.
On Store R the four currentVisitorConsent() strings stayed empty before the click and at the end of Fresh, Reject, and Accept. marketing, analytics, and sale stayed true on all three.
| Run | Osano at end | Shopify strings | marketing / analytics / sale |
|---|---|---|---|
| Fresh, and the pre-click state on Reject and Accept | ESSENTIAL ACCEPT. STORAGE, MARKETING, PERSONALIZATION, ANALYTICS, OPT_OUT DENY. | empty | true / true / true |
| Reject | STORAGE, MARKETING, PERSONALIZATION, ANALYTICS DENY. OPT_OUT ACCEPT. ESSENTIAL ACCEPT. | empty | true / true / true |
| Accept | STORAGE, MARKETING, PERSONALIZATION, ANALYTICS ACCEPT. OPT_OUT DENY. ESSENTIAL ACCEPT. | empty | true / true / true |
How to check Postscript on your own store
- Open a regular Chrome window in private mode. Open DevTools, Network tab, Preserve log on.
- Load the store, click Reject in the banner, then add one item to the cart.
- Filter for postscript and look for sdk.bundle.js. If it appears before you click Accept, the main SDK loaded after Reject.
- Repeat in a new private window with no click, then with Accept.
- In the Console, run currentVisitorConsent() on Shopify.customerPrivacy. Then run marketingAllowed() and analyticsProcessingAllowed().
- In Application, localStorage, look for keys starting with ps_, including the contract key and the ready key.
For the method, see How to test an SMS tool before Accept.
Setup notes from the official docs
Steps below come from the official docs. We did not verify each one.
- Postscript installs the SDK as a Shopify theme app embed: Online Store, Themes, Customize, App embeds. The JavaScript embed starts on. Save it. After a theme change, turn it on again or acquisition tools, cookies, and onsite events for automations stop. Source: Embed Postscript SDK via Shopify Theme App Extension, 2026-02-09. Those docs show no consent switch and no region switch.
- A headless store pastes sdk.bundle.js with its shopId and sends page_view and add_to_cart itself. Sources: Postscript Headless Integrations and the SDK API Reference.
- Installing Osano on Shopify says to add an osano-shopify snippet, call window.Osano.cm.ready("shopify"), and render it from theme.liquid. Without that, Osano says it does not govern Shopify cookies, scripts, and Pixels. Category map: Personalization to Preferences, Marketing to Marketing, Analytics to Analytics, Do Not Sell to Sale of Data. Also turn off automated cookie-banner settings, remove the Shopify banner, and choose regions that require consent.
- Theme tags and tag-manager tags follow Osano categories and blocking. Shopify Pixels follow the Customer Privacy API. Source: Shopify and Osano Troubleshooting Guide.
- Shopify's Customer Privacy API page says regions that are not set to require consent allow processing by default. The sentence is quoted in the previous section.
Not legal advice.
FAQ
Does Postscript set cookies before consent?
No Postscript cookie appeared in any of the six runs.
Does Postscript respect Reject on its own?
The loader has no consent check. On both stores sdk.bundle.js loaded only in the Accept run, which we attribute to the banner.
Does add-to-cart send data to Postscript?
The anonymous visitor on Store R sent none. Each run added one item, and no data request went to Postscript. Subscriber events were not tested.
Sources
These links cover the platform and regulatory context used in this guide. Applicability still depends on the organization and jurisdiction.
Save a US-baseline technical record
After a DIY check, run a free US-baseline audit: one browser visit outside California, with cookies, requests, and screenshots stored as evidence. That visit does not run EU reject/accept or California GPC. EU, California, and Global 2 audits can be purchased from Billing after sign-in.