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

# Privacy Controls

Adora takes privacy seriously and provides you with controls to allow or block what is captured in the end user's browser. There are three primary privacy control features to manage data capture: masking, blocking, and URL management.

By default, the Adora snippet does the following:

* Masks all input fields, except for those with the CSS class `adora-unmask`.
* Masks all HTML elements with the CSS class `adora-mask`.
* Blocks all HTML elements with the CSS class `adora-block`.
* Captures data only on pages where the snippet is installed, or where the URL is explicitly allowlisted. It also respects URL blocklists.

***

## What does Adora capture?

When an end user's browser loads with the Adora JavaScript snippet enabled, Adora begins capturing the HTML and CSS of the page. For example, consider the following page:

```html theme={"system"}
<html>
  <head>
    <script>
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.src = "https://adora-cdn.com/adora-start.js";
      script.onload = function () {
        adoraStart({
          orgId: "00000000-0000-0000-0000-000000000000", // fake ID
        });
      };
      document.head.appendChild(script);
    </script>
  </head>
  <body>
    <h1>Hello!</h1>
    <p>Welcome to our great site</p>
  </body>
</html>
```

Adora's snippet takes a snapshot of the page's HTML, inlines any CSS, and removes JavaScript. The following is an example of the serialized HTML tree:

```JSON theme={"system"}
{
  "type": "snapshot",
  "data": {
    "node": {
      "type": 0,
      "childNodes": [
        {
          "tagName": "html",
          "childNodes": [
            {
              "tagName": "head",
              "attributes": {},
              "childNodes": [{
                "type": 2,
                "tagName": "body",
                "attributes": {},
                "childNodes": [{
                  "type": 2,
                  "tagName": "h1",
                  "attributes": {},
                  "textContent": "Hello!",
                  "childNodes": []
                }]
              }]
            }
          ]
        }
      ]
    }
  }
}
```

If the page changes—e.g., a button is clicked or JavaScript modifies the DOM—the changes are captured and sent to Adora's servers using the [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) API. This example shows incremental changes:

```JSON theme={"system"}
{
  "events": [
    {
      "type": "click",
      "data": {
        "node": {
          "tagName": "button",
          "attributes": {
            "id": "my-button"
          }
        }
      }
    },
    {
      "type": "incremental",
      "data": {
        "added": [
          {
            "node": {
              "tagName": "p",
              "textContent": "A new paragraph!"
            }
          }
        ]
      }
    }
  ]
}
```

No screenshots or images are captured during this process. Only the changelog of HTML and CSS is sent, ensuring that unwanted data is filtered out on the client side before being sent to Adora.

Screenshots and event replays are generated by replaying the captured event data in a secure headless browser within Adora’s network. HTML and CSS changes are applied incrementally to a controlled web page, with specific events marked as screenshots.

***

## Key privacy controls

### Masking

Masking replaces text content with **\*** characters, allowing text structure to remain visible while obscuring specific values. For example:

<img src="https://mintcdn.com/adora/gGLiM8BT_tMzkR2M/images/privacy-masking.png?fit=max&auto=format&n=gGLiM8BT_tMzkR2M&q=85&s=c644219cec0248f16960a536df4d8718" alt="masking" width="1530" height="555" data-path="images/privacy-masking.png" />

From a data capture perspective, we replace the textContent value of the element before it is sent to our servers.

There are two ways to mask, using a CSS class or a data-attribute.

#### CSS class masking

To mask an element and all of its children, add the `adora-mask` CSS class to the HTML element. For example:

```html theme={"system"}
<div>
  <h1>Adora Mask Example</h1>
  <div>I display normally.</div>
  <div class="adora-mask">
    <span>This is masked</span>
  </div>
</div>
```

Results in:

<img src="https://mintcdn.com/adora/gGLiM8BT_tMzkR2M/images/privacy-masking-class.png?fit=max&auto=format&n=gGLiM8BT_tMzkR2M&q=85&s=d064de7a7ef59dac5db36fdc3ba64214" alt="masking-class" width="1542" height="564" data-path="images/privacy-masking-class.png" />

If you prefer to use custom class names, [contact us](mailto:hey@adora.so).

#### Data attribute masking

To mask an element and all of its children, add `data-adora-mask="true"` to the HTML element. For example:

```html theme={"system"}
<div>
  <div id="visible-content">This will be visible</div>
  <div data-adora-mask="true" id="masked-section">
    <p>This paragraph will be masked</p>
    <span>This span will be masked</span>
  </div>
</div>
```

### Unmasking

Unmasking allows you to see user input, which can be helpful for support request fields or search boxes. Apply the `adora-unmask` CSS class to unmask input fields. For example:

```html theme={"system"}
<div>
  <input type="text" value="this is masked" />
  <input type="text" class="adora-unmask" value="this is unmasked" />
</div>
```

Results in:

<img src="https://mintcdn.com/adora/gGLiM8BT_tMzkR2M/images/privacy-unmasking-input.png?fit=max&auto=format&n=gGLiM8BT_tMzkR2M&q=85&s=3e7c186bea9fadb8a779c81a65272a91" alt="unmasking-input" width="1542" height="456" data-path="images/privacy-unmasking-input.png" />

#### Nesting mask and unmask

The `adora-mask` and `adora-unmask` classes apply to all children of the element. This allows you to mask a section while selectively unmasking specific parts within it. For example:

