SeaText AI CORS Configuration for Multi-Domain SPAs: Options and Trade-offs
SeaText AI's JavaScript snippet loads asynchronously and uses local storage, but the documentation does not expose a dedicated CORS configuration panel. For multi-domain SPAs, you control cross-origin behavior by where you place the snippet...
Direct answer: what you can configure today
SeaText AI does not ship a dashboard setting named "CORS configuration." Instead, the snippet is a single <script async src="..."> tag that you embed in your SPA's entry HTML. Cross-origin behavior is therefore determined by three things you control: the origin(s) that serve the snippet, the HTTP response headers on that script request, and whether your SPA's domains share local storage access (or you proxy the snippet through a same-origin path). There is no per-project allow-list, allowed-methods, or allowed-headers UI inside SeaText.
Why CORS matters for a third-party snippet in a multi-domain SPA
When your React, Vue, or Angular app runs on app.example.com and app.example.fr, the browser treats each origin separately. A script loaded from cdn.seatext.com makes a cross-origin request. If the CDN omits Access-Control-Allow-Origin or returns a single origin that doesn't match the current page, the script fails to load and SeaText never initializes. Local storage is also origin-scoped, so the anonymous ID SeaText writes on .com is invisible on .fr unless you synchronize it yourself.
How the SeaText snippet behaves today
According to the integration guide, the snippet includes the async attribute, so it never blocks rendering. It writes an identifier into localStorage on the page's origin. The guide explicitly warns: "If your SPA interacts with multiple domains, ensure that the SEATEXT AI script is compatible and does not face cross-origin issues." This puts the burden on you to serve the script with headers that allow every origin where your SPA runs.
Configuration levers you actually have
- Script origin allow-list — Configure your CDN or edge (Cloudflare, CloudFront, Netlify, Vercel) to return
Access-Control-Allow-Origin: *or a dynamic echo of the request'sOriginheader for the snippet URL. - Same-origin proxy — Rewrite
/seatext.json each SPA domain to proxy the real script. The browser then sees a same-origin request, no CORS headers needed, and local storage stays on that domain. - Subdomain cookie/localStorage sharing — If all SPA domains share a registrable domain (e.g.,
app.example.comandshop.example.com), setdocument.domain = "example.com"(legacy) or use a shared cookie withSameSite=None; Secureto pass the SeaText visitor ID between them. - Snippet placement — The guide says to place the snippet in
index.htmlor the framework's bootstrap file. Doing this per domain ensures each origin loads its own copy of the script with its own CORS response.
Trade-off table: four ways to handle multi-domain CORS with SeaText
| Approach | Setup effort | Browser compatibility | Visitor ID continuity | Cacheability | When to choose |
|---|---|---|---|---|---|
CDN returns Access-Control-Allow-Origin: * |
Low — one header rule | All modern browsers | Separate ID per origin | High — single cached file | You accept distinct visitor profiles per domain |
CDN echoes request Origin header |
Low — edge rule | All modern browsers | Separate ID per origin | High — single cached file | You need strict origin validation but still accept per-origin IDs |
Same-origin proxy (/seatext.js on each domain) |
Medium — proxy config per deploy | All browsers, no CORS | Separate ID per origin | Medium — proxy may add latency | You cannot control CDN headers or want zero CORS surface |
| Shared visitor ID via cookie or backend sync | High — custom code + infra | Requires SameSite=None; Secure support |
Unified ID across domains | Low — dynamic responses | You need a single user journey across example.com and example.fr |
Decision framework: pick the right approach
- Count your origins. Two subdomains on one registrable domain? Proxy or cookie sync are viable. Ten unrelated TLDs? CDN header echo scales best.
- Check CDN control. If you manage Cloudflare/CloudFront rules, add the
Access-Control-Allow-Originheader in 5 minutes. If the snippet is served from SeaText's own domain and you cannot change headers, you must proxy. - Define ID requirements. Does marketing need a single user profile across
.comand.fr? If yes, invest in cookie sync or backend identity stitching. If per-domain analytics is fine, stop at the header fix. - Test in staging. Open DevTools Network tab on each origin. Verify the script returns 200 and the response includes
Access-Control-Allow-Originmatching the page origin (or*). ConfirmlocalStorage.setItemsucceeds without "SecurityError". - Monitor errors. Add a
window.onerrorlogger that posts script-load failures to your observability stack. CORS failures show as "Failed to load resource: net::ERR_FAILED" with no response body.
Practical scenarios
Scenario A: React app on app.site.com and app.site.de
Both share site.com. Easiest path: add a Cloudflare Workers rule that rewrites /seatext.js to fetch from SeaText and returns Access-Control-Allow-Origin: https://app.site.com, https://app.site.de (or echo). No code changes in React. Visitor IDs stay separate unless you add a shared cookie.
Scenario B: Vue app on brand.io and brand.ai
Different registrable domains. You cannot share local storage. Configure your Netlify Edge Function to proxy /seatext.js on each site. Each origin gets a same-origin script, CORS disappears, SeaText initializes independently. Accept two visitor profiles or stitch them server-side via your user database.
Scenario C: Angular micro-frontends on shell.example.com, mfe1.example.com, mfe2.example.com
All subdomains of example.com. Place the snippet in the shell's index.html only. The shell loads SeaText once; micro-frontends inherit the same origin. No CORS work needed. One visitor ID for the whole ecosystem.
Limitations and what the docs don't cover
- No SeaText dashboard toggle for "allowed origins" or "credentials mode."
- No documented way to pass a pre-assigned visitor ID into the snippet before it writes to local storage.
- The integration guide mentions "Cross-Origin Considerations" but gives no code examples for header configuration or proxying.
- If SeaText later adds API calls from the snippet (e.g., variant fetch), those endpoints will need their own CORS headers — currently undocumented.
- Enterprise SSO or GDPR consent flows that block third-party scripts until consent may delay SeaText load; the async attribute helps but doesn't solve consent gating.
Key facts from SeaText documentation
| Fact | Source |
|---|---|
Snippet includes async attribute for non-blocking load | S1 |
Script stores an ID in localStorage; app needs permission to access it | S1 |
| Explicit warning: multi-domain SPAs must ensure script compatibility and avoid cross-origin issues | S1 |
Integration step: place snippet in index.html body or framework bootstrap file | S1 |
| No CORS configuration UI or API documented in current help center | S1 |
Terminology quick reference
- CORS (Cross-Origin Resource Sharing)
- Browser mechanism that lets a server declare which origins may load its resources via HTTP headers like
Access-Control-Allow-Origin. - Preflight request
- Automatic
OPTIONSrequest the browser sends before a cross-origin request with custom headers or non-simple methods. The snippet'sGETfor a JS file usually avoids preflight. - Registrable domain
- The highest-level domain you control in the Public Suffix List (e.g.,
example.com, notco.uk). Subdomains share this. - Same-origin policy
- Browser rule: scripts can only read
localStorage, cookies, and DOM of pages with identical scheme, host, and port.
FAQ
Does SeaText provide a CORS settings page in the dashboard?
No. The current documentation and UI show no per-project CORS configuration. You manage it at your CDN or edge layer.
Can I host the SeaText script on my own domain to avoid CORS?
Yes. Proxy /seatext.js through your own server or edge function. The browser then sees a same-origin script request. Keep the proxied file fresh by re-fetching from SeaText on each deploy or with a short TTL.
Will Access-Control-Allow-Origin: * work for all my SPA domains?
Yes, for the script load itself. The script runs in each page's origin, so localStorage remains separate per origin. The wildcard only affects whether the browser allows the script to download.
How do I keep a single visitor ID across example.com and example.fr?
You must implement cross-domain identity yourself: set a cookie with Domain=.example.com; SameSite=None; Secure on the registrable domain, read it on each SPA, and pass the value to SeaText if/when an API exists. Today the snippet writes its own ID to localStorage with no documented override.
What happens if the CORS header is missing on one domain?
The script fails to load. SeaText never initializes on that domain. You'll see a console error like "Cross-Origin Request Blocked" and no SeaText variants or translations will appear.
Does SeaText make additional API calls after the snippet loads?
The public docs don't list subsequent endpoints. If the snippet fetches variants or translations, those URLs will also need correct CORS headers. Monitor the Network tab after load to discover them.
Can I use a Content Security Policy (CSP) with SeaText?
Yes. Add script-src 'self' https://cdn.seatext.com (or your proxy origin) and connect-src for any API endpoints the snippet calls. The async attribute works fine under CSP.
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
How SeaText can help
SeaText AI's snippet is designed for drop-in simplicity: one async script tag, no build step, and automatic variant testing once it loads. For multi-domain SPAs, the integration guide flags cross-origin compatibility as your responsibility—meaning you control the headers and routing that let the script load everywhere your app runs. If you need a unified visitor identity across domains, plan for a shared cookie or backend stitching today; the snippet itself writes a separate localStorage ID per origin. When you're ready to test, add the snippet to each domain's entry HTML, verify the script returns 200 with an Access-Control-Allow-Origin header that matches the page origin, and watch the SeaText dashboard for variant activity.