Set up › Instrument your app
Send custom events
Custom events name the moments that matter, such as a finished checkout. They become filters, funnel steps and flow steps, and they help the AI judge.
Instrument with your AI agent
Copy a complete instruction for a coding agent (Claude Code, Cursor, Copilot…) with your repo open. It says how to find the SDK your app already sends to Sequential, where to add the calls, what never to send, and how to check they arrive, and it includes this page.
On this page
What it is for
Autocapture records what happened on screen, such as a click on "Continue". It cannot know what the click meant. A custom event names it, such as checkout_started.
The AI judge answers mostly from the session's events. Without custom events, it must guess what clicks and page paths mean.
What it needs
- A supported SDK that sends to your project. See Check your install.
- The same user id on all of a person's events, so a funnel or flow can follow the person. See Identify your users.
Questions that named events answer
Autocapture records what happened on screen: a page view, a click on "Continue", a form sent. It cannot know what that click meant in your product. A custom event names it: checkout_started, invite_sent, report_exported.
With named events, you can answer questions such as these:
| Question | How to answer it |
|---|---|
| Of the people who started checkout this week, how many finished? | A funnel from checkout_started to checkout_completed. |
In what order do people reach project_created, invite_sent and integration_connected? |
A flow with those three steps. |
| Which sessions started an export and did not finish it? | Ask and Watch. They read your events when they judge sessions. |
Custom events also give the AI judge evidence. The default rubric asks what the person came to do (Intent). It also asks how the session ended (Outcome). The judge answers mostly from the session's events.
Without custom events, the judge sees page paths, clicks, sent forms and errors. It must guess what they mean in your product. With custom events, it reads checkout_completed or payment_declined.
How Sequential handles a custom event
- Your code calls the SDK's capture or track method with an event name. Properties are optional.
- Sequential stores the name exactly as sent. It gives the event the class Custom, because the name is not one of the SDK's own event names. See Events.
- The name becomes a value of the Event Name field. You can filter on it in Events, Sessions and Users. You can use it as a step in Funnels and Flows.
- When Sequential judges a session, each custom event becomes one line for the judge: the name, then its properties as
key=valuepairs.
Decide what to send
- Milestones:
signup_completed,onboarding_completed,project_created - Money:
checkout_started,checkout_completed,plan_upgraded,subscription_cancelled - Your product's core job:
report_exported,invoice_sent,integration_connected - Failures people hit:
payment_declined,export_failed,import_failed
Without failure events, the judge can only guess the outcome. Do not send what autocapture already records. See Sending rules.
Naming rules
| Rule | Write |
|---|---|
object_action, past tense |
checkout_started, report_exported |
Lowercase, words joined by _ |
plan_upgraded |
| Nothing variable in the name | invoice_sent with { currency: 'EUR' } |
Never starts with $ |
checkout_started |
| Short | under 60 characters |
Do not use names that the SDKs use or that Sequential hides. See Names to avoid.
Sending rules
Names not to write, for each naming rule:
| Rule | Not |
|---|---|
object_action, past tense |
startCheckout, export |
Lowercase, words joined by _ |
Plan Upgraded, planUpgraded |
| Nothing variable in the name | invoice_sent_4812, checkout_started_pro |
Never starts with $ |
$checkout |
| Short | a sentence |
- Send each event once, from the code where the moment happens.
- If one action means two things, send both events.
- Filters and funnel steps match the name exactly.
Checkout Startedandcheckout_startedare two different events. - Without failure events, the judge can only guess the outcome from behaviour.
- Name a failure after what failed, for example
checkout_failedorexport_failed. Use a specific outcome such aspayment_declinedonly when the app can tell. - Send only the few moments that show if your product helped a person.
- Do not send events that autocapture already records, such as page views and button clicks.
button_clickedadds nothing. What each SDK supports lists what each SDK autocaptures. - Send
checkout_completedafter your server confirms the payment, not when the button is pressed. Sendexport_failedfrom the error branch. - In component code, make sure that a re-render does not send the event again.
- An upgrade paid through checkout is a
checkout_completedand aplan_upgraded. Then each name means the same thing in every funnel and count. - A name with an id in it is a new event every time.
- Steps and filters cannot match an event's properties. To use a moment as its own funnel step, give it its own event name. Send
plan_upgradedandplan_downgraded, notplan_changedwithdirection: 'up'.
Names to avoid
Names that SDKs use. Names that start with $ belong to the SDKs. Some plain names do too:
| SDK | Taken names |
|---|---|
| Pendo | click, load, focus |
| Amplitude | session_start |
| Smartlook | navigation, error |
Sequential gives an event with one of these names the class of that SDK's own events. It gives some of them the class System and hides them.
Names that Sequential hides. Sequential hides a fixed set of names that carry little meaning. It hides them in the Events list, from any SDK and in any letter case. A replay's Insights does not pass them to the judge. For example: scroll, scroll_depth, hover, resize, focus, blur, heartbeat, ping, idle, set, change, session_start, session_end, app_backgrounded and feature_flag_called.
Sequential still stores the event. All +N above the list shows it. Names like checkout_started and report_exported are on neither list.
Long names. The judge may see only the first 60 characters of a name.
Properties
Add a few short properties that explain the event, such as plan, seats or error_code.
- Do not start a key with
$. - Keep personal words, such as
name,userandemail, out of keys that the judge must read. - Keep values short. The judge sees an event's properties as one line of at most 80 characters.
- For a failure, send a code that you choose, such as
error_code: 'card_declined'. - Watch and Ask do not pass date values to the judge.
- If a value is a web address, Sequential replaces its query values with
[redacted]before it stores the value. It keepsutm_*parameters.
Never send personal data
Keep these out of event names and properties:
- people's names, email addresses, phone numbers and postal addresses
- anything a user typed
- tokens, passwords, card details and one-time links
The key filter does not protect you in a replay's Insights. There, the judge receives up to three of each custom event's properties, whatever their names.
Send who the user is with identify, not in event properties. See Identify your users.
Property rules: exact behaviour
- Other useful properties are
format,stepanditem_count. - Mixpanel drops properties whose keys start with
$. The judge and the property preview on the Events page skip them. - The full list of personal words is in Which properties the judge reads.
- If the app has no error code at that point, send the HTTP status or a small fixed set that you define, for example
networkorhttp_402. Do not send the message that your server returned, because messages vary and can contain personal data. - Sequential stores a value written as a date and time as a date. See Which properties the judge reads.
Which properties the judge reads
The judge skips a property if its key contains one of these words: email, mail, phone, tel, password, pass, token, secret, address, addr, name, ip, user, username, account, ssn, iban, card. Sequential calls this the key filter.
Sequential splits a key into words at _, -, ., spaces and capital letters. So the judge skips plan_name, userRole and account_type. It reads plan, role, workspace_tier and description.
Dates. Sequential stores a value written as a date and time, such as 2026-10-01T09:00:00Z, as a date. Watch and Ask do not pass it to the judge. Raw event data still shows it.
Where the key filter does not apply
- The key filter applies wherever the judge reads events from storage: Watch, Ask and the rubric's Try it preview.
- The Insights tab of a replay builds its own list in the browser. There, the judge receives up to three of each custom event's properties, whatever their names. See AI and third parties.
Web addresses in property values
If a property value is a web address, Sequential replaces its query values with [redacted] before it stores the value. It keeps marketing parameters such as utm_*. This does not filter personal data. Keep personal data out of properties. See What Sequential keeps from page URLs.
Add the calls
Use the SDK that already sends your app's data, not a second one. If there is none, see Install Sequential.
- Amplitude: leave batching (
useBatch) off. Batched events do not reach Sequential today. - Pendo: not checked against a live Pendo agent yet. The judge sees the event name alone.
Sequential SDK
sequential.capture('checkout_completed', { plan: 'pro', seats: 5 });capture() throws an error on a name that starts with $. Do not rely on that error. Some calls drop the event silently. See Sequential SDK: exact behaviour.
To add properties to every event, register super properties:
sequential.register({ experiment: 'onboarding_b' });Super properties last only as long as the page. So call register() on every page load. Register only a few short ones. Sequential shows super properties first, so too many can hide the event's own properties.
sequential.reset() clears super properties. It also starts a new anonymous visitor and a new session. So call it only on sign-out.
Sequential SDK: exact behaviour
Dropped events
- If a call with a
$name was queued before the SDK loaded, the SDK skips it silently. It does not throw. - If the properties cannot be turned into JSON, the SDK drops the event silently. Examples are a
BigIntor an object that refers to itself. - In TypeScript, sequential.js has no published type declarations. Read it through
windowwith a narrow local type, as the Sequential SDK page describes.
Super properties
- Super properties are for properties that belong on every event. An example is the experiment variant that a visitor is in.
- The SDK adds super properties to every later event from the page, autocaptured events included.
- If
capture()passes the same key, thecapture()value wins. - Super properties come before the event's own properties. The hover preview on the Events page and a replay's Insights show only the first three. The judge's 80-character line fills in the same order. So each super property can take the place of one of the event's own properties.
sequential.unregister('experiment')removes one super property.sequential.reset()clears them all. It also starts a new anonymous visitor and a new session. So call it only on sign-out.
PostHog (web)
posthog.capture('checkout_completed', { plan: 'pro', seats: 5 });Mixpanel
mixpanel.track('checkout_completed', { plan: 'pro', seats: 5 });Amplitude
amplitude.track('checkout_completed', { plan: 'pro', seats: 5 });Pendo
pendo.track('checkout_completed', { plan: 'pro', seats: 5 });Smartlook
smartlook('track', 'checkout_completed', { plan: 'pro', seats: 5 });Per-SDK differences
PostHog. Sequential keeps the properties on the event. In a mobile app, use the capture call of PostHog's SDK for your platform. See Mobile apps.
Mixpanel. Mixpanel drops properties whose keys start with $, except autocapture's element properties.
Amplitude. Leave batching (useBatch) off. Batched events do not reach Sequential today.
Pendo. Pendo support is the least proven. The event should arrive with your event name. This has not been checked against a live Pendo agent yet. If your events appear with the name track, the event name was lost.
Sequential stores Pendo properties as user properties, not on the event. So the judge's line for a Pendo event is the name alone.
Check it arrived
- Trigger the moment in your app.
- Open Events.
- Check that the second date in the query card is today's date in UTC.
- Click + condition. The builder opens under the sentence.
- Pick the Field Event Name.
- In the Value box, pick your event name.
- Click Run. This applies the dates and the filter together. The row shows a Custom badge and your event name.
If the row appears only under All +N, Sequential hides the name. Rename the event.
Check it arrived: exact behaviour
- The dates are at the top of the query card on Events.
- All +N is above the list.
- The date range includes its whole end date, in UTC. So by default, it includes today's events.
- When you click in the Value box, it lists the event names that Sequential has received, most frequent first.
- To see the properties, click the icon at the end of the row (Event details). The Properties table lists them. Raw event data shows the stored event.
Build a funnel from an event
- Open Funnels and click + Add step.
- In the new step, click + Condition.
- For the Field, pick Event Name.
- For the Value, type your event name.
- Add the next step in the same way.
- Click Run.
Limits
- Filters and steps match an event name exactly. They cannot match event properties.
- On Retention, a custom event can be the start event or the return event.
- The judge reads at most 255 events per session. After plain clicks, custom events are among the next events that it leaves out.
- Sequential does not judge a session with fewer than 3 events that the judge can read.
- Custom events do not guarantee an answer. To ask about your own moments, add questions in Customise the rubric.
Limits: exact behaviour
- There is no "contains" or "starts with" match on an event name.
- Event Property has a type and an operator, for example Number >
5or Text containspro. is on Text matches the exact text of the whole value. See Property conditions. - On the Retention page, set the start event or the return event to your custom event, with an Event Name condition. For example: people who signed up came back to
invoice_createdon day 7. With no conditions, each of them is any event. - If a session is longer than 255 events, Sequential leaves out plain clicks first. Custom events are among the next events that it leaves out.
- Custom events give the judge evidence. How much one event changes an answer depends on the model and on your questions.
Count each event name
To see a count per event name, open /events?breakdown_by=event_name. To choose the dates, add &from_date= and &to_date=, each written YYYY-MM-DD in UTC. The range includes the to_date day.
The grouped by list on Events does not offer Event Name.