Why your widget isn't appearing: allowed origins
If you installed the DeskCrew snippet but the widget won't work. Messages won't send, the Help/Updates/Feedback tabs and your logo never load, or an embedded portal is blank. The cause is almost always Allowed origins. DeskCrew only lets your widget talk to your workspace from web addresses you've explicitly added to the allowlist on the Install page, and the match has to be exact. Add the precise origin of the page you're testing (the https://… part of your address bar) and it starts working immediately. This article explains what an origin is, why the match is strict, and how to confirm the fix.
The 30-second fix
Go to Install → Allowed origins, type the exact scheme + domain of your live site into the box (for example https://yoursite.com), and click Add origin. If you're also testing locally, add http://localhost:3000 (matching your dev port). Then hard-refresh your site. In the large majority of cases, that's the entire fix.
If you're not sure what to type, open the page where the widget lives, look at the browser address bar, and copy everything up to (but not including) the first single / after the domain. That's your origin. Paste that.
What an "origin" is
An origin is the combination of three things from a URL: the scheme (http or https), the host (the domain, like example.com), and the port (usually hidden). It is not the full page URL. The path and query string are ignored. DeskCrew uses the origin as the identity of a website, and it must match one of your allowlisted entries exactly.
Take the URL https://shop.example.com/pricing?ref=x. Its origin is https://shop.example.com. The /pricing?ref=x part is irrelevant to the allowlist. So you add the domain once and every page under it is covered.
DeskCrew normalizes what you enter (lowercases the host, strips a trailing slash, drops the default port), so https://Example.com/ and https://example.com are treated as the same. But it does not guess between different schemes, subdomains, or ports. Those are genuinely different origins and each must be added on its own.
Why the match must be exact
DeskCrew checks the browser-reported origin of every widget request against your allowlist and rejects anything that isn't a character-for-character match (after normalization). This is a deliberate security control: it stops other websites from embedding your widget, opening tickets in your name, or scraping your board. The trade-off is that near-misses are treated as strangers.
These are all different origins, and adding one does not cover the others:
| You added | These will still be blocked |
|---|---|
https://example.com | https://www.example.com (different host) |
https://example.com | http://example.com (different scheme) |
https://example.com | https://app.example.com (different subdomain) |
https://example.com | http://localhost:3000 (local dev) |
http://localhost:3000 | http://localhost:5173 (different port) |
Only http:// and https:// origins are accepted. If you paste something that isn't a valid origin, the page shows: "Invalid origin: must be a valid http or https origin (e.g. https://example.com)."
www vs non-www. A very common trap
https://example.com and https://www.example.com are two different origins, and visitors can land on either one depending on how your site is configured. If you only added the non-www version but a customer visits the www version, the widget breaks for them. The safe move is to add both.
To be thorough, add every hostname your site actually serves pages on:
https://example.comhttps://www.example.com- any subdomains that embed the widget, e.g:
https://app.example.com,https://help.example.com
Adding an origin you don't use causes no harm, so err on the side of listing all of them.
Add your local development address too
While you're testing the widget on your own machine before going live, your pages are served from something like http://localhost:3000. Which is a completely separate origin from your production domain. If it isn't on the allowlist, the widget won't work during development, even though the exact same snippet will work in production.
Add your dev origin explicitly, matching the port your dev server prints when it starts:
http://localhost:3000(Next.js, Create React App default)http://localhost:5173(Vite)http://localhost:8080,http://127.0.0.1:3000, etc. whatever your tooling uses
Note that localhost and 127.0.0.1 are also different origins, so add whichever one you actually load in the browser.
What "blocked" actually looks like
When a page's origin isn't allowlisted, the failure is quiet by design (DeskCrew returns a generic "forbidden" so it can't be used to probe your account). Different parts of the widget fail in different ways, which is why the symptom is often described as "it's not showing" even when the bubble is visible.
- Floating chat widget: the launcher bubble usually still appears, because the loader script itself is public. But when you try to send a message you get "Couldn't send. Please check your connection," and the extra tabs (Help, Updates, Feedback) and your workspace name/logo never load. The header keeps showing the generic default. That combination is the tell-tale sign of an origin problem.
- Embedded portal (
DeskCrew.embed): the iframe stays blank or never finishes loading, because the portal only accepts a connection from an allowlisted parent page. - Changelog / What's-new widget: entries don't load.
If your list is completely empty, the Install page warns you outright: "No origins added yet. The widget will be blocked everywhere."
Confirm it with browser DevTools
To confirm an origin problem for certain, open your browser's developer tools and look at the Console and Network tabs while the widget tries to load. A blocked request shows up as a CORS error or a 403. This turns a vague "it's not working" into a precise, fixable answer.
- Open the page with the widget, then press F12 (or right-click → Inspect) to open DevTools.
- Go to the Console tab and reload the page. A CORS block looks like:
Access to fetch at
'https://deskcrew.io/api/widget/config?..'from origin'https://www.example.com'has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. The origin quoted in that message:https://www.example.comin the example. Is the exact string you need to add to Allowed origins. Copy it verbatim. - Go to the Network tab, filter for
widget, and reload. Requests to/api/widget/config,/api/widget/submit, etc. returning 403 (forbidden) confirm the origin isn't allowlisted. - Add that exact origin on the Install page, click Add origin, then hard-refresh (Ctrl/Cmd + Shift + R) and retry. The CORS errors should disappear and the request should return 200.
The golden rule: whatever origin the browser reports in the CORS error is exactly what you paste into Allowed origins: same scheme, same host, same port, no path.
Still not working after adding the origin?
If the origin is correct but the widget still misbehaves, check these:
- Typo or wrong scheme: re-read the entry;
httpvshttpsandwwwvs non-wwware the usual culprits. - You added a full URL, not an origin: remove any path (
/feedback,/page); the entry should end at the domain (or port). - You just rotated your widget key: old snippets die when the key rotates. Re-copy the current snippet from the Install page and re-paste it on your site.
- Cached page: hard-refresh, or test in a private/incognito window so you're not seeing an old cached version of the page without the fix.
- Embedded portal only: also confirm
basePathmatches the route the page is served on (see "Embed the feedback board + a What's-new widget in your site").
