Add the recorder

One script tag records every page it is on. It works on any site, with any framework or none.

The script tag

Replace replay.example.com with the domain of your Replayowl server:

<script src="https://replay.example.com/recorder.js"
  data-endpoint="https://replay.example.com/api/ingest" defer></script>

Put it on every page you want recorded. Page loads in the same tab within 30 minutes are merged into one session.

Starting from code

Leave out data-endpoint and start the recorder yourself, for example after the visitor has accepted your consent banner:

ReplayOwl.start({ endpoint: "https://replay.example.com/api/ingest" });

Stop it with ReplayOwl.stop(). Anything still waiting to upload is sent when it stops.

Attaching your user IDs

To find a session by the account that was signed in, pass your own user ID. Any of these work:

<script src="https://replay.example.com/recorder.js"
  data-endpoint="https://replay.example.com/api/ingest"
  data-user-id="user_8421" defer></script>
ReplayOwl.start({ endpoint, userId: "user_8421" });
ReplayOwl.identify("user_8421");

identify can be called at any time after the script has loaded, including before start. The whole session is attributed to that user, including what happened before the call. An ID is 1 to 128 characters. A session keeps up to five different IDs, so a visitor who switches accounts can be found under each one. The current ID is kept in sessionStorage, so later pages in the same tab carry it.

With defer, the script has not run yet when your inline code runs. Call identify after the script has loaded, for example in its load event, or use data-user-id.

Options

Pass options as fields in ReplayOwl.start({ ... }). The five masking options can also be set on the script tag, written as data-mask-all-text="true", data-mask-all-inputs="false" and so on.

Option Default What it does
maskAllInputs true Mask every text input
maskAllText false Mask all text on the page
maskEmails true Mask email addresses in regular text
maskCardNumbers true Mask runs of 12 to 19 digits, such as card and account numbers
maskDigits false Mask every digit
sessionTimeoutMin 30 Minutes of inactivity after which the next page load starts a new session
captureLogs true Record console.error, console.warn, uncaught exceptions and unhandled promise rejections

See Masking and privacy for the attributes that mask or hide individual elements.

What gets recorded

  • The page: a full snapshot when it loads, then every change. Each node gets a fixed numeric ID, so replays do not depend on CSS selectors that can point at the wrong element after the page changes.
  • Styles: same-origin stylesheets are copied into the snapshot, so replays do not depend on your site still serving the same CSS. Rules that CSS-in-JS libraries write straight into the CSSOM, insertRule, constructed stylesheets and adoptedStyleSheets are captured too.
  • Shadow DOM: open shadow roots and their stylesheets, including custom elements that attach a shadow root later.
  • Forms: typing, selecting and checking, and values set by scripts, so autofill by form libraries shows up.
  • Behaviour: mouse and touch movement, clicks, window and element scrolling, viewport size, focus, tab visibility, media play and pause, and console errors.

Framework guides