Troubleshooting
Causes and fixes for the most common problems when installing and using the SDK on your checkout.
First, open the checkout with your browser's developer tools and run Proteside.getStatus() in the console. The
result points to most of the problems below. See Verify the installation.
Installation
The dashboard only considers the SDK active when it receives events from real customers. Check, in this order:
- Is the snippet published? View the source of the published checkout page and search for
Proteside Start. Clear your site, theme and CDN caches. - Is it on the right domain? The snippet must be on the pages where the checkout actually runs, which may be on a different domain or subdomain.
- Has anyone opened the checkout? Open the page yourself and reload the dashboard after a few seconds.
- Does the SDK load? Run
Proteside.getStatus()in the console. If it errors, see the next item. - Are events going out? In the Network tab,
POST …/api/sdk/eventsshould respond202. See The SDK runs, but nothing reaches the dashboard.
If the SDK Health page shows Only synthetic checks, Proteside's checker found the snippet, but no real customer has gone through the checkout yet.
shield.js didn't load. Common causes:
- the snippet isn't published, or only the bootstrapper was pasted;
- the Content Security Policy doesn't allow
https://cdn.proteside.cominscript-src(the console showsRefused to load the script); - an ad or tracker blocking extension blocked the file (test in a private window with no extensions);
- an optimization plugin changed or removed the tag.
Wait a few seconds: the SDK only finishes starting up after fetching the configuration (up to 2 s). If it stays
false:
data-keyis missing on theshield.jstag. Without it, the SDK doesn't initialize and shows no warning.- The key has an invalid format. The console shows
[Proteside] Initialization failed silentlywithInvalid apiKey format. The key starts withpk_live_. - The tag was loaded as
type="module". Remove that attribute.
The SDK sends this warning, and getStatus().installationOrderValid becomes false, when there's any <script> on
the page before the bootstrapper.
To see the page's first two scripts, run this in the console:
Array.from(document.scripts).slice(0, 2).map((s) => s.src || s.textContent.slice(0, 40))- The first item starts with
"use strict";(followed byvar __ProteBootsor, if the store has inline rules, bywindow.__PROTE_INLINE__=): the bootstrapper is the first script and the order is correct. - The first item starts with
window.__PROTE_INLINE__=and the second with"use strict";var __ProteBoots: this is case 1. - Anything else: this is case 2.
After fixing it, resolve the alert in the dashboard. If it doesn't come back on the next visit to the page, the order is right.
This warning isn't part of the compliance status in PCI DSS Evidence.
Case 1: older snippet, with the window.__PROTE_INLINE__ line in its own tag. For stores with blocking rules or
allowed GTM containers, the dashboard's snippet used to put the configuration in a separate <script> before the
bootstrapper. It now goes at the start of the bootstrapper's own <script>. From SDK 1.1.2 on, the old tag doesn't
count as a preceding script, as long as it only contains the window.__PROTE_INLINE__={…}; assignment. If the warning
persists:
- check in SDK Health whether the page still runs a version older than 1.1.2;
- make sure nobody added code to the
window.__PROTE_INLINE__line or rewrote the JSON: with any other content, the tag counts as a preceding script again; - or paste the snippet again from Pages & Domains. The current format has a single inline tag and doesn't depend on the SDK version.
Don't delete the window.__PROTE_INLINE__ configuration to make the warning go away: it's what blocks scripts from
the page's very first byte.
Case 2: there's another script before the snippet. Move the snippet to the top of the <head> and publish again.
If the preceding script comes from the theme, a plugin or the platform itself and can't be moved, protection keeps
working, but with partial coverage: whatever that script does before the bootstrapper isn't observed. On Next.js,
check the final tag order in the source of the published page.
These detections depend on the bootstrapper. If only the shield.js tag was pasted, or an optimization plugin turned
the bootstrapper into an external or deferred file, the SDK runs with reduced coverage, and getStatus() doesn't
indicate it. Check in the console:
typeof window.__PROTE_BOOT_TS__ === 'number' // should be trueIf it's false, paste the full snippet again and exclude it from JavaScript optimizations.
The shield.js URL (stable or latest channel) is written into the snippet. After changing the channel in
Payment protection, copy the snippet again from Pages & Domains and publish it.
If SDK Health shows more than one active version for several days, check that every page uses the same snippet. Right after an update, it's normal to see two versions because of browser and CDN caching.
Blocks and rules
Common console messages and what to allow:
| Message | What's missing |
|---|---|
Refused to load the script 'https://cdn.proteside.com/…' | https://cdn.proteside.com in script-src |
Refused to execute inline script | hash, nonce or 'unsafe-inline' for the bootstrapper |
Refused to connect to 'https://app.proteside.com/…' | https://app.proteside.com in connect-src |
The inline script message gives you the 'sha256-…' hash to include. See
Content Security Policy and headers.
With Allowed GTM containers filled in, the SDK blocks any gtag/js with an ID outside the list, including Google
Analytics 4 (G-…) and Google Ads (AW-…) tags fired by GTM itself. The list only accepts GTM-… IDs, so there's no
way to allow those IDs.
To fix it:
- In Payment protection, empty the Allowed GTM containers list and click Save changes.
- Copy the snippet again from Pages & Domains and publish it. The list is also written into the snippet and keeps blocking at the start of the page load until you paste the snippet again.
The block applies in both protection modes, Monitor and Block.
- The script is in the page's HTML. Scripts written into the HTML run before the SDK loads and can't be stopped in the browser. In Scripts, they show up with a note that they keep loading from the HTML. Remove the tag from the HTML or the theme.
- The rule is by Content hash. The SDK doesn't apply rules of this type. Use Domain or Script URL.
- The rule is inactive. Inactive rules aren't sent to the SDK.
- The change hasn't arrived yet. See A dashboard change didn't reach the checkout.
- In Rules, deactivate the rule that matches the affected script. Remember that a Domain rule blocks the entire domain and all its subdomains.
- Copy the snippet again from Pages & Domains and publish it: rules are written into the snippet.
- If you turned on Block mode, switch back to Monitor while you investigate.
Turning on Developer mode doesn't undo the blocks written into the snippet. See Pause and developer mode.
Data in the dashboard
That's expected. Every new script the SDK finds enters the inventory with the Needs review status and waits for your decision. To comply with PCI DSS 4.0, requirement 6.4.3, authorize each legitimate script with a justification or block the ones that shouldn't be there. You can authorize all first-party scripts at once and create policies to automate recurring decisions.
An authorized script goes back to Needs review when its content changes or when the authorization expires. See Scripts and Policies.
- Configuration cache: the configuration may be cached for 60 seconds, and the CDN may serve the previous version for a few more minutes. Wait and reload the checkout.
- Rules and GTM containers: these are written into the snippet. Paste the snippet again after changing them.
- Release channel: requires pasting the snippet again.
Check the response to GET …/api/sdk/config and POST …/api/sdk/events in the Network tab:
| Response | Cause | What to do |
|---|---|---|
401 | The key doesn't exist or was rotated more than 24 hours ago. The SDK runs with its local defaults, but events are discarded. | Copy the current snippet from Pages & Domains. |
402 | The subscription isn't current. The SDK stays paused. | See Billing. |
403 | The store is suspended. | Contact support. |
| Request blocked | CSP without https://app.proteside.com in connect-src, or an ad blocker. | See CSP and headers. |
A domain that had already sent events went 24 hours without real sessions. Check that the snippet is still published (a theme or template update can remove it) and that the checkout had visits during that period. The alert resolves itself when traffic comes back.
Payment
- No customer has paid with Pix yet with the SDK on the page. The status changes with the first valid reading.
- The Pix code is in an
<input>or<textarea>field. The SDK only reads text. Show the code as text. See Payment integrity and Pix. - The snippet isn't on the page that shows the Pix code, for example a payment page separate from the checkout.
- The code is inside the payment provider's iframe. The SDK only reads the main page, not the content of iframes.
The recipient read from the code isn't among the Trusted recipients. Before treating it as an attack, check:
- whether the registered key is the same one that appears in the copy-and-paste code generated by your payment provider. Some providers generate the code with their own key, different from the store's key;
- whether all the keys your store uses are registered and active.
If the code's key belongs neither to your store nor to your provider, treat it as an incident: open the alert in Alerts.
A dynamic BRCode carries a charge URL instead of the recipient's key, so there's no key to compare against the trusted
list. The SDK keeps comparing the displayed code with the first reading on the page. If the code includes the amount,
also provide the expected amount with
Proteside.expectPayment().
Still having problems?
Gather the output of Proteside.getStatus(), the responses from /api/sdk/config and /api/sdk/events in the
Network tab and the address of the affected page, and contact Proteside support.