> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glood.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Security Policy Setup

> Configure CSP to enable Glood pixel tracking and event transmission

# Content Security Policy Setup

Hydrogen ships with a strict Content Security Policy. Without whitelisting Glood's domains, the browser blocks both recommendation fetches and pixel events with CSP violations. This page shows the required configuration.

## Required CSP Configuration

Add the Glood domains to the `connectSrc` directive in your `app/entry.server` file. Hydrogen **merges** your entries with its defaults, so localhost/HMR entries are preserved in development:

```javascript theme={null}
// app/entry.server.tsx (or .jsx)
const {nonce, header, NonceProvider} = createContentSecurityPolicy({
  shop: {
    checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
    storeDomain: context.env.PUBLIC_STORE_DOMAIN,
  },
  connectSrc: [
    "'self'",
    'https://storefront.glood.ai', // v3 headless suite (init, sections, events, recommendations)
  ],
});
```

## Glood Domains Explained

### Required Endpoints

| Domain                        | Purpose                                                                                                                                                  | Used By             |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `https://storefront.glood.ai` | v3 headless suite — session init, recommendation sections (`useRecommendations`, `fetchRecommendationSections`), recommendations, and event transmission | Recommendations app |

<Note>
  `https://events.glood.ai` is **no longer used**. As of v3, events go to the versioned events API on the main host (`POST https://storefront.glood.ai/api/storefront/v3/headless/events`). For a `version: 2` client, events go to `POST https://storefront.glood.ai/api/storefront/event` — still on the main host. The single `storefront.glood.ai` entry covers all cases.
</Note>

### Why This Domain Is Needed

* **Session Init**: On load, v3 clients bootstrap a session via `POST /api/storefront/v3/headless/init`
* **Recommendation Fetches**: Sections and recommendations are fetched via `fetch()` API calls
* **Event Transmission**: The SDK sends analytics and attribution events via `fetch()` to the versioned events API
* **Privacy Compliance**: Events are only sent when customer consent is granted
* **Personalization**: Allows Glood to provide personalized recommendations

## Implementation in Hydrogen

Add the CSP configuration to your root layout file:

```typescript theme={null}
// app/root.tsx
import {
  json,
  type LoaderFunctionArgs,
} from '@shopify/remix-oxygen';
import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
  useLoaderData,
} from '@remix-run/react';
import {
  Analytics,
  getShopAnalytics,
  useNonce,
} from '@shopify/hydrogen';
import { createContentSecurityPolicy } from '@shopify/hydrogen';

export async function loader({context}: LoaderFunctionArgs) {
  const {nonce, header, NonceProvider} = createContentSecurityPolicy({
    shop: {
      checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
      storeDomain: context.env.PUBLIC_STORE_DOMAIN,
    },
    connectSrc: [
      "'self'",
      'https://storefront.glood.ai',     // v3 headless suite (init, sections, events, recommendations)
    ],
  });

  return json({
    nonce,
    header,
    // ... other loader data
  });
}

export default function App() {
  const nonce = useNonce();
  const data = useLoaderData<typeof loader>();

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <Analytics>
          <GloodProvider client={glood} loaderData={data}>
            <Layout>
              <Outlet />
            </Layout>
          </GloodProvider>
        </Analytics>
        <ScrollRestoration nonce={nonce} />
        <Scripts nonce={nonce} />
      </body>
    </html>
  );
}

export function headers({loaderHeaders}: {loaderHeaders: Headers}) {
  return {
    'Content-Security-Policy': loaderHeaders.get('Content-Security-Policy'),
  };
}
```

If you use a non-default recommendations `endpoint`, add that host to `connectSrc` instead of (or alongside) `storefront.glood.ai`.

## Troubleshooting

CSP violations show up in the browser console:

```
Content Security Policy: The page's settings blocked the loading of a resource at https://storefront.glood.ai/
```

If you see this, the Glood host is missing from `connectSrc` — add `'https://storefront.glood.ai'` (or your custom endpoint). With `debug: true` on the client, successful transmission logs the target URL, so you can confirm the request reaches the network rather than being blocked.

## See Also

* [Event System](/for-developers/glood-hydrogen-sdk/api-reference/event-system) - How events are transmitted
* [Configuration](/for-developers/glood-hydrogen-sdk/configuration) - Endpoint and pixel settings
* [Installation Guide](/for-developers/glood-hydrogen-sdk/installation) - Complete setup instructions
* [Hydrogen CSP Documentation](https://shopify.dev/docs/custom-storefronts/hydrogen/deployment/content-security-policy) - Official Shopify CSP guide