```html theme={"system"}
<div class="adora-mask">
  <p>This paragraph is masked</p>
  <div class="adora-unmask">
    <p>This paragraph is unmasked</p>
    <span>This span is also unmasked</span>
  </div>
  <p>This paragraph is masked</p>
</div>
```

In this example, the outer `div` with `adora-mask` masks all its contents. However, the inner `div` with `adora-unmask` overrides this for itself and all of its children, making them visible.

#### Element-only masking and unmasking

If you want to mask or unmask only a specific element without affecting its children, use `adora-mask-element` or `adora-unmask-element`. These classes apply only to the element itself, not its descendants.

```html theme={"system"}
<div class="adora-mask">
  <p>This paragraph is masked (inherits from parent)</p>
  <p class="adora-unmask-element">This paragraph is unmasked</p>
  <div>
    <span>This span is masked (inherits from grandparent)</span>
  </div>
</div>
```

In this example, the second `<p>` element is unmasked because of `adora-unmask-element`, but the `<span>` inside the `<div>` remains masked because `adora-unmask-element` does not propagate to children.

This is useful when you need fine-grained control over individual elements without affecting the masking state of their children.

### Blocking

Blocking replaces content with an empty transparent box while preserving the original spacing. This is useful for removing entire images or sections from being captured.

There are two ways to block, using a CSS class or a data-attribute.

#### CSS class blocking

Add the `adora-block` CSS class to an element to block its content and all of its children.

For example:

```html theme={"system"}
<div>
  <h1>Normal</h1>
  <div>I display normally.</div>
  <h1>Blocked</h1>
  <div class="adora-block">
    <span>This is blocked</span>
  </div>
</div>
```

Results in:

<img src="https://mintcdn.com/adora/gGLiM8BT_tMzkR2M/images/privacy-blocking-contents.png?fit=max&auto=format&n=gGLiM8BT_tMzkR2M&q=85&s=41851babcf969f4405bd467d3fba2e49" alt="blocking-contents" width="1542" height="555" data-path="images/privacy-blocking-contents.png" />

Examples of blocking an image:

<img src="https://mintcdn.com/adora/gGLiM8BT_tMzkR2M/images/privacy-blocking-image.png?fit=max&auto=format&n=gGLiM8BT_tMzkR2M&q=85&s=65e64837a4f94a09f35d76c8734e7df9" alt="blocked-image" width="1449" height="972" data-path="images/privacy-blocking-image.png" />

If you wish to use your own class name, [contact us](mailto:hey@adora.so).

#### Data attribute blocking

Add the `data-adora-block` attribute to an element to block its content and all of its children.

For example:

```html theme={"system"}
<div>
  <div id="visible-content">This will be visible</div>
  <div data-adora-block id="blocked-content">
    This will be blocked
    <input type="text" value="secret" />
  </div>
  <div id="another-visible">Also visible</div>
</div>
```

### URL Management

Adora offers both automatic and opt-in URL management for greater control of captured data. To manage URL controls for your organization, please visit the access control tab in settings [here](https://app.adora.so/settings/access-control), or [contact us](mailto:hey@adora.so).

#### Controlling What URLs Adora Captures

By default, Adora captures all URLs where the snippet is installed. To prevent Adora from capturing specific URLs, you can:

1. Avoid adding the script to those pages (e.g., using rules in Google Tag Manager or your codebase).
2. Install the snippet on all pages but configure a blocklist or allowlist for URLs. This is especially useful for single-page applications (SPAs) with dynamic routing, where managing snippet installation may be more complex.

Allowlists and blocklists use simple wildcard patterns. For example, you can configure Adora to capture all pages except those matching specific patterns:

* `/private-section/*` blocks direct pages under private-section (like /private-section/page1)
* `/private-section/**` blocks all pages under private-section, including deeply nested ones (like /private-section/accounts/user/settings)

When the Adora snippet loads, it checks if the current URL is blocked or allowed. By default, all URLs are allowed unless specified otherwise.

#### Redacting Path Data in URLs

URL aggregation is a key feature of Adora that simplifies your workflow by grouping similar paths. For example, URLs like `/page/uuid1`, `/page/uuid2`, and `/page/uuid3` are aggregated into `/page/*` in the UI. By default, this aggregation occurs server-side, meaning the full path (e.g., `/page/uuid1`) is sent to Adora.

If sending full paths is not desirable—e.g., when paths include sensitive data like `uuid1`—you can define client-side grouping rules using regex patterns. These rules allow Adora to strip or group paths before they are sent to the server. For example, you could provide the rule `/page/*` to ensure all such URLs are captured as `/page/*`.

#### Query Parameters

By default, Adora removes all query parameters to minimize the risk of unintentionally capturing sensitive information, such as authentication tokens. This default behavior provides peace of mind out of the box.

However, there are scenarios where query parameters are essential for differentiating steps within the same page. For example, a signup process might use `/signup?step=1`. By default, Adora would treat all such pages as `/signup`. To distinguish between steps, you can explicitly allow specific query parameters, such as `step`, to be captured.

### Stopping and restarting capturing

You can stop (or pause) Adora from capturing events by calling `window.adoraStop()` anytime. You can verify that Adora has been stopped capturing events by verifying that no requests being sent to `/sessions/SESSION_ID/events` in the "Network" tab. The snippet will not capture any events until `window.adoraStart()` has been called again.
