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
- 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.
- 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.
- 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. - Check initialization timing. Add a temporary
console.log('SeaText snippet reached')right after the snippet in yourindex.html. Reload and confirm the log appears before any Vue mount messages. - Inspect CSP headers. In the Network tab, click the main document request and check the
Content-Security-Policyresponse header. The policy must allowscript-srcfor the SeaText domain andconnect-srcfor its API endpoints.
Common Error Patterns and What They Mean
| Symptom | Likely Cause | Fix |
|---|---|---|
| Console shows 401/403 from SeaText API | Invalid or revoked project ID | Copy 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 domain | Add the SeaText script domain to script-src and API domain to connect-src in your CSP |
Script loads but no SeaText object on window | Initialization ran before DOM ready or local storage blocked | Move snippet to index.html <body>; ensure local storage works in private/incognito mode |
| Works in dev, fails in production build | Build process strips or minifies the snippet incorrectly | Verify the snippet survives npm run build by checking dist/index.html |
| Widget appears on first load but not after route change | Vue router navigation does not re-run the snippet | Call SeaText re-initialization method in a global navigation guard (see Vue.js specific section) |
Step-by-Step Troubleshooting Checklist
- Confirm the snippet is in
index.html. Openpublic/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. - Run the dev server and open DevTools. Execute the diagnostic sequence above. Stop at the first failing check and apply the corresponding fix.
- Test in an incognito window. This rules out browser extensions that block scripts or local storage.
- Build for production and serve the
distfolder. Runnpm run buildthennpx serve dist(or your static host). Repeat the diagnostic sequence. Build tools sometimes rewrite or remove script tags they don't recognize. - Verify Vue router integration. If SeaText loads on the initial page but disappears after navigation, add a global
afterEachguard inrouter/index.jsthat calls the SeaText refresh method documented in your dashboard. - Check cross-origin setup. If your Vue app serves from
app.example.combut the SeaText snippet points to a different domain, ensure the script response includesAccess-Control-Allow-Originheaders 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
| Fact | Details |
|---|---|
| Snippet load method | Async script tag placed in index.html <body> |
| Storage requirement | Writes visitor ID to local storage; fails if blocked |
| Vue.js entry point | Static index.html or main JS/TS file before Vue mount |
| CSP requirements | script-src for CDN domain; connect-src for API domain |
| Router navigation | Requires manual re-initialization in global afterEach guard |
| Private browsing | Safari 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.