AI Policy
Last updated: August 24, 2026
We believe in being transparent about how we use AI. This page starts with the part that concerns your data — every place SimpleLogs may send something to a language model, what it sends, and how to switch it off — and ends with how we use AI to build and document the product itself.
How We Use AI on Customer Data
Your log events, performance timing data, and session recordings belong to you. Here is exactly what gets used by AI, why, and how to turn it off.
Each feature below has its own switch, and one switch covers all of them: Settings → AI → "Use AI". With it off we send nothing to a language model for your team — whatever the individual settings say, and including any AI feature we add later. Those settings are saved, so turning AI back on restores the setup you had.
AI Frustration Cluster Labeling
Our Session Replay feature includes rule-based (non-AI) detection of frustration signals in a recording — rage clicks, dead clicks, form abandonment, and similar patterns. Related occurrences across sessions are grouped into clusters (e.g., "the same button on the same page failing the same way across many sessions"). To turn a cluster into a human-readable label like "checkout button unresponsive on mobile Safari," we send a small set of derived, human-readable examples from that cluster — a description of the control, including its visible text, the page path, and a short plain-English behavior description such as "3 rapid clicks in 0.4s" — to an AI model.
When the frustration followed something failing, the cause goes with it: the address of the request that came back an error, or the message of the JavaScript error that fired. "Pay now returns a 500 on /checkout" is the label worth having, and "people click a button a lot" is not.
What is sent is limited to those derived examples. It never includes:
- Raw session recordings or DOM snapshots;
- Full log lines or timing data;
- The identity attached to those sessions — the user id, email, name, group and anonymous id we hold are not among the fields this pipeline reads. What is sent is produced by your application, though: a page path, a failed request's address, and the visible text of the control involved. Whatever your own URLs and on-screen labels put in front of a user can travel with them;
- Anything caught by our PII-masking rules — password fields, payment fields, and pattern-matched sensitive data are stripped before this pipeline ever sees them;
Frustration cluster labeling is enabled by default. To stop sending this data, turn it off any time from Settings → AI → "Frustration cluster labels" — doing so does not affect Session Replay recording or any other part of the product.
AI Script Naming
The Performance tab names the scripts that blocked your site's main thread. Most are named by a list we maintain ourselves — Google Tag Manager, Stripe, your own bundler's output — with no AI involved. For the ones that list doesn't recognize, we send the script's address to an AI model so it reads as "Acme Tag Manager" rather than a hostname.
What is sent, per script: its address with the query string and fragment removed, how many milliseconds it blocked, how many page views it appeared on, and counts of how it was triggered. It never includes:
- The addresses of your own pages, or any query string — the part of a URL that carries container ids, API keys and personal data is removed in the browser, before the data is ever sent to us;
- Identity, metadata, log lines, or timing data;
- Anything from a page view the script in question did not block.
AI Script Naming is enabled by default. Turn it off any time from Settings → AI → "Script naming" — every name our own list produces stays, and scripts it doesn't recognize show their hostname instead.
Outside of the features described here, we do not:
- Pass your raw log data, timing data, or session replay recordings to any AI model, whether our own or a third party's;
- Use your Customer Data to train, fine-tune, or evaluate AI systems;
- Allow any of our AI development tools to access production customer data.
For any AI feature that operates on your Customer Data, current or future, we will describe it here exactly like this — what is sent, why, and how to turn it off — and give you a per-team control to disable it without losing any other part of SimpleLogs.
Page & Element Descriptions
To make a problem report readable, SimpleLogs asks a language model what each page and control in your application is for, and how much it matters. That lets a detected issue say “the coupon field rejects every code” rather than “users struggle with an input”, and lets a problem on your checkout button outrank the same problem in your footer.
What is sent: the element's tag name, its id and class names, any accessibility label, and its visible text — the same descriptors already used for cluster labels. The page is identified by its route with dynamic segments masked, and a few example addresses go with it as they were, so the model can tell a listing from a detail page. No session recording and no identity information is included — but your text and your addresses are your own: a heading that greets someone by name, or an address carrying their email, is sent as your application wrote it.
These descriptions are written once per page and control rather than once per visit, so one description outlives any single session. The descriptors behind them are read from recorded pages, which is why the visible text of your own markup is what reaches the model.
This is off-switchable per team under Settings → AI → "Page and element descriptions". Turning it off does not degrade anything else: descriptions fall back to what your markup already says, and importance to a deterministic rating, so your frustration and anomaly scores never depend on it.
AI Session Summaries
Every session replay is titled with what the visitor was doing rather than with a session identifier. For almost every session that title involves no AI at all: it is composed from the page and control descriptions above, which were generated once per page rather than once per visit — “Checkout — dead click on Pay now button”.
A language model is used only for sessions our frustration scoring rates as badly frustrated, where the useful thing is the part a composed title cannot express: the sequence and its outcome, as in “abandoned checkout after the promo code failed”. That is a small fraction of sessions, and it is deliberate — it keeps this feature's cost tied to the size of your application rather than to how much traffic it gets.
What is sent, for those sessions only: the sequence of pages visited as route patterns, the descriptions SimpleLogs already holds for those pages and controls, which frustration detectors fired and how often, the label of the control each one fired on, and the messages of any errors logged during the session. No session recording, no typed input, no identity, and no session metadata is included. The summary describes what a person did rather than who they were — with the same caveat as everywhere else on this page: a control's label is its visible text, a route keeps any segment our masking does not recognize as an id, and an error message says what your application wrote. We do not rewrite any of them.
This is on by default and off-switchable per team under Settings → AI → "Session summaries". With it off, every replay keeps the composed title — derived directly from your data, with nothing sent anywhere.
AI Anomaly Summaries
SimpleLogs finds slowdowns and error bursts statistically — detecting them, scoring them, and working out what they correlate with involves no AI at all. A language model writes one thing: the single line at the top of a detected anomaly that turns its statistics into a sentence, as in “checkout submission ran 4σ slow while 12 sessions showed elevated frustration”.
What is sent: the touchpoint's name and environment, the anomaly's own numbers — how long it ran against its baseline, how many standard deviations that is, how many times it happened, and for an error burst how many errors fired — the names of touchpoints that were slow in the same window, how many sessions showed frustration during it, and whether traffic spiked. No log or error message contents, no session recording, no user data, and no identity information.
This is on by default and off-switchable per team under Settings → AI → "Anomaly summaries". With it off the same line is written from a local template instead. Detection, ranking and correlation are identical either way, because none of them were ever the AI's work.
Identity Data
SimpleLogs can attach a person to the sessions, logs and timings it captures, so you can answer who an issue affected. Because that is the most sensitive data we hold on your behalf, this section covers it in full: where an identity comes from, what our AI features do with it, and how to switch it off.
Where identity comes from
Three places, and all three are your own application telling us something. Every identity we store records where it came from, and whether it is something you asserted or something we read off data you were already sending.
- An
identify()call — you tell us who the current user is, and what you pass is what we store: user id, email, name, account or tenant, and any scalar traits you choose to add. Recorded as confirmed. - Claims on a token your app is already sending — when our browser SDK instruments an outgoing request that carries an
Authorization: BearerJWT, it readssub,email,nameand the tenant claims out of that token's payload. The decode happens in the browser, the token itself is never stored and never sent to us, and the result is recorded as inferred rather than confirmed — because a claim is a label, not an assertion you made. This is on by default and is one line to turn off; see below. - A teammate — a member of your team can attach a person to a session in the dashboard after the fact. Marked as manual, which outranks everything automatic, precisely because it exists to correct the machine.
Separately, every browser gets an anonymous id: a random value minted on first visit and kept in browser storage. It is not a person and carries nothing about one — it is the handle that lets a visitor's pre-login activity be attributed to them once they do log in. It is stamped on captured data whether or not anyone ever identifies, and calling clearIdentity() on logout rotates it, so the next person to use that browser doesn't inherit the previous one's trail.
Beyond those, we do not guess. We never inspect cookies, browser storage, or the contents of your pages looking for who someone might be, and our ingest never infers identity from the shape of your metadata — a key called userId is probably a user id, but "probably" is not a basis for storing who someone is, and a wrong answer there is worse than no answer. One exception, and it is a display one: a recording that carries no identity but does carry a metadata key like email or userName is labeled with that value in the dashboard, and today it reads the same as one you told us. Nothing is stored from it and nobody can be filtered by it as an identity, though the metadata value itself remains filterable like any other. Everything you do send passes through the same redaction as the rest of your data before it is stored.
What our AI features do with identity: nothing
None of the identity we hold is sent to a language model by any feature on this page. Not the user id, not the email, not the name, not the account or tenant, not the traits you attach, and not the anonymous browser id. That is a property of how these features are built rather than a promise laid over them — identity is simply not among the inputs any of them assemble. What can still carry an identifier is your own URLs, on-screen labels and error messages, as noted under cluster labels above:
- Page and element descriptions are written from the descriptors of your own markup, once per page and control rather than once per visit, so a description outlives any single session.
- Frustration cluster labels are written from a detector name, a page path, the address of a failed request, the message of a JavaScript error, and the description of the element involved — a pattern seen across many sessions, with no session's owner attached.
- Session summaries are the closest an AI feature gets to one person, and they are built from route patterns, page descriptions, which detectors fired, the label of the control each one fired on, and error messages. A summary says what someone was trying to do; the model is never told whose session it was.
- Anomaly summaries are written from statistics — durations, baselines, counts and touchpoint names.
- Script naming is written from a script's address with the query string removed.
The two settings are therefore independent, and neither one changes the other: turning AI off does not reduce what identity is captured, and turning identity off does not change a single AI output. Nor is identity used to train, fine-tune or evaluate any model, ours or a third party's.
How to turn it off
Identity capture is controlled in your application's SimpleLogs configuration, because that is where the data originates — a switch on our side would only discard something your users' browsers had already sent.
identity: {
// Stops the Bearer-token read below, and stops
// identity being attached to logs, timings and
// request headers. Pair it with removing your
// identify() calls — see below. Default: true.
enabled: false,
// Narrower: keep identify(), but stop reading
// claims out of Bearer tokens. Default: true.
fromJwt: false,
}- Want no inference, but still want to say who someone is? Set
fromJwt: falseand keep callingidentify(). Then the only identity we capture is the one you passed us explicitly — a teammate can still attach one by hand, which no setting here reaches. - Want no identity at all? Set
enabled: falseand never callidentify()— and if you have called it before, callclearIdentity()once, so nothing a browser stored earlier rides along. You do not also needfromJwt: false:enabled: falsestops the token read before it happens. What remains is the anonymous browser id, which says a browser came back, not who was using it. - Call
clearIdentity()on logout — it forgets the person and rotates the anonymous id, which matters most on shared and public machines.
Capture, scoring, replay, anomaly detection and every AI feature above keep running unchanged; the dashboard stops being able to answer "who". A few things do change, and one of them can change what gets recorded, so it is worth checking before you flip the switch.
- Session retention rules that test who someone is stop matching, because there is no longer anything for them to test. Rules are first-match-wins, so the effect depends on how yours are written: a rule that keeps your paying customers' sessions stops keeping them, and — the direction worth knowing about — a rule that suppresses recording for your own staff stops suppressing, so those sessions start being recorded. Check Settings → Session Retention first.
- Audience groups are defined entirely in terms of who someone is, so they stop resolving: the Audience tab empties, and the audience filters on anomalies and session replays return nothing.
- Active users on the latency chart stops being drawn, because it counts distinct identified people. Page views and sessions are unaffected, and the line is hidden rather than flattened to zero, so nothing there reads as a traffic collapse that did not happen.
For data you have already captured, each person has a profile page in the dashboard with an erase action. It removes their logs, their timings, and the records of their session recordings, and reports how many it deleted. It does not yet reach everything, and we would rather say so than let you find out during a request: the per-page-view performance samples that also carry identity survive it, so do the stored recording files behind a deleted recording record, and so does any name one of your teammates assigned by hand — and for a session attributed that way, the logs and timings behind it survive with it, because the erase looks for an identity those documents were never stamped with. Clearing a whole team's data, in Settings, covers the first two. For an erasure request that has to account for every copy, write to support@simplelogs.io and we will handle it directly.
AI-Assisted Code Development
We use AI tools to assist in writing code for SimpleLogs. AI helps us move faster and explore more approaches — but it is never the final word on what ships to production.
Every line of code that goes into our core product or published npm packages is subject to a mandatory human review by experienced software engineers. This review is not a formality — engineers are expected to understand, question, and own the code they approve. In addition to human review, all production code must be accompanied by tests, and those tests must pass before any release. AI-written code that cannot be adequately tested does not ship.
This policy applies to our core application and all published SDK packages. Our documentation and example projects follow a lighter process (described below) and are not subject to the testing requirement, though they are still human reviewed.
Core product & npm packages
AI may assist in writing code. Human review required. Tests required. All tests must pass before release.
Documentation & example projects
AI may assist in writing content or code examples. Human review required. Tests are not required.
AI-Assisted Documentation
Much of the documentation for SimpleLogs — including guides, API references, and tutorials — is written with AI assistance. This allows us to produce more comprehensive documentation, keep it up to date with product changes, and free up our engineers to focus on building features.
AI-generated documentation is always reviewed by a human for technical accuracy before it is published. If you spot an error or something that seems off, please let us know at support@simplelogs.io — human oversight is not perfect, and your feedback helps us catch mistakes.
Our Commitment
AI is a powerful tool for building software, and we use it pragmatically to move faster and write better code. But we believe that speed without accountability is a risk — so every AI-assisted output is reviewed by a human engineer before it affects you.
We will keep this page up to date as our practices evolve. If you have questions about how we use AI, we're happy to talk — support@simplelogs.io.