Seatext library

How to Troubleshoot SeaText Not Loading in Your Vue.js App

SeaText fails to load in Vue.js apps most often because the snippet runs before the DOM is ready, the project ID is invalid, CSP headers block the script, or local storage is restricted. Start...

SeaText not appearing in your Vue.js application usually comes down to a handful of predictable causes. The snippet loads asynchronously and relies on local storage, so anything that blocks script execution, prevents storage access, or runs the initialization too early will stop the widget from appearing. This article walks through a diagnostic sequence you can follow in order, explains what each symptom means, and shows the fix for each root cause.

How SeaText Loads in a Vue.js Single-Page Application

SeaText delivers its functionality through a JavaScript snippet you place in your application's entry point. For Vue.js apps, that entry point is typically index.html or the main JavaScript/TypeScript file where Vue mounts the application. The snippet includes the async attribute, so the browser downloads it without blocking page render. Once downloaded, the script writes an identifier into the browser's local storage and begins rewriting page elements based on your project configuration.

Because Vue.js controls the DOM after mount, the snippet must be present before Vue takes over. If you inject the snippet inside a component lifecycle hook instead of the static HTML, the script may load after SeaText has already tried to initialize, resulting in a silent failure.

Diagnostic Sequence: Check These in Order

  1. Open the browser console (F12 → Console). Look for 401 or 403 responses from SeaText endpoints. A 401/403 almost always means the project ID in your snippet is wrong or the project has been disabled in the dashboard.
  2. Switch to the Network tab. Filter for "seatext" or the script domain. Confirm the script request returns 200 and the response body contains JavaScript, not an HTML error page. If the request is blocked, you will see "blocked:csp" or "blocked:mixed-content" in the status column.
  3. Verify local storage access. In the Console, run localStorage.setItem('test','1'). If it throws a SecurityError or QuotaExceededError, SeaText cannot store its identifier and will not initialize.
  4. Check initialization timing. Add a temporary console.log('SeaText snippet reached') right after the snippet in your index.html. Reload and confirm the log appears before any Vue mount messages.
  5. Inspect CSP headers. In the Network tab, click the main document request and check the Content-Security-Policy response header. The policy must allow script-src for the SeaText domain and connect-src for its API endpoints.

Common Error Patterns and What They Mean

SymptomLikely CauseFix
Console shows 401/403 from SeaText APIInvalid or revoked project IDCopy the snippet again from the SeaText dashboard and replace the entire script block in index.html
Script request shows "blocked:csp"Content-Security-Policy header missing SeaText domainAdd the SeaText script domain to script-src and API domain to connect-src in your CSP
Script loads but no SeaText object on windowInitialization ran before DOM ready or local storage blockedMove snippet to index.html <body>; ensure local storage works in private/incognito mode
Works in dev, fails in production buildBuild process strips or minifies the snippet incorrectlyVerify the snippet survives npm run build by checking dist/index.html
Widget appears on first load but not after route changeVue router navigation does not re-run the snippetCall SeaText re-initialization method in a global navigation guard (see Vue.js specific section)

Step-by-Step Troubleshooting Checklist

  1. Confirm the snippet is in index.html. Open public/index.html (or your framework's equivalent) and verify the SeaText script tag sits inside the <body> tag, not in <head> and not inside a Vue component template.
  2. Run the dev server and open DevTools. Execute the diagnostic sequence above. Stop at the first failing check and apply the corresponding fix.
  3. Test in an incognito window. This rules out browser extensions that block scripts or local storage.
  4. Build for production and serve the dist folder. Run npm run build then npx serve dist (or your static host). Repeat the diagnostic sequence. Build tools sometimes rewrite or remove script tags they don't recognize.
  5. Verify Vue router integration. If SeaText loads on the initial page but disappears after navigation, add a global afterEach guard in router/index.js that calls the SeaText refresh method documented in your dashboard.
  6. Check cross-origin setup. If your Vue app serves from app.example.com but the SeaText snippet points to a different domain, ensure the script response includes Access-Control-Allow-Origin headers that include your origin.

Vue.js Specific Integration Pitfalls

The SeaText documentation for SPAs notes that Vue.js requires the snippet in the static entry HTML, not inside a .vue file. A common mistake is adding the snippet in App.vue mounted() hook. By the time that hook runs, SeaText's initialization window has passed.

Another Vue-specific issue arises with vue-cli or Vite when the index.html template uses HTML plugin injection. If you place the snippet in the template but the build process moves it to <head> or wraps it in a module script, the async attribute may be dropped, changing load timing. Always inspect the built dist/index.html to confirm the snippet remains intact.

For applications using Vue 3's createApp with delayed mount (e.g., waiting for auth), place the snippet before the mount call in main.ts or keep it in index.html and ensure the mount does not replace the entire <body> content.

Content Security Policy and Network Restrictions

Modern Vue deployments often ship with strict CSP headers. SeaText needs two permissions: script-src to load its JavaScript and connect-src to call its API for variants and tracking. A minimal CSP addition looks like:

Content-Security-Policy: script-src 'self' https://cdn.seatext.com; connect-src 'self' https://api.seatext.com

If you use a nonce-based CSP, add the nonce to the SeaText script tag: <script nonce="{{nonce}}" async src="..."></script>. Without the nonce, the browser will refuse to execute the script even if the domain is allowed.

Corporate networks and some ad-blockers also block domains that look like tracking scripts. If the Network tab shows "blocked:client" or the request never fires, test on a personal hotspot or disable extensions temporarily to isolate the cause.

Local Storage and Cross-Origin Considerations

SeaText stores a visitor identifier in local storage. This fails in three scenarios:

  • Private/incognito mode in Safari: Safari blocks all local storage in private browsing. SeaText cannot initialize. There is no workaround; the widget simply will not load for those visitors.
  • Cookie/storage blocking extensions: Extensions like uBlock Origin or Privacy Badger may clear or deny local storage writes. The console will show a SecurityError when SeaText attempts localStorage.setItem.
  • Cross-origin iframe embedding: If your Vue app runs inside an iframe on a different domain, the browser treats local storage as third-party and may block it depending on the parent page's permissions policy.

To test, open the Console and run try { localStorage.setItem('st_test','1'); console.log('OK'); } catch(e) { console.error(e); }. If it logs an error, SeaText will not work until storage is allowed.

When to Contact SeaText Support

Escalate to support when:

  • The script loads (200 OK), CSP allows it, local storage works, initialization timing is correct, but no SeaText object appears on window.
  • You see a 5xx error from SeaText API endpoints.
  • The widget loads but shows no variants despite active campaigns in the dashboard.
  • You need help configuring the Vue router re-initialization call.

Before contacting support, capture a HAR file (Network tab → right-click → Save as HAR) and note the exact Vue version, build tool (Vite, vue-cli, Nuxt), and whether you use SSR.

Key Facts

FactDetails
Snippet load methodAsync script tag placed in index.html <body>
Storage requirementWrites visitor ID to local storage; fails if blocked
Vue.js entry pointStatic index.html or main JS/TS file before Vue mount
CSP requirementsscript-src for CDN domain; connect-src for API domain
Router navigationRequires manual re-initialization in global afterEach guard
Private browsingSafari blocks local storage → SeaText will not load

Frequently Asked Questions

Why does SeaText work in development but not after npm run build?

Build tools may move the script tag to <head>, strip the async attribute, or treat the snippet as a module. Always open dist/index.html and verify the snippet is unchanged and inside <body>.

Do I need to re-initialize SeaText on every Vue route change?

Yes. SeaText initializes once on page load. Vue router navigation swaps components without a full reload, so SeaText does not automatically re-scan the new DOM. Call the refresh method in a router afterEach guard.

Can I put the snippet in a Vue component instead of index.html?

Not reliably. Component-mounted scripts run after Vue takes over the DOM, missing SeaText's initialization window. The documentation explicitly recommends the static entry HTML.

What CSP directives does SeaText need?

script-src for the script CDN (e.g., https://cdn.seatext.com) and connect-src for the API endpoint (e.g., https://api.seatext.com). Add nonces if your policy requires them.

Does SeaText work in Safari private browsing?

No. Safari blocks all local storage in private mode. SeaText cannot store its visitor ID and will not initialize. This is a browser limitation, not a SeaText bug.

How do I verify the project ID in my snippet is correct?

Open the SeaText dashboard, go to Installation, copy the snippet, and compare the project ID parameter with the one in your index.html. A mismatch causes 401/403 errors visible in the console.

What if my Vue app uses server-side rendering (Nuxt)?

For Nuxt, add the snippet in app.html or use the head script configuration with body: true so it renders in the body of the server-generated HTML. Ensure the script is not bundled by the SSR process.

Further reading and comparison sources

These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.

Learn more

Visit the website for more information.