The same-origin policy and why CORS exists
The browser enforces a same-origin policy: JavaScript loaded from shop.example.com cannot, by default, read responses from api.personalization.com. It is protection against attacks in which a malicious site could read data from other sites on behalf of a signed-in user.
CORS is the mechanism that lets a server explicitly permit requests from named origins, exempting them from the same-origin policy.
How CORS works
A simple request (a GET with no custom headers):
1. The browser sends the request with the header Origin: https://shop.example.com.
2. The server checks whether that origin is allowed.
3. If it is, it returns Access-Control-Allow-Origin: https://shop.example.com.
4. The browser passes the response through to the JS.
Preflight for complex requests:
OPTIONS /api/recommendations HTTP/1.1
Origin: https://shop.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, X-API-Key
The server has to answer:
Access-Control-Allow-Origin: https://shop.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-API-Key
Access-Control-Max-Age: 86400
CORS during a personalization platform integration
When a JavaScript recommendation widget is connected, the browser calls the personalization API on a different domain. If the server does not return the right CORS headers:
- The browser blocks the response — not the request; the server does receive it
- The console shows
CORS policy: No 'Access-Control-Allow-Origin' header - Recommendations never appear, although everything works server-side
Important: a CORS error is only visible in a browser. Test the API with curl or Postman and everything works, because those tools do not implement the same-origin policy. Check the integration in a real browser with DevTools open.
Common configuration mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| No CORS header | Recommendations do not load | Add Access-Control-Allow-Origin |
| Wildcard plus credentials | Requests carrying cookies are blocked | Name the origin and add Allow-Credentials: true |
| OPTIONS not handled | Preflight returns 404 | Add an OPTIONS handler to the router |
| The wrong domain | A CORS error on a subdomain | Allow *.shop.example.com, or each subdomain individually |