User impersonation side effects: exclude impersonation from analytics, emails and jobs

Exclude impersonation from analytics, emails, last-seen, billing, jobs and webhooks: tag requests with the real actor, then suppress or attribute each one.

Every system downstream of a login assumes the person holding the session is the person it belongs to. When support impersonates a customer, that assumption breaks. To exclude impersonation from analytics, emails, usage meters and background jobs, derive one verified “support is acting” flag from the session on your server, carry the real actor with every request and job, and have each integration decide whether to suppress the effect, attribute it, or let it through.

None of this is exotic. It’s an inventory problem. The side effects are spread across client SDKs, server helpers, queues and outbound webhooks, and each one needs a deliberate answer before a customer reports it.

What side effects does user impersonation cause?

A user impersonation side effect is anything your application does because a session exists, rather than because the customer chose to do it. WorkOS published a thorough inventory (opens in a new tab) of these, from analytics identify calls to lifecycle email and queued jobs. Here’s a working list with a sensible default for each:

Side effectWhat goes wrongSensible default
Product analytics and session countsSupport clicks inflate the customer’s usage and skew funnelsSuppress, or tag and filter
Error trackingErrors the agent triggers appear as the customer’sTag with support context
Lifecycle and marketing emailA support visit completes an onboarding step and advances a drip campaignSuppress
Transactional notifications (“you changed X”)The customer is told they did something they didn’t doSuppress the self-action notice; decide separately about a notice of access
Last seen, last login, read receiptsInactive customers look active; unread items become readSkip the update
Billing and usage meteringSupport activity consumes the customer’s quota or billExclude, or meter to an internal bucket
Background jobsWork runs later as the customer with no record of who started itAttribute at enqueue time
Webhooks to the customer’s systemsEvents land in their tools attributed to their userDepends on scope; see below

Not every row applies to every product. The point is to answer each one on purpose.

Where should the impersonation flag come from?

Take it from verified authentication state on the server, never from a header, query parameter or local storage value the browser can set.

Most auth providers already mark impersonated sessions:

Turn that into a small, boring object that every layer can read: isSupportSession, the actor reference, the subject reference and the support session ID. Put it on your request context on the server, and render it into the initial page payload for the browser.

Two details decide whether this works in practice.

Timing. Analytics SDKs usually initialize on page load. If the flag arrives in a later fetch, the identify call has already fired. Ship the flag with the session so it’s available before any tracking code runs.

Tabs. Don’t rely on browser-only state. Devora’s frontend SDK, for example, reports isImpersonating() for a validated session in this tab, as its JavaScript reference (opens in a new tab) notes. Its per-tab capability is never written to browser storage, so without a session bridge (opens in a new tab), a reload or new tab runs as the impersonated user with no banner, scope enforcement or capture. A suppression check that only reads browser state would miss that tab. A flag derived from the server session wouldn’t.

Write the check so a missing or malformed flag leaves normal behavior in place. A bug in your suppression code should mean one support session gets tracked by mistake, not that tracking stops for every customer.

How do you exclude impersonation from analytics?

Skip identify for impersonated sessions, then either opt the session out of capture or tag every event so you can filter it. Pick one approach per tool and apply it on the client and the server.

Opting out. Most analytics SDKs have a documented switch:

  • PostHog’s posthog.opt_out_capturing() prevents all data from being captured and sent, including autocapture, manual captures and session replays, per PostHog’s data collection docs (opens in a new tab). PostHog persists the opt-out in local storage or a cookie, so call opt_in_capturing() when the staff member is back in their own session.
  • Mixpanel’s mixpanel.opt_out_tracking() stops the SDK sending data for the current instance, and opt_out_tracking_by_default lets you start opted out, as its JavaScript SDK docs (opens in a new tab) describe.
  • Segment’s Analytics.js supports (opens in a new tab) source middleware through addSourceMiddleware, which can enrich an event or drop it by returning null.

Opt-out switches don’t always cover everything analytics-adjacent. WorkOS points out that PostHog’s opt-out suppresses capture but doesn’t stop feature flag evaluation, which can still enroll the customer in an experiment. Check flags, surveys and experiments in whichever SDK you use.

Tagging instead. If you want to measure support work, keep the events but add a property such as support_session: true and exclude it from customer-facing reports. This keeps the data, but only works if every dashboard actually applies the filter.

Server-side tracking. Events sent from your backend usually go through a separate helper. Gate it on the same request-context flag.

URLs. Impersonation links often carry a one-time code. Devora’s SDK removes its exchange parameter immediately, and its docs say not to forward (opens in a new tab) it to analytics, error reporting or another URL. Make sure your page-view tracking doesn’t record the landing URL before that happens.

Should impersonated sessions send emails and notifications?

Suppress the noise, keep the signal. Emails that describe the customer’s own actions (“you updated your billing address”) or advance lifecycle sequences should not fire for support activity. The customer didn’t do it, and a confusing alert can look like an account takeover.

