Skip to content

Changelog

AnyReplay Changelog

What changed in AnyReplay, written for the people using it. Subscribe with RSS to hear about new SDK versions and features.

RSS feed

  1. v0.3.0Web SDKReact Native SDKDashboardPrivacy

    SDK 0.3.0: what people type is masked by default

    Every AnyReplay SDK now masks what people type into form fields unless you opt out with `maskAllInputs: false`. Passwords, one-time codes and card fields stay masked either way, and new projects start with masking on.

    • Breaking, and the reason to read this entry: `maskAllInputs` now defaults to `true`. A recording shows a form being filled in, with asterisks instead of what was typed — in inputs, text areas and selects, including values that were already there when the page loaded. The same goes for a React Native TextInput and a Flutter text field. This reverses the default introduced in 0.1.3.
    • To keep seeing what people type, set `maskAllInputs: false`. It is one line in your init options, under the same name in every SDK. A website whose snippet does not set the option follows the project's own switch: if your project already had masking off, the script-tag snippet keeps recording typed values after the new default is deployed, and so does @anyreplay/browser from npm once you upgrade. Until the first answer from our servers arrives, a page records masked. The React Native and Flutter SDKs do not ask the project; set maskAllInputs: false there when you upgrade.
    • Passwords, one-time codes, payment fields and card numbers are still never recorded, with maskAllInputs: false too. Rich-text editors (contenteditable) are still recorded unless you set maskAllTyping: true or mark them with ar-mask.
    • New projects start with masking on. Creating a project — in the dashboard or in the app — shows one switch, Mask what visitors type into form fields, on by default. If a project has it off, including a project created earlier that answered no to the old checkout question, the setup page now writes maskAllInputs: false into the snippet, so the code you copy keeps recording typed values on any SDK version.
    • A masking option that is not a boolean is still ignored, and fields stay masked. maskAllInputs: "false" — the string a tag manager variable often hands over — leaves fields masked and logs a warning in the console.
    • The Google Tag Manager template, the WordPress plugin and the Shopify embed now tick Mask form fields by default and send maskAllInputs: false when it is unticked. The updated versions reach their stores in their next release; until then, unticking the box there leaves fields masked.
    • React Native: a view that moves is replayed where it now stands. When a view moved under a new parent, or siblings changed order, 0.2.3 sent no removal, and the replay could show the view twice or in its old place. 0.3.0 sends the move. The player also repairs recordings made with older versions where it can.
    • The script-tag snippet picks up the browser changes as soon as they are deployed. npm installs get them by upgrading @anyreplay/browser or @anyreplay/react-native — and the Capacitor, Cordova, Electron and Tauri packages — to 0.3.0.
  2. Dashboard

    Flutter on the setup page

    Flutter apps can be recorded: `anyreplay_flutter` is on pub.dev, and the setup page has a Flutter tab with the project key already in the code. The setup-guide email can send it to a developer.

    • A Flutter tab on the setup page. It shows the code to paste into lib/main.dart with the project key filled in — flutter pub add anyreplay_flutter, one init call and a navigator observer that names each screen after its route — says what the app needs, and links to the install guide. The app id is read from the app itself.
    • Flutter is recorded the way React Native is: as a tree of words and boxes read from Flutter itself, never as screenshots, so every replay can be searched, masked word by word and translated.
    • The install guide email covers it too: add the package and call init, run the app again (a hot reload does not load the plugins it brings), open it once.
    • anyreplay_flutter 0.1.0 needs Flutter 3.27 or later. It has been tested end to end on the iOS simulator; Android is supported and not yet tested on a device. Native iOS and Android SDKs are still coming.
  3. v0.2.3Web SDKReact Native SDK

    SDK 0.2.3: a user identified straight after init is no longer lost

    `identify` called straight after `init` — the usual place, right after a login on page load or app start — was sometimes lost, and the session showed no user. The SDKs now wait until the session exists, then send it.

    • `identify` called straight after `init` was sometimes lost; now it waits for the session to exist. The SDK sent the user's id and email before the session's first recording had reached us, so there was no session to attach them to yet, and they were not sent again. The session was recorded, but without a user, so searching for that person did not find it. The SDKs now hold the identity until the session's first recording has been accepted and then send it, once. An identify after that goes out at once, as before.
    • If the server still answers that it found no session, the SDK tries once more after the next recording is accepted. In React Native, the new session that starts after 30 minutes away is given the same user once it exists.
    • Our servers now also keep an identity that arrives before its session for a couple of minutes and attach it when the session starts, so sessions from apps still on an older SDK are linked too.
    • The script-tag snippet picks up the fix as soon as it is deployed, with nothing for you to change. npm installs get it by upgrading @anyreplay/browser or @anyreplay/react-native — and the Capacitor, Cordova, Electron and Tauri packages — to 0.2.3. Nothing changes in how you call identify.
  4. Dashboard

    Ionic, Cordova and Electron on the setup page

    The setup page now has tabs for Capacitor and Ionic, Cordova and Electron apps, with the project key already in the code. The setup-guide email can send each of them to a developer.

    • Three new tabs on the setup page: Capacitor / Ionic, Cordova and Electron. Each shows the code to paste with the project key filled in, says what the app needs before it can record, and links to its install guide. Electron's code names the project's first allowed app as its appId; Capacitor and Cordova read the app id from the app itself.
    • The install guide email covers them too, with steps for each: install, add the call, rebuild the app, open it once.
    • @anyreplay/capacitor, @anyreplay/cordova and @anyreplay/electron are no longer a preview. @anyreplay/tauri still is, and Tauri stays on the setup page's list of what is coming.
  5. v0.2.2Web SDKReact Native SDKPrivacy

    SDK 0.2.2: a card number inside a note is no longer recorded

    A card number typed inside longer text — a note, a message to support — could be recorded, because the SDKs only recognised a field that held nothing but a card number. Both SDKs now hide its digits after the sixth and keep the rest of the text.

    • A card number typed inside longer text could be recorded; now its digits after the sixth are hidden. The rules in 0.2.1 looked at a field's whole value, so a notes field that read "my card is 5555 5555 5555 4444" was ordinary text and was recorded as it was typed. Both SDKs now look for a card number anywhere in what a person types — in a browser input or text area, in a contenteditable editor, and in any React Native TextInput, multi-line ones included — and replace its digits with * as soon as a seventh digit is typed, so no more than six are ever recorded. The words around it, and other numbers such as a phone number, a date or an order number starting 0 or 1, are still recorded.
    • Sessions recorded before you upgrade may contain a card number that someone typed inside longer text in an unmarked field. Marked payment fields, and fields covered by maskAllInputs or maskAllTyping, were masked throughout.
    • Capacitor and Cordova no longer send a chunk twice after the app is closed at the wrong moment. The SDK remembered which chunk number it had just used only every few seconds, so an app closed right after sending could start again with the same number and send it once more. The number is now saved the moment it is taken. Nothing was lost before — the server kept the data — but the session could show a duplicate warning.
    • In the player, a reported error no longer also appears as a tracked event. An error your app threw, or reported with trackError, showed up twice in the Events list: once as the error and once as a tracked event named $error. It now appears once, as the error, with its marker on the timeline and its row in the Console.
    • The script-tag snippet picks up the browser fix as soon as it is deployed, with nothing for you to change. npm installs get it by upgrading @anyreplay/browser or @anyreplay/react-native — and the Capacitor, Cordova, Electron and Tauri packages — to 0.2.2. The player fix needs no upgrade.
  6. v0.2.1Web SDKReact Native SDKPrivacy

    SDK 0.2.1: a card number being typed is no longer recorded on the way

    A card number being typed could be recorded before it was complete. Both SDKs now mask it from the seventh digit, so at most the first six digits are ever recorded. Two smaller fixes from the same device test ride along.

    • A card number being typed could be recorded before it was complete; now at most the first six digits are. The floor masked a value once it was a whole, valid card number, but a number is typed one key at a time. In the browser every keystroke is recorded on its own, so a field named nothing in particular — no autocomplete="cc-number", no name or label that says "card" — sent 4, 42, and on up to the first twelve or thirteen digits in the clear before the finished number was masked. React Native reads the screen twice a second, and a read that landed mid-number recorded what had been typed so far. Fields marked as payment fields were never affected. Both SDKs now also mask a value that could still become a card number — digits only (spaces and dashes allowed), starting 2–6, grouped like a card and more than six digits long — so at most the six digits that identify the card's issuer are recorded. Telephone numbers starting 0 or + or written in short groups, dates, postcodes and quantities are still recorded. A seven-digit or longer number starting 2–6 typed without breaks, such as an order number, is now masked too; that is the trade we chose.
    • The same rule covers a card number typed on its own into a `contenteditable` editor in the browser SDK, and the values already in a page's fields when recording starts.
    • Sessions recorded before you upgrade may contain the first digits of a card number typed into an unmarked field. Marked payment fields, and fields covered by maskAllInputs or maskAllTyping, were masked throughout.
    • A recording that starts before the page has loaded now opens with its page details (address and size), as the recording format requires. Two empty "page loaded" events used to come first; nothing used them, and they are dropped. This mostly affected desktop apps, which can start recording very early.
    • Images are no longer uploaded after ingest refuses them. When a project did not list an app, the browser SDK asked which images ingest already had, was refused, and then uploaded every image anyway — to be refused again. It now stops at the first refusal.
    • The script-tag snippet (served from our CDN) picks up these fixes as soon as they are deployed, with nothing for you to change. npm installs get them by upgrading @anyreplay/browser or @anyreplay/react-native — and the Capacitor, Cordova, Electron and Tauri packages — to 0.2.1.
  7. v0.2.0Web SDKReact Native SDKIngestDashboardPlayerPrivacy

    SDK 0.2.0: recordings that survive a bad network, and apps that say what they are

    Both SDKs keep recording through an outage and send the backlog in pieces the server accepts. Apps can be allowed by their bundle id, every session says which platform recorded it, and React Native records taps, scrolling and controls the way people used them.

    • A lost connection no longer ends a recording. 0.1.4 stopped after five failed deliveries in a row, and after a long outage could send its whole backlog as one request too large to accept. 0.2.0 waits and tries again — 2 s, doubling to a minute, never sooner than the server asks — and sends what it kept in chunks of about 256 KB. Only a real refusal, such as a paused project or a used-up plan, stops it.
    • Allowed apps. An app has no web address, so a project that listed its domains used to refuse every app. Add the app's bundle id or package name under Allowed apps in the project's settings and pass the same value as appId; the setup page writes it into the snippet for you.
    • Every session says what recorded it — platform, SDK version, app version and, on Android, the device model — and you can search by it, for example platform:react-native.
    • React Native records what people did. A tap is recorded when the finger lifts, so a scroll or a swipe is no longer a burst of taps that looks like rage. Scroll positions, bold and italic text, switches, checkboxes, sliders, spinners, modals, maps, web views and videos are drawn in the replay, and tablets are recorded as tablets.
    • A refusal can become a yes. A visitor who declines and then accepts on the same page — or in the same app session — is now recorded from that moment, as a new visitor. trackError(error) reports an error you caught yourself.
    • Apps built from web pages. @anyreplay/capacitor, @anyreplay/cordova, @anyreplay/electron and @anyreplay/tauri are published as a preview for Ionic, Cordova and desktop apps, and keep the app's styles, fonts and images in the recording. Their install guides are in the docs; they join the setup page once we have tested them on devices.
  8. v0.1.4Web SDK

    SDK 0.1.4: a rage click is a rage click again

    The browser SDK counted every ordinary click three times, so nearly every session with a click was flagged as a rage click. It now counts clicks, and finds a real burst wherever it lands.

    • The "Rage click" flag means something again. The browser reports a mouse-down and a mouse-up around every click, and the SDK counted all three — exactly the three-click threshold — so one ordinary click was enough to flag a session. Only clicks count now: three or more within a second, within 30 pixels of each other. A tap on a phone is a click, so touch devices are still covered.
    • A burst is found where it happens. A click somewhere else just before it no longer hides a burst on the button that is not answering.
    • Sessions recorded before you upgrade keep the flag they were given, so the "Rage click" filter will over-report on older recordings until they age out. The script-tag snippet already serves the fix; npm installs get it with 0.1.4.
    • @anyreplay/react-native moves to 0.1.4 alongside it, with no behaviour change, so both SDKs share a version number.
  9. v0.1.3Web SDKReact Native SDKPrivacy

    SDK 0.1.3: recordings now show what people type

    Both SDKs record the values people type into forms instead of masking them. Masking becomes a switch you turn on — maskAllInputs: true restores the old behaviour — and passwords, one-time codes and payment fields are never recorded in any mode. The setup wizard now asks whether your site has a checkout or a sign-in form and hands you the matching snippet.

    • Breaking, and the reason to read this entry: `maskAllInputs` now defaults to `false`. After upgrading, recordings of your site will contain what visitors type into inputs and text areas, and the values that were already in those fields — a name, an address, the message they wrote to support. Watching someone fail to complete a form is most of the value of a replay, and until now you could not see what they were trying to enter.
    • To keep the old behaviour, set `maskAllInputs: true`. One line in your init options, and every field value is asterisks again exactly as before. Do it before you upgrade if any form on your site carries data you should not store. maskAllTyping: true is the stricter switch: form fields and the text of every contenteditable editor.
    • Some fields are never recorded, whatever you configure. Passwords and one-time codes; card numbers, security codes, expiry dates and cardholder names, recognised from autocomplete="cc-…" or from a name, label or placeholder that reads like one; IBANs, routing numbers and sort codes; and any value of 13–19 digits that passes the card-number check. No option turns these off. type="email" and type="tel" inputs are not on that list: an address and a phone number are ordinary contact details, so they are recorded by default and masked by maskAllInputs, maskAllTyping or ar-mask like any other field. See masking and blocking for the full list.
    • The `ar-mask` class now masks a field's value, not just text. Put it on one input, or on a <fieldset> around several, and their values are masked while the rest of the page records normally — which is what to reach for when only part of a form is sensitive. A prefilled <textarea> marked this way is masked too, in its value and in its text.
    • A masking option that is not a boolean is ignored and says so. maskAllInputs: 'true' — the string a tag manager variable hands over — leaves masking off and logs a warning in the console, rather than failing silently.
    • `@anyreplay/react-native` now behaves the same way. maskAllInputs defaults to false there too, so a recording keeps what a person types into a TextInput, and maskAllInputs: true restores the old behaviour in one line. The same floor applies as far as a phone can tell it: secureTextEntry fields, and any field whose textContentType, autoComplete, keyboardType, accessibility label, placeholder or testID names a password, a one-time code or a payment instrument — plus any value shaped like a card number. A bare <TextInput /> with no props says nothing about itself and is recorded, exactly as an unnamed <input> is on the web; give sensitive ones a textContentType, an autoComplete or an ar-mask testID.
    • The setup wizard asks one question. Creating a project now asks whether the site has a checkout, sign-in or account form, and generates the install snippet with maskAllInputs: true when you say yes. You can change the answer on the project's setup page; it only changes the snippet the dashboard shows you — the snippet already on your site is what decides what is recorded.
    • Our privacy policy and DPA have been updated to say what recordings may now contain; the DPA moves to version 1.1 and owners will be asked to accept it.
  10. v0.1.2Web SDKReact Native SDKPrivacy

    SDK 0.1.2: nothing is stored until the visitor agrees

    With requireConsent on, the recorder now writes nothing to the browser and sends nothing until consent is granted — and a withdrawal erases what an earlier acceptance created.

    • Nothing before consent. With requireConsent: true, createRecorder() no longer writes the visitor and session keys to browser storage, starts no recording and makes no request until consent(true) is called. Previously the visitor id was written as soon as the script loaded, which is storage that needs consent in the EU.
    • A withdrawal clears what was stored. consent(false) after an acceptance deletes the visitor and session keys and stops recording for that page; a later acceptance is a new visitor.
    • Sampling is decided at consent. A sampled-out visitor is still decided once and stays decided; the decision now happens the first time they agree rather than the first time they load a page.
    • React Native: consent before init is no longer lost. A consent(true) or consent(false) call made before init() finishes is applied once it does, which is the order the documented example uses.
    • Nothing changes for apps that do not set requireConsent. See consent.
  11. v0.1.1Web SDKReact Native SDK

    SDK 0.1.1: the browser SDK works outside a bundler

    @anyreplay/browser now carries its recording engine inside the package, so it imports cleanly in Node and in test runners as well as in bundled apps.

    • @anyreplay/browser bundles rrweb instead of depending on it. Importing the SDK outside a bundler used to fail on its first line because rrweb's entry points do not resolve as ES modules under Node; it now works anywhere.
    • There is nothing extra to install: npm install @anyreplay/browser is the whole dependency.
    • @anyreplay/react-native moves to 0.1.1 alongside it, with no behaviour change, so both SDKs share a version number.
  12. v0.1.0Web SDKReact Native SDK

    Both SDKs on npm, with public source

    The browser and React Native recorders are published on npm as @anyreplay/browser and @anyreplay/react-native, MIT-licensed, with their source on GitHub.

    • npm install @anyreplay/browser for web apps, as an alternative to the script tag. See npm package.
    • npm install @anyreplay/react-native for React Native and Expo apps. See React Native.
    • The source of both is public at github.com/baemtech/anyreplay-sdk, so you can read exactly what the recorder does inside your product before you ship it.
    • Both packages are MIT-licensed and ship TypeScript types.
  13. Web SDKPlayerPlansDashboard

    Custom events, session navigation and a recording-hours meter

    Tag moments with track(), move through sessions without leaving the player, and see recording hours metered beside sessions. Projects can cap themselves.

    • Custom events. anyreplay('track', name, properties) puts a marker on the timeline; filter the session list by event with Has event. See custom events.
    • Route changes in single-page apps are recorded automatically as $navigate markers and count as pages. See single-page apps.
    • Sessions survive reloads. A reload or same-origin navigation within 30 minutes continues the same session instead of starting a new one.
    • A session rail beside the player keeps the list you came from, with its filters, so Prev and Next move between sessions without reloading.
    • Keyboard shortcuts in the player — Space, arrow keys, J/K, N, 1–4 for speed, F and ? for the full map — plus auto-advance to the next session, and your speed and skip-inactive setting carried from one recording to the next.
    • A rebuilt timeline with clicks, rage clicks, tracked events and route changes as markers, idle stretches hatched and a hover readout.
    • Recording hours are metered alongside sessions. Either meter filling up pauses new sessions while recordings in progress finish, and usage emails show both.
    • Project session caps, from the snippet (maxSessionsPerMonth) or the Projects page; the lower one applies. See session caps.
    • The contact form on anyreplay.com now delivers messages to the team and sends you an acknowledgement.
  14. Website

    anyreplay.com: product pages, guides and comparisons

    anyreplay.com has a front door: product and pricing pages, a blog, fair comparisons with other replay tools, use cases and a glossary.

  15. PlansDashboard

    Free trial limits and usage emails

    The free trial includes one project and 500 sessions a month, and owners and admins are emailed as usage reaches 50, 75, 90 and 100 percent.

    • A trial organisation can have one project and record 500 sessions a month.
    • At the limit, new sessions are refused while sessions already in progress are still accepted; nothing already recorded is deleted.
    • Owners and admins get an email at 50, 75, 90 and 100 percent of the month, in their own language, with the real numbers.
    • The dashboard home and settings pages show the same usage.
  16. React Native SDKPlayerPrivacy

    React Native recordings that show what the screen shows

    The React Native recorder now reads React's committed tree, captures images, icons and styling, and masks iOS text fields correctly.

    • Recording reads the tree React actually committed on each tick, so memoised screens, custom Babel setups and nativewind apps are all recorded.
    • Fix: text fields on iOS are now masked by default like on Android. Previously an iOS TextInput could slip past the default mask.
    • Recordings include image URLs, icon-font glyphs, gradients, corner radius and borders, and the player draws them.
    • Images shipped inside your app are uploaded once per project by content hash; photos from the device are never read.
    • Fix: a session resumed after a relaunch no longer restarts its chunk numbering, which could drop the resumed part.
  17. React Native SDKPlayerTranslation

    React Native session replay

    Record React Native apps as structure and text rather than screenshots, and play the sessions back in the dashboard — translatable like web sessions.

    • A React Native recorder with no native module: install it, call init, wrap the app in <AnyReplay>.
    • Screens are recorded as element trees and text, so a mobile session can be translated just like a web one.
    • A mobile player that draws the recorded screens, with seeking that rebuilds each frame from the last snapshot so scrubbing backwards is exact.
    • Screen tracking for React Navigation with trackNavigation, taps and rage taps, consent and identify.
  18. AccountsTranslationPrivacy

    Password reset and more resilient translation

    Forgotten passwords can be reset by email, and long translations recover from interruptions instead of failing outright.

    • Password reset. Request a link from the sign-in page. Links work once, expire in an hour, and completing a reset signs out every other session on the account.
    • A translation interrupted by a service restart picks up again instead of staying stuck.
    • One imperfect batch from the translation model no longer discards the whole translation; only the affected strings stay in their original language.
    • Error reporting was added to the services, built to exclude recordings, request bodies, cookies and visitor addresses.
    • Encrypted, off-site backups of the database and recordings, with a weekly restore test.
  19. AccountsPrivacyDashboard

    Google sign-in, and retention that deletes

    Sign in with Google, and recordings are now actually deleted when you delete them and when they pass your organisation's retention period.

    • Sign in with Google, including creating an account on first sign-in.
    • Deleting a session deletes the recording from storage, not only from the list.
    • Retention is enforced. A sweep every six hours deletes sessions older than your organisation's retention setting. See data retention.
    • Requests are rate-limited per source address, not only failed sign-ins per account.
    • Privacy policy and terms pages describing what the product actually does.
  20. TranslationPlayerDashboard

    On-demand translation and a self-diagnosing install wizard

    Translate any recorded session into your language from the player, and install the recorder with a setup page that explains why nothing is arriving.

    • Translate to… in the player translates the recorded interface on demand, with context for each string, a cache shared across your organisation and a glossary for terms that must not change. See session translation.
    • Moderators can correct a translation; corrections are written to the audit log.
    • Install wizard. Each project's setup page offers the snippet as HTML, for Google Tag Manager, Next.js, React Native and npm, turns Connected on the first event, and diagnoses failures: snippet never loaded, events blocked, domain not allowed, project paused, plan limit or session cap reached.
    • A pasted URL is accepted as a project domain; only the host is kept.
  21. PlayerPrivacy

    The replay player

    Watch recorded sessions in the dashboard: a player with a timeline and an interaction list, inside a sandbox that cannot run the recorded page's code.

    • Play, pause, seek and change speed, with a timeline sized from the recording before anything downloads.
    • An interaction list alongside the player.
    • Replays run in an iframe sandboxed without allow-scripts, and recorded scripts are rebuilt as inert elements, so a recording cannot execute code in the dashboard.
  22. Web SDKIngestDashboardAccounts

    Recording begins: browser SDK, ingest and sessions

    The first version of AnyReplay: a browser recorder with input masking on by default, an ingest service guarded by allowed domains, and a session list.

    • A browser recorder built on rrweb, loaded with one snippet: every input masked by default, deterministic per-visitor sampling, retries with a circuit breaker, and delivery with sendBeacon when a tab closes.
    • An ingest service that accepts recordings only from each project's allowed domains, with per-key rate limits.
    • Organisations, projects, roles and an audit trail, with the dashboard in English, Turkish, German, Spanish and French and in light or dark.
    • A session list showing every recorded visit within seconds of it happening.

Start free — 1 project, 500 sessions a month

Install the snippet, record a session, and watch it back in your own language.