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

# Install the Signals pixel

> Add optional, consent-aware browser measurement to your website.

The Signals pixel collects first-party browser events through your collection domain. PlainRouter gives each signal tracker a unique snippet with its publishable key and collection URL.

<Info>
  The pixel is not required to activate a Signal. Complete [server-side ingestion verification](/docs/signals/verify-ingestion) first, then install the pixel only where your consent policy permits it.
</Info>

## Before you begin

You need:

* A collection domain that shows as active in PlainRouter.
* Access to the shared `<head>` template or site-wide code injection setting for your website.
* Permission to deploy changes to the domain connected to your signal tracker.

If your collection domain is still pending, complete [Configure DNS and CNAME](/docs/signals/configure-dns) first.

## Install the pixel

<Steps>
  <Step title="Copy your snippet">
    Open **Signals**, continue setup, and find **Optional browser confirmation**.

    Click **Copy code**. Use the complete snippet exactly as PlainRouter provides it. Its key and script URL are unique to your signal tracker.
  </Step>

  <Step title="Add it to every page">
    Paste the snippet immediately before the closing `</head>` tag in your site-wide layout.

    Your snippet follows this structure:

    ```html theme={null}
    <script>
      window.signalq = window.signalq || function () {
        (window.signalq.q = window.signalq.q || []).push(arguments);
      };
      signalq("init", { key: "YOUR_PUBLISHABLE_KEY" });
    </script>
    <script async src="https://YOUR_COLLECTION_DOMAIN/s/v3.js"></script>
    ```

    Keep the initialization block before the asynchronous script. This preserves commands that run while the pixel is loading.
  </Step>

  <Step title="Deploy and visit your site">
    Publish the change, then open any page on the connected website.

    After your consent integration supplies a complete grant, track a test event and use the network checks below to confirm the pixel loads and sends it.
  </Step>
</Steps>

<Note>
  You can close the setup screen after deployment. Reopen **Signals** later to check the signal tracker status.
</Note>

## Verify the installation

To test browser collection, open your browser's developer tools and reload the page:

1. Select the **Network** tab.
2. Search for `v3.js` and confirm it loads from your collection domain.
3. Grant consent through your integration, track a test event, then search for `events` and confirm the browser sends a request to `/v1/events` on the same domain.

Both requests should return a successful `2xx` response.

## What happens on initialization

`signalq("init", ...)` initializes browser collection without creating visitor state or sending an ordinary event. Browser events require `consent_basis: "consent"` and `granted` values for `ad_storage`, `ad_user_data`, and `ad_personalization`. Missing, unknown, denied, malformed, or withdrawn state does not send an ordinary browser event.

The browser flow is not the authoritative activation check. Use the identity-free server verification event for setup.

<Note>
  The generated snippet uses `signalq`. Do not rename it to `signal`; the v3 bundle intentionally exposes only the collision-resistant `signalq` global.
</Note>

## Content Security Policy

If your website uses a Content Security Policy, allow the collection domain in both places:

* Add `https://YOUR_COLLECTION_DOMAIN` to `script-src`.
* Add `https://YOUR_COLLECTION_DOMAIN` to `connect-src`.
* Apply your site's nonce or hash policy to the inline initialization block.

You may need to allow `https://connect.facebook.net` in `script-src` after you [connect Meta](/docs/signals/connect-meta). The Meta library loads only after advertising consent is granted.

## Troubleshoot

### The script does not load

* Confirm the snippet appears in the rendered page source.
* Clear your site cache or CDN cache after deploying.
* Disable content blockers while testing.
* If your site uses a Content Security Policy, allow your collection domain in `script-src`. The initialization block must also follow your site's nonce or hash policy for inline scripts.

### The event request is blocked

* Allow your collection domain in the `connect-src` directive of your Content Security Policy.
* Confirm you installed the snippet on a domain allowed by the signal tracker.
* Confirm the publishable key and script URL came from the same PlainRouter snippet.

### Signal setup still shows as incomplete

The browser pixel does not complete activation. Send the server verification event described in [Verify Signal ingestion](/docs/signals/verify-ingestion), and confirm the collection hostname is active.

## Next step

Add your consent state and business events in [Track events and consent](/docs/signals/track-events).