Notifications also act as the customer’s independent check on what happened to their account. WorkOS makes this case (opens in a new tab), arguing that suppression should depend on session type computed from the token, not on a control the operator can toggle. A reasonable middle ground:

  • Suppress self-action notices and lifecycle triggers for impersonated requests.
  • Decide, as a policy, whether customers get a notice that support accessed their account.
  • Never give support agents a way to cancel notifications for a session they’re running.

Better still, block the actions that would trigger security notices. Password, MFA, email, role and billing changes generally shouldn’t happen in an impersonated session at all. The read-only impersonation guide covers how to enforce that on the backend.

What about last seen, read receipts and usage metering?

Skip the update for impersonated requests. These values feel harmless but drive real decisions.

Last seen and last login feed churn analysis, inactive-account cleanup, “we miss you” campaigns and seat reporting. A customer who hasn’t logged in for months shouldn’t look active because support helped them. Store support visits in a separate field if you want them.

Read state is trickier. Devora’s own scope docs (opens in a new tab) give marking a notification as read as an example of a write that’s operationally read-only, which a team might allow as a read-only exception. Mechanically that’s true. From the customer’s side, though, an unread item they were saving has quietly disappeared. Decide whether support’s views should mark anything as read, and if not, skip the write rather than allowlisting it.

Billing, quotas and rate limits. If you meter API calls, exports, seats or AI usage, support activity shouldn’t count against the customer. Exclude impersonated requests from the meter, or record them against an internal account so you can still see the cost.

How do background jobs and webhooks keep actor context?

Capture the actor when the job is enqueued, not when it runs. A job queued during a support session may run minutes or hours later, after the session has ended. By then there’s no session to inspect.

Put these fields in the job payload:

  • Staff actor reference and customer subject reference.
  • Support session reference (from verified context, never a token).
  • Scope at enqueue time.

The worker then attributes its effects to both identities and decides whether to re-check that the session is still allowed. In Devora, every ending triggers a signed termination request (opens in a new tab) to your backend, retried if delivery fails and sent even with no tab open, so you can record which session IDs are revoked and have workers consult that list. The audit log guide covers recording “accepted” and “completed” as separate events.

Webhooks to customer systems need a scope-based answer. In a read-only session, nothing should emit them, because nothing should change. In a write session where support fixes data, the customer’s integrations usually need the event to stay in sync, so suppressing it creates drift. Emit it, and keep the support attribution in your own audit trail. If you add an “initiated by support” field to the payload, treat it as a schema change and document it.

Test each side effect in staging

Run one impersonated session against a staging account with every integration pointed at test destinations. These are pass conditions to check, not results we’ve run.

ScenarioExpected outcome
Page load in an impersonated sessionNo identify call; events suppressed or tagged before the first one is sent
Same session, server-side tracking pathEvent suppressed or tagged, same as the client
New tab or reload during the sessionSame suppression; the flag comes from the server session
Support views an onboarding pageNo lifecycle step completed, no drip email queued
Support views a notification listUnread state unchanged, unless you chose otherwise
Customer’s last-seen valueUnchanged after the session
Metered action during a write sessionNot counted against the customer’s usage
Job enqueued during the sessionPayload carries actor, subject and session reference
Staff member’s own session after impersonation endsAnalytics opted back in and attributed to staff

Where Devora fits

Devora handles the access side: requests with a reason, approval by an approver or admin in your organization, read-only or read-and-write scope, a time limit, access history, optional recording and a backend scope guard. It passes your backend verified context (opens in a new tab) with the actor, subject, session ID and scope for every impersonated request.

It doesn’t know about your analytics, email provider, meters or queues, and it doesn’t suppress anything in them. That code is yours, and the context is what makes it straightforward. For the wider set of responsibilities, see the multi-tenant impersonation checklist.

If you want that context without building the access workflow yourself, create a Devora account and try one staging session against the table above.

Sources

Quick answers

Common questions, answered clearly.

Direct answers to the questions teams usually ask when evaluating this approach.

How do I exclude impersonated sessions from product analytics?

Decide on the server whether the session is impersonated, using verified auth state, and send that flag down with the page. Before your analytics SDK initializes, skip identify and either opt the session out of capture or tag every event as support activity. Check server-side tracking calls too, because they bypass the browser SDK.

Should impersonated sessions send emails to the customer?

Not the ones that describe the customer's own actions or advance lifecycle campaigns. Security-relevant notices are different: if a support session really changes something important, the customer may need to know. Make that decision from the session type on the server, not from a switch the support agent controls.

Should support activity update a customer's last-seen time?

No. Last-seen and last-login values feed churn reports, inactivity cleanup and seat counts. Skip the update for impersonated requests, or store support visits in a separate field.

What should a background job enqueued during impersonation record?

The staff actor, the customer subject, the support session reference and the scope, captured when the job is enqueued. The worker can then attribute its effects correctly and decide whether to re-check that the session is still allowed before it runs.

Does Devora suppress analytics or emails during impersonation?

No. Devora gives your backend verified context for each impersonated request, including actor, subject, session ID and scope, and enforces read-only or write scope on routes behind its guard. Deciding what your analytics, email and billing code does with that context is your application's job.

Put it into practice

Give your team context.Keep control of access.

Bring approvals, scoped sessions, and access history into your support workflow.