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

# Auto Capture

> Configure auto capture for the Userpilot Cordova plugin

Configure automatic screen and interaction capture for Cordova applications using the Userpilot Cordova plugin.

The Userpilot Cordova plugin can automatically capture screens and interactions in your Cordova app and forward them to the native Userpilot SDKs, enabling analytics and engagement without manual screen and event tracking. Because Cordova renders inside a WebView, auto capture runs entirely in the DOM at runtime — there is **no build-time instrumentation** and no per-element wiring. The engine detects route changes and interactions and bridges them to the native SDK, so the resulting events appear alongside native auto capture on the backend.

***

## SDK Configuration

Auto capture is **off by default**. Auto capture behavior is configured through the `options` object passed to `userpilot.setup`.

```javascript theme={null}
document.addEventListener('deviceready', function () {
  userpilot.setup(
    '<APP_TOKEN>',
    {
      logging: true,
      enableScreenAutoCapture: true,
      enableInteractionAutoCapture: true,
      enableInteractionTextCapture: true,
      enableInteractionAccessibilityLabelCapture: true,
      enableInteractionValueCapture: false,
    },
    function onSuccess() {},
    function onFail(error) {}
  );
});
```

| **Option**                                   | **Type**  | **Default** | **Description**                                                                                                                                                                                                       |
| -------------------------------------------- | --------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enableScreenAutoCapture`                    | `boolean` | `false`     | Enables automatic screen tracking from route/history changes.                                                                                                                                                         |
| `enableInteractionAutoCapture`               | `boolean` | `false`     | Enables automatic interaction capture (taps, changes, text input, submits, dialogs).                                                                                                                                  |
| `enableInteractionTextCapture`               | `boolean` | `true`      | If `false`, `target_text` is omitted from captured interaction payloads. Typed input values are never captured verbatim regardless of this flag.                                                                      |
| `enableInteractionAccessibilityLabelCapture` | `boolean` | `true`      | If `false`, accessibility labels (`aria-label` / `title`) are not captured, and `attr__desc` is omitted from hierarchy segments.                                                                                      |
| `enableInteractionValueCapture`              | `boolean` | `false`     | Enables value payload capture: `is_checked`, `selected_value`, and selected date/time. Slider `min`/`max` and `selected_index` for selects/lists are always included; `selected_value` only when this flag is `true`. |
| `maxHierarchyDepth`                          | `number`  | `30`        | Maximum number of ancestry nodes included in the hierarchy path.                                                                                                                                                      |

When either `enableScreenAutoCapture` or `enableInteractionAutoCapture` is enabled, the DOM auto capture engine starts automatically after `setup`. The configuration is read once from `setup`; use [Runtime Controls](#runtime-controls) to pause or resume afterwards.

<Tip>
  **Note**

  Auto Capture automatically tracks screen views and ignores manually sent `screen` events while enabled.

  If you are migrating from manual screen tracking, please review the migration guide [here](https://docs.userpilot.com/data-events/mobile-screen-tracking/mobile-screen-auto-capture#important).
</Tip>

***

## Screen Capture

When `enableScreenAutoCapture` is `true`, the plugin patches `history.pushState` / `history.replaceState` and listens for `popstate` and `hashchange`. The screen name is resolved with the following priority:

1. **Hash route** (for example `#/settings` → `/settings`). File-based Cordova apps keep a constant, noisy `pathname`, so a meaningful hash route is preferred. This covers hash-based SPA routers.
2. **`location.pathname + location.search`** (for history-routed apps), reported as-is — a bare `/` is a valid screen name and is kept.

The name always comes from the URL. There is no fallback to `document.title` or any other substitute. If the URL resolves to an empty string, no screen event is emitted. Consecutive identical names are de-duplicated.

Debounced `text_change` events are flushed **before** a screen transition is published — on both automatic route changes and manual `userpilot.screen(...)` calls — so a field edited just before navigating is still attributed to the screen it was typed on.

<Tip>
  **Manual screens**

  Manual `userpilot.screen()` calls are ignored whenever `enableScreenAutoCapture` is configured — manual and automatic screen tracking remain mutually exclusive, including while auto capture is stopped. To send screens manually, leave `enableScreenAutoCapture: false`.
</Tip>

***

## Interaction Capture

When `enableInteractionAutoCapture` is `true`, the plugin captures DOM interactions through delegated capture-phase listeners on `document` for `click`, `change`, `input`, and `submit`, plus a `MutationObserver` for dialog presentation. Events that originate inside a web component's shadow DOM are resolved to the real host element.

Each interaction is classified into a `raw_interaction_type` based on the element's tag, `type`, and ARIA `role`:

| **Interaction type**    | **Emitted for**                                                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `tap`                   | `button`, `a[href]`, `[role="button"]`, `[role="link"]`, `[role="menuitem"]`, `[onclick]` (climbs to the nearest interactive ancestor) |
| `tab_selected`          | `[role="tab"]`                                                                                                                         |
| `list_item_selected`    | A clickable element that also matches `[role="option"]` or `[role="listitem"]`                                                         |
| `menu_item_selected`    | `[role="menuitem"]`, or any clickable element inside a `[role="menu"]` container                                                       |
| `checkbox_selected`     | `input[type="checkbox"]` without `[role="switch"]`                                                                                     |
| `radio_button_selected` | `input[type="radio"]`                                                                                                                  |
| `switch_changed`        | `[role="switch"]` (including `<input type="checkbox" role="switch">` and `<button role="switch">`)                                     |
| `slider_changed`        | `input[type="range"]`                                                                                                                  |
| `spinner_selected`      | `select`                                                                                                                               |
| `date_picker_changed`   | `input[type="date" \| "month" \| "week" \| "datetime-local"]`                                                                          |
| `time_picker_changed`   | `input[type="time"]`                                                                                                                   |
| `text_field_changed`    | `input` (text-like types), `textarea`, `[contenteditable]`, `[role="textbox"]` — debounced per field; typed text is never captured     |
| `form_submitted`        | `form` submit (submit-control taps are omitted so only this event is sent)                                                             |
| `view_presented`        | An element matching `[role="dialog"]` / `[role="alertdialog"]` added to the DOM                                                        |

