Skip to main content

SDK Installation Verification FAQ

After installing the Break Ground SDK on your website, the dashboard verifies the installation in three steps:

  1. Script Loaded — any event received (proves the API key works and the script loaded)
  2. SDK Initialized — an SDK_INIT event received (proves DAP('init', ...) was called)
  3. Events Flowing — behavioral events received (proves data capture is working)

If verification is stuck on one of these steps, find your symptom below.


"Script not loaded" — Step 1 fails

No events are reaching the API at all.

Wrong or missing API key

The tenantKey in your snippet must exactly match an active API key from Settings > API Keys. A typo, an empty string, or a revoked key will silently fail.

How to fix:

  1. Go to your Break Ground dashboard → Settings > API Keys
  2. Copy the full API key (it starts with wfx_)
  3. Replace the tenantKey value in your snippet:
    DAP("init", {
    tenantKey: "wfx_abc123...",
    baseUrl: "https://api.yourapp.com",
    });
  4. Redeploy your site and click Check Again in the verification panel

Missing or incorrect baseUrl

If you omit baseUrl, the SDK defaults to a placeholder URL (https://api.dap.example.com) that does not exist.

How to fix:

  1. Go to your Break Ground dashboard → Settings > Installation

  2. Copy the full snippet — it includes the correct baseUrl for your environment

  3. Replace your existing snippet with the copied one

  4. Verify the baseUrl starts with https:// and has no trailing slash:

    // Correct
    DAP("init", { tenantKey: "wfx_...", baseUrl: "https://api.yourapp.com" });

    // Wrong — trailing slash
    DAP("init", { tenantKey: "wfx_...", baseUrl: "https://api.yourapp.com/" });

    // Wrong — missing baseUrl entirely (defaults to placeholder)
    DAP("init", { tenantKey: "wfx_..." });

Content Security Policy (CSP) blocking the script

How to diagnose:

  1. Open your website in Chrome/Edge → press F12 → go to the Console tab
  2. Look for an error like:
    Refused to load the script 'https://...' because it violates the following
    Content Security Policy directive: "script-src 'self'"
  3. If you see this error, your CSP is blocking the SDK

How to fix:

  1. Find your CSP header — it's typically set in one of these places:
    • A <meta http-equiv="Content-Security-Policy"> tag in your HTML <head>
    • An HTTP response header (Content-Security-Policy) set by your web server or CDN (e.g., nginx config, Cloudflare headers, Vercel vercel.json)
  2. Add the SDK script domain to the script-src directive. For example, if your SDK is hosted at https://cdn.breakground.io:
    script-src 'self' https://cdn.breakground.io;
  3. Also add the API domain to connect-src so the SDK can make API calls:
    connect-src 'self' https://api.yourapp.com;
  4. If you self-host the SDK (bundled with your app), you only need the connect-src change

Ad-blockers or privacy extensions

Browser extensions like uBlock Origin, Privacy Badger, or Brave Shields can block third-party scripts and network requests.

How to diagnose:

  1. Open your website in a private/incognito window with all extensions disabled
  2. Check if the SDK verification passes now
  3. If it passes in incognito but not in a normal window, an extension is blocking it

How to fix:

The best solution is to self-host the SDK so it's served from your own domain:

  1. Download the SDK bundle from npm: npm install @breakground/runtime-sdk
  2. Include the SDK file from your own static assets instead of a CDN
  3. This makes the SDK indistinguishable from your own code to ad-blockers

If self-hosting isn't an option, document for your end users that they should allowlist your site in their ad-blocker.

Script tag placement

How to diagnose:

  1. Open your website → press F12 → go to the Console tab
  2. Type typeof DAP and press Enter
  3. If it returns "undefined", the SDK script hasn't loaded yet

How to fix:

Use the exact snippet from Settings > Installation — it includes a command queue that handles load ordering automatically. If you're placing the script manually, ensure this order:

<!-- 1. Load the SDK script FIRST (no async/defer) -->
<script src="https://cdn.breakground.io/sdk.js"></script>

<!-- 2. Initialize AFTER the script tag -->
<script>
DAP("init", { tenantKey: "wfx_...", baseUrl: "https://api.yourapp.com" });
</script>

If you must use async, use the command queue pattern:

<script>
// Command queue — buffers calls until the SDK loads
window.DAP =
window.DAP ||
function () {
(window.DAP.q = window.DAP.q || []).push(arguments);
};
DAP("init", { tenantKey: "wfx_...", baseUrl: "https://api.yourapp.com" });
</script>
<script async src="https://cdn.breakground.io/sdk.js"></script>

"SDK not initialized" — Step 2 fails

The script loaded, but the SDK_INIT event was never received.

DAP('init', ...) never called

How to diagnose:

  1. Open your website → press F12 → go to the Console tab
  2. Type typeof DAP — if it returns "function", the script loaded
  3. Search your page source (Ctrl+U) for DAP('init' — if it's missing, the init call was never added

How to fix:

Add the init call after the SDK script tag. The snippet from Settings > Installation includes both the script tag and the init call — copy the full snippet, not just the <script src> tag.

baseUrl pointing to the wrong environment

How to diagnose:

  1. Open your website → press F12 → go to the Network tab
  2. Filter by /api/sdk/config
  3. Check the request URL — does the domain match your Break Ground dashboard URL?
    • Dashboard at https://app.breakground.io → API should be https://api.breakground.io
    • Dashboard at https://app.staging.breakground.io → API should be https://api.staging.breakground.io

How to fix:

  1. Go to the correct dashboard environment → Settings > Installation
  2. Copy the snippet (it has the matching baseUrl)
  3. Replace the snippet on your website

API endpoint unreachable

How to diagnose:

  1. Open your website → press F12 → go to the Network tab
  2. Filter by /api/sdk/config
  3. Look at the request status:
    • No request at all → the init call isn't running (see sections above)
    • Status (failed) or ERR_NAME_NOT_RESOLVED → DNS can't resolve the API domain
    • Status (failed) with ERR_CONNECTION_REFUSED → API server is down or port is blocked
    • CORS error in console → see "CSP blocking" section above

How to fix:

  1. Test from your terminal to rule out browser issues:
    curl -v https://your-api-domain/health
  2. If curl also fails:
    • Verify the domain is correct (no typos)
    • Check if your network/firewall allows outbound HTTPS to the API domain
    • Check the Break Ground status page for outages
  3. If curl succeeds but the browser fails, it's a CSP or CORS issue — see the CSP section above

JavaScript errors before init()

How to diagnose:

  1. Open your website → press F12 → go to the Console tab
  2. Look for red error messages that appear before any [DAP] log entries
  3. An uncaught error in a script that runs before the SDK init call will halt JavaScript execution

How to fix:

  1. Fix the unrelated JavaScript error first — the error message and stack trace in the console will point to the source
  2. Alternatively, move the SDK snippet to a separate <script> tag so other script errors don't block it:
    <!-- Isolated — errors in other scripts won't affect this -->
    <script src="https://cdn.breakground.io/sdk.js"></script>
    <script>
    DAP("init", { tenantKey: "wfx_...", baseUrl: "..." });
    </script>

SDK loaded asynchronously with early init call

How to diagnose:

  1. Check your page source — if the SDK <script> tag has async or defer, and the DAP('init') call is in a separate inline <script> above or alongside it, the init call may run before the SDK loads
  2. In the Console, look for DAP is not defined or DAP is not a function

How to fix:

Use the command queue pattern (see the "Script tag placement" fix above) — this ensures init calls are buffered and replayed after the SDK loads.

Init timeout too low

How to diagnose:

  1. Enable debug mode by adding debug: true to your init config
  2. Look in the Console for a message like: SDK init timed out
  3. Check the Network tab — is the /api/sdk/config request taking longer than your initTimeoutMs value?

How to fix:

Either remove the custom initTimeoutMs (the default is 10 seconds, which is sufficient for most networks) or increase it:

DAP("init", {
tenantKey: "wfx_...",
baseUrl: "...",
initTimeoutMs: 15000, // 15 seconds
});

If the config request consistently takes more than 10 seconds, the issue is likely network latency to the API — consider whether a CDN or regional endpoint is available.


"Events not flowing" — Step 3 fails

The SDK initialized successfully, but no behavioral events (page views, clicks) are being received.

Domain mismatch (most common)

If your API key is bound to a specific site, the SDK must be loaded from a matching domain.

How to diagnose:

  1. Open your website → press F12 → go to the Network tab
  2. Filter by /api/sdk/events
  3. If you see 401 responses, click the request → go to the Response tab
  4. Look for the error code AUTH_ORIGIN_MISMATCH

How to fix:

  1. Go to your Break Ground dashboard → Settings > Sites
  2. Find the site linked to your API key
  3. Check the Domain field — it must match your website's domain exactly:
    • Your site is www.example.com → domain must be www.example.com, not example.com
    • Your site is app.example.com → domain must be app.example.com
  4. If you need both example.com and www.example.com to work, enable the Allow Subdomains toggle for that site
  5. Alternatively, go to Settings > API Keys and use a tenant-wide API key (not bound to any specific site)

API key revoked or expired

How to diagnose:

  1. Open your website → press F12 → go to the Network tab
  2. Filter by /api/sdk/ — if all requests return 401, the API key is invalid

How to fix:

  1. Go to your Break Ground dashboard → Settings > API Keys
  2. Check if the key listed in your snippet is still in the table and shows Active status
  3. If the key is missing or revoked, create a new API key:
    • Click Create API Key
    • Optionally bind it to a site
    • Copy the new key (you won't be able to see it again)
    • Update your snippet's tenantKey with the new key
  4. Redeploy your site

Tenant account inactive

How to diagnose:

  1. Check the Network tab for 401 responses with error code AUTH_TENANT_INACTIVE
  2. Try logging into the Break Ground dashboard — you may see a suspension notice

How to fix:

Contact Break Ground support or check your billing status. Account suspension is typically caused by an expired subscription or a billing issue. Once the account is reactivated, the SDK will resume sending events automatically — no code changes needed.

Rate limited

How to diagnose:

  1. Open the Network tab and filter by /api/sdk/events
  2. If you see 429 status codes, you're being rate limited (600 requests/minute per tenant)

How to fix:

This typically only happens during initial rollout on high-traffic sites. The SDK automatically retries with exponential backoff. To reduce request volume:

  1. Check if you have the SDK installed on multiple high-traffic pages — consider a phased rollout
  2. If you're sending custom events at high frequency, batch them or reduce frequency
  3. Contact Break Ground support to discuss a rate limit increase if your traffic legitimately needs it

Plan limits reached

How to diagnose:

  1. Go to your Break Ground dashboard → Settings > Plan
  2. Check your Monthly Active Users (MAU) usage — if you're at 100%, new events are rejected
  3. Check if specific features (custom events, auto-tracking) show as unavailable on your plan

How to fix:

  1. Upgrade your plan in Settings > Plan to increase your MAU limit
  2. Or, if you're in a trial period, contact sales to extend the trial
  3. Events will start flowing again immediately once the limit is raised — no code changes needed

Auto-tracking disabled

How to diagnose:

  1. Check your SDK init config — if autoTrack is set to false, the SDK only sends SDK_INIT and won't automatically capture page views or clicks
  2. In the Console with debug: true, you won't see auto-track event logs

How to fix:

Either remove autoTrack: false from your config (auto-tracking is enabled by default) or explicitly set it to true:

DAP("init", {
tenantKey: "wfx_...",
baseUrl: "...",
autoTrack: true, // default — remove autoTrack: false if present
});

If you intentionally disabled auto-tracking, you need to send events manually for Step 3 to pass:

DAP("track", "my_custom_event", { key: "value" });

How to diagnose:

This is most common on single-page sites where the user clicks a link immediately after the page loads. The SDK batches events and flushes them periodically — if the user navigates away before the first flush, events are lost.

How to fix:

  1. This usually resolves itself — the verification will pass once a user stays on a page long enough for the batch to flush (a few seconds)
  2. For testing, stay on the page for at least 5 seconds after it loads, then navigate
  3. If you're running a single-page app (SPA), this is less of an issue since navigation doesn't cause a full page unload

Verification timed out (after 2 minutes)

The dashboard polls the installation status every 5 seconds for up to 2 minutes.

Caching delay

The status endpoint caches results for 10 seconds. If you just deployed the SDK, events may not appear immediately.

How to fix: Click Check Again in the verification panel. Each click starts a fresh 2-minute polling cycle.

Event processing delay

Events are processed asynchronously through a background worker queue. Under heavy load, there can be a delay between the SDK sending events and them appearing in verification.

How to fix:

  1. Wait 30 seconds after your page loads, then click Check Again
  2. If it still times out after multiple attempts, the issue is likely one of the problems described in the sections above — follow the debugging checklist at the bottom of this page

Browser tab backgrounded

Some browsers throttle network requests and timers for background tabs. If you switch away from the dashboard tab during verification, polling may be delayed.

How to fix: Keep the dashboard tab in the foreground during the 2-minute verification check. Open your website in a separate browser window (not just a new tab) so both are visible.


Works locally but not in production

Localhost bypass

The API always allows requests from localhost (localhost, 127.0.0.1, *.localhost) regardless of the site domain configured on the API key. This means verification passes in local development even if the domain is wrong.

How to fix:

  1. Go to Settings > Sites and verify the domain matches your production URL exactly
  2. Common mistakes:
    Site domain set toProduction URLResult
    example.comwww.example.comFails (enable Allow Subdomains)
    staging.example.comapp.example.comFails (wrong domain)
    localhost:3000app.example.comFails (localhost only)
  3. Enable Allow Subdomains if you serve from multiple subdomains

Different CSP policies

Your local dev server typically has no Content Security Policy, while production may enforce strict rules.

How to fix:

  1. Check your production site's CSP by opening DevTools → Console and looking for CSP violation errors
  2. Add the required domains to your CSP (see the "CSP blocking" section above):
    script-src 'self' https://cdn.breakground.io;
    connect-src 'self' https://api.yourapp.com;
  3. To test CSP locally before deploying, add a CSP meta tag to your local HTML:
    <meta
    http-equiv="Content-Security-Policy"
    content="script-src 'self' https://cdn.breakground.io; connect-src 'self' https://api.yourapp.com;"
    />

CDN or reverse proxy stripping headers

The API uses the Origin and Referer headers for domain validation. Some CDNs (Cloudflare, AWS CloudFront) or reverse proxies (nginx, Traefik) strip these headers.

How to fix:

  1. Check if your CDN/proxy is stripping the Origin header:
    # From your production server, make a request that mimics the browser
    curl -H "Origin: https://www.example.com" -H "X-API-Key: wfx_..." \
    https://your-api-domain/api/sdk/config -v 2>&1 | grep -i "origin"
  2. Configure your CDN/proxy to forward the Origin header:
    • Cloudflare: Origin is forwarded by default — no action needed
    • AWS CloudFront: Add Origin to the cache policy's allowed headers
    • nginx: Add proxy_set_header Origin $http_origin; to your proxy config
    • Vercel/Netlify: These forward headers by default — no action needed

Firewall or WAF blocking API requests

How to diagnose:

  1. Open DevTools → Network tab on your production site
  2. Filter by /api/sdk/ — look for blocked or failed requests
  3. If requests aren't even appearing, the WAF may be blocking them before they leave the browser

How to fix:

  1. Allowlist the Break Ground API domain in your WAF/firewall rules:
    • Outbound HTTPS (port 443) to your API domain (e.g., api.breakground.io)
  2. If using a corporate proxy, ensure it doesn't block or modify requests to the API domain
  3. Test from behind the same network as your users:
    curl -H "X-API-Key: wfx_..." https://your-api-domain/api/sdk/config
    If this times out or returns an unexpected response, the network is blocking it

General debugging checklist

Follow these steps in order. Most issues are caught by steps 1–3.

Step 1: Enable debug mode

Add debug: true to your SDK config — this logs every SDK action to the browser console:

DAP("init", { tenantKey: "wfx_...", baseUrl: "...", debug: true });

Step 2: Check the Network tab

Open your website → press F12 → go to the Network tab → filter by /api/sdk/:

StatusMeaningFix
No requests at allSDK script didn't load or init wasn't calledSee "Script not loaded" and "SDK not initialized" sections
401Invalid API key, revoked key, or domain mismatchCheck the response body for the specific error code
429Rate limited (>600 req/min)Reduce traffic or contact support
(failed) / network errorAPI endpoint unreachableCheck DNS, firewall, and API status
CORS error in ConsoleCSP or CORS misconfigurationSee "CSP blocking" section
200Working correctlyWait for verification to catch up (caching delay)

Step 3: Check the Console tab

Look for:

  • [DAP] prefixed messages (SDK debug logs) — these show what the SDK is doing
  • Red CSP violation errors — these tell you exactly which resource was blocked and which directive to update
  • DAP is not defined — the SDK script didn't load

Step 4: Verify your API key

  1. Go to dashboard → Settings > API Keys
  2. Confirm the key in your snippet appears in the list and shows Active
  3. Check the Site column — if it's bound to a site, verify the domain matches

Step 5: Verify your site domain

  1. Go to dashboard → Settings > Sites
  2. Confirm the domain matches your production URL (including www. if applicable)
  3. Toggle Allow Subdomains if you serve from multiple subdomains

Step 6: Test API connectivity directly

Run this from your terminal (replace the values):

curl -H "X-API-Key: wfx_your_key_here" https://your-api-domain/api/sdk/config
ResultMeaning
JSON response with tenant configAPI key and endpoint are working — issue is browser-side (CSP, ad-blocker, script loading)
{"error": "Unauthorized", "code": "AUTH_INVALID_API_KEY"}API key is wrong or revoked
{"error": "Unauthorized", "code": "AUTH_ORIGIN_MISMATCH"}This won't happen in curl (no Origin header) — but confirms the key exists
{"error": "Unauthorized", "code": "AUTH_TENANT_INACTIVE"}Account suspended — contact support or check billing
Connection timeout / DNS errorAPI domain is wrong or blocked by your network

Step 7: Check your plan limits

Go to dashboard → Settings > Plan and verify your MAU usage is below the limit.