# Single Domain Setup

{% hint style="info" %}
**How it works** \
The snippet is dormant until a recording starts. When triggered, the recorder communicates with the snippets via a browser-native local messaging API. Because this local messaging channel is scoped to the same origin, the recorder page must share the same root domain as your app pages (subdomains are fine). That's why this setup requires a dedicated page on your domain to host the recorder.
{% endhint %}

### Setup overview

To capture console logs, you need to:

1. Install the Birdie snippet on your app
2. Whitelist Birdie in your Content Security Policies
3. Identify your users with an email (<mark style="color:$primary;">optional</mark>)
4. Configure a recording page

## 1. Install the Birdie snippet

You can choose between 2 options:

### Option A: Frontend Integration using NPM

```javascript
npm install @birdie-so/snippet
# or
yarn add @birdie-so/snippet
```

<details>

<summary>Use with React / Vue / Angular / JS</summary>

You must get your own clientId, get it from your Birdie [Settings → Logs](https://app.birdie.so/settings/logs)  section.

```javascript
import { initBirdie } from "@birdie-so/snippet";

initBirdie({
  clientId: "YOUR_CLIENT_ID", // *** required ***
  
  // Optional contact info
  contact: { 
    email: "alex@empire.com",
    name: "Alexander",
    id: 65523 
  },

  // Optional metadata available to recordings
  metadata: {
    any: {
      key: "123",
      product_id: "EBF-233"
    },
  },

  // Optional hook once Birdie is ready
  onReady(birdie) {
    birdie.on("start", (data) => {
      console.log("Recording started", data);
      birdie.metadata = { dynamicKey: "value" };
    });

    birdie.on("stop", (data) => {
      console.log("Recording stopped", data);
    });
    
    // if you need to update the contact email after initialization:
    birdie.update({ contact: { email: "alex@empire.com" } })

    // or update your metadata:
    birdie.update({ metadata: { status: { id: "123", label: "active", color: "#000000" } } })
    
  },
});
```

👉 You will find some more infos about implementation [in this page](https://www.npmjs.com/package/@birdie-so/snippet?activeTab=readme).

</details>

***

### Option B: Manual installation

{% hint style="info" %}
We do not recommend installing Birdie through Google Tag Manager or Segment. The preferred method is to paste the code directly onto your web application, as this will result in faster load times.
{% endhint %}

1. Go to [Settings → Logs](https://app.birdie.so/settings/logs)&#x20;
2. Click on <mark style="color:purple;">Send to developer</mark>, or Copy the snippet code and paste it in the <mark style="color:green;">`<head>`</mark> section of your web app.\
   Note that the snippet is unique to your organization.

<details>

<summary>How to add custom medatada</summary>

Optionally add your own metadata if you need to store additional data along the recordings like this:

```javascript
// 1st method: add this before loading the snippet
window.birdieSettings = {
    contact_email: "john.doe@acme.com",
    metadata: {
        mykey: "value",
        otherkey: [
            { x: 12, y: 13 },
            { opacity: 35, width: 440 }
        ]
    }
}

// 2nd method, add metadata after loading the snippet: 
if (window.birdie) {
    window.birdie.metadata = {
        mykey: "value",
        otherkey: [
            { x: 12, y: 13 },
            { opacity: 35, width: 440 }
        ]
    }
}
```

💡 Note that if you have several tabs open with the snippet loaded, only the latest metadata that was set will be available along a recording.

</details>

<details>

<summary>How to hook into recorder events</summary>

Optionally you can register for events to know when a recording has started and stopped. First make sure window\.birdie object is present by registering for onBirdieReady event before loading the snippet, then register for "start" and "stop" events like this:

```javascript
window.birdieReadyCallback = function() {
  console.log("Birdie Ready, window.birdie object is now available")
  window.birdie.on('start', function(data) {
    console.log("A recording was started", data);
    // save custom data, or add metadata
    window.birdie.metadata = { key: "value" }
  });
  window.birdie.on('stop', function(data) {
    console.log("A recording was stopped", data);
  });
}
  
window.birdieSettings={
  onBirdieReady: birdieReadyCallback
}

// then add the snippet…
```

</details>

***

## 2. Whitelist Birdie in your Content Security Policy

To ensure proper functionality, whitelist the following:

* **HTTPS**: <mark style="color:purple;">`https://*.birdie.so`</mark> &#x20;
* **Secure WebSocket protocol:** <mark style="color:purple;">`wss://*.birdie.so`</mark>
* **Port**: <mark style="color:purple;">`443, 3478 (TCP and UDP)`</mark>
* **IP Address**: <mark style="color:purple;">`18.189.92.93`</mark> and  <mark style="color:purple;">`3.20.198.186`</mark>

#### Popup communication compatibility

Some Birdie flows require the Recorder opened in a new window to communicate with the window that opened it.

If your page sends the following header:

`Cross-Origin-Opener-Policy: noopener-allow-popups`

then the opened page may not have access to `window.opener`, and popup-to-opener communication may not work.

Make sure your opened page does not isolate itself from its opener in a way that disables `window.opener`.

***

## 3. Identify your customer with an email - <mark style="color:blue;">optional</mark>

The setup depends on how you installed the snippet:

**If you installed with NPM**&#x20;

Set the `contact: { email: ""}` value, or update it as soon as you have it. See full example above:

```javascript
onReady(birdie) {
    birdie.update({ contact: { email: "alex@empire.com" } })
    ...
```

**If you installed manually**

Add `contact_email` info in your `window.birdieSettings` . See example above:

```javascript
window.birdieSettings = {
    contact_email: "john.doe@acme.com",
    ...
```

## 4. Configure and verify your recording page

When a customer opens a Birdie recording link, Birdie needs a page on your site to display the recording interface.

This page is called your **recording page:**

You choose which page Birdie should use, then add that URL in your [Birdie logs settings](https://app.birdie.so/settings/logs).\
Birdie will launch the recorder directly from your site. \
You can think of it as a simple entry point on your site where Birdie launch the recorder and allow customers to record their screen directly from your site.

<details>

<summary>How the recording page works under the hood?</summary>

{% hint style="info" %}
The diagram below shows what happens technically when a recording starts - useful context if you want to understand why the setup is structured this way, but nothing here requires additional integration work on your part.
{% endhint %}

<figure><img src="/files/U52Dqtikxvitl2hoyCr1" alt=""><figcaption></figcaption></figure>

</details>

#### Step 1: **Create your recording page**

The best practice here is to create a dedicated recording page on your app.\
Example:

```
https://app.acme.com/recorder
```

This page should:

* include the Birdie snippet
* be on the same domain as your app
* be a blank page
* be accessible without authentication (like your login page)
* not redirect anywhere

👉 This ensures your recorder works reliably in all situations.

{% hint style="warning" %}

#### Important: redirects can break the recorder

If your recording page redirects users, for example to a login page, Birdie parameters may be lost.

Example:

```
https://app.acme.com/recorder?birdie-recording=...
```

If these parameters are removed:

* the recording interface will not appear
* logs will not be captured.

#### Requirement: preserve query parameters

If your app performs redirects, your developers must ensure that:

* the full query string is preserved, or
* parameters are forwarded to the destination page
  {% endhint %}

#### What happens when a recording starts

When a customer opens a recording link:

1. Birdie opens your recording page
2. The Birdie snippet loads
3. The recording interface appears
4. Logs are captured during the session across your app

<details>

<summary>What logs Birdie collects</summary>

Birdie collects logs from pages that:

* run the Birdie snippet
* are on the same domain as the recording

That means:

* a recorder started on `acme.com` can collect logs from `sub.acme.com`
* a recorder started on `sub.acme.com` can collect logs from `ace.com`

</details>

👉 This is why the page must be on your domain and include the Birdie snippet.

***

#### Step 2: Add your recording page in Birdie

Go to your Birdie logs settings:

1. Enter your [recording page URL](https://app.birdie.so/settings/logs)
2. Click **Verify**

Birdie will check that your setup is correct before enabling log collection:&#x20;

<figure><img src="/files/fTauMFQvazTmwkoM3QtV" alt=""><figcaption></figcaption></figure>

#### Quick test before verifying

Before clicking **Verify** :

1. Open your recording page in an incognito window
2. Add a test parameter, for example:

   ```
   https://app.acme.com/recorder?test=1
   ```
3. Check that:
   * the page does not redirect, or
   * the parameter is still present after redirect

If the parameter disappears, your setup needs adjustment.

<details>

<summary>What if verification fails or the recorder does not appear?</summary>

Common causes:

* The page redirects and removes query parameters
* The Birdie snippet is not installed on the page
* The page is on a different domain

👉 These issues prevent the recorder from starting correctly.

</details>

<details>

<summary>Can I set it up in a testing (staging) environment?</summary>

If you want to test your setup before using it in production, you can also configure a testing environment.

This works the same way as your main setup, but is intended for internal testing only.

When configured, you will see a separate “Testing environment” section in your Birdie logs settings.

***

#### Important differences

The testing environment behaves slightly differently from your production setup:

* it is designed for internal testing only
* it does not use your helpdesk integration
* recordings must be triggered manually

***

#### How to test your staging setup

To test your staging environment:

1. Go to your Birdie logs settings
2. Find the **Testing environment** section
3. Click **Request a recording**

👉 This will generate a recording link that you can use to validate your setup.

***

#### Important

The testing environment will **not work through your helpdesk integration**.

You must use the **“Request a recording”** link to test it:

<figure><img src="/files/NkqsZXskv5sJzOt02QTy" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Subdomains and Safari limitation</summary>

IIn Safari, logs are only captured when the snippet is running on the exact same subdomain.

</details>

***

{% hint style="info" %}
Tip: when a snippet is loaded into your app, a cookie named `__birdie_snippet_status` is maintained as long as the snippet is loaded, and expires 60s after the snippet is unloaded. If you need to detect the presence of the snippet in one of your pages you can test the presence of this cookie.
{% endhint %}

{% hint style="success" %}
If you need help or have a question, contact us at <support@birdie.so>
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.birdie.so/birdie-docs/request-screen-recordings/installation/snippet/single-domain-setup.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