Each interaction maps to a high-level analytics category (`tap`, `text_change`, `selection_change`, `value_change`, `view_presented`) — that is the event name that reaches your analytics backend.

Rapid duplicate interactions on the same element are suppressed with a short de-dupe window (\~500 ms).

<Tip>
  **Custom components**

  To make custom components captured, build them from standard HTML and ARIA roles. For example, a custom list row should be a clickable element (`<button>` / `<a href>`) carrying `role="option"` (or `role="listitem"`) to be reported as `list_item_selected`; a custom toggle should carry `role="switch"`.
</Tip>

### Component Value Gating

By default, user-input values are stripped from event payloads — `is_checked`, selected dates and times, slider values, and dropdown selections do not leave the device. To include them, pass `enableInteractionValueCapture: true` in `setup` options. Position and configuration fields such as `selected_index` and slider `min`/`max` are always captured because they don't reveal user input; `selected_value` is only included when value capture is enabled.

***

## Privacy Controls

Global flags govern what is captured:

* **Text capture** — `enableInteractionTextCapture`
* **Accessibility label capture** — `enableInteractionAccessibilityLabelCapture`
* **Value payload capture** — `enableInteractionValueCapture`

Disabling text capture removes `target_text` from the payload. Redaction replaces an existing text/title with `****`; when no text exists, the property is omitted. Redaction is scoped to `target_text`. It does **not** mask `accessibility_label` — accessibility labels are developer-authored, so they are controlled only by `enableInteractionAccessibilityLabelCapture`.

Auto capture never sends typed input values verbatim — only the field's label plus `has_text` / `text_length`.

### `userpilotRedactText`

Redaction replaces the captured `target_text` with `****`. The interaction event still fires — the element is still identified by type, position, and structure — only the human-readable text is masked. Accessibility labels are not masked by redaction; they are controlled only by `enableInteractionAccessibilityLabelCapture`.

The programmatic API accepts either an `Element` or a CSS selector and applies to the element and its subtree. A selector is resolved when the call is made, so call it once the target elements are in the DOM:

```javascript theme={null}
userpilot.userpilotRedactText('#profile-form');
userpilot.userpilotRedactText(document.querySelector('.credit-card'));
```

A declarative HTML attribute is also supported:

```html theme={null}
<form data-userpilot-redact>
  <input type="email" />
</form>
```

### `userpilotIgnoreInteractions`

Ignoring skips **interaction** events whose hit-tested element lies inside the subtree (taps, value changes, text-field updates, etc.). Route-driven **screen** events are **not** suppressed — they come from route detection, not from element hit testing. The host app's own handlers still run — only auto capture ignores those interactions.

The programmatic API accepts either an `Element` or a CSS selector and applies to the element and its subtree:

```javascript theme={null}
userpilot.userpilotIgnoreInteractions('#admin-panel');
userpilot.userpilotIgnoreInteractions(myElement);
```

A declarative HTML attribute is also supported:

```html theme={null}
<div data-userpilot-ignore>
  <button>Internal action</button>
</div>
```

| **Attribute**           | **Effect**                                           |
| ----------------------- | ---------------------------------------------------- |
| `data-userpilot-ignore` | Drops auto capture for the element and its subtree.  |
| `data-userpilot-redact` | Masks `target_text` for the element and its subtree. |

***

## Runtime Controls

Auto capture starts automatically from `setup` (based on options). To stop or resume collection at runtime without re-passing the config — for example a "private mode" — use:

```javascript theme={null}
userpilot.stopAutoCapture(onSuccess, onFail);   // detaches all listeners
userpilot.resumeAutoCapture(onSuccess, onFail); // restarts with the same config
```

While stopped, no screen or interaction events are recorded regardless of other configuration. Pausing auto capture does not enable manual `screen()` calls: when `enableScreenAutoCapture` is configured, manual and automatic screen tracking remain mutually exclusive, including while auto capture is stopped.

***

## Limitations

* **WebView only.** Auto capture observes the DOM rendered in the Cordova WebView. Anything rendered outside the WebView (fully native screens or plugins with their own UI) is not captured by this engine.
* **Custom widgets need semantic markup.** Elements that handle interactions without using standard tags or ARIA roles (for example a clickable `<div>` with no `role` and no handler attribute) are not classified. Use the supported building blocks in the [interaction table](#interaction-capture) — or add the appropriate `role` — to be captured.
* **Typed input values are never captured.** For text fields, `target_text` is the field's label and only `has_text` / `text_length` describe the content; the value itself is never sent.
* **Text fields need a label to report one.** `target_text` is resolved from `aria-labelledby`, an associated/wrapping `<label>`, or a `label` attribute. A placeholder is deliberately not used as a label — it is reported separately as `placeholder`.
* **One screen source at a time.** Manual `screen(...)` is suppressed whenever `enableScreenAutoCapture` is configured, including while auto capture is stopped.

<Frame>
  [**For any questions or concerns please reach out to support@userpilot.com**](mailto:support@userpilot.com)
</Frame>
