Event catalog
Every event the SDK sends, when and why.
Every event name the SDK can send. Events marked automatic need no code. The rest are sent when your app calls the matching method.
Fields on every event
| Field | Description |
|---|---|
event_id | Unique ID. Retries with the same ID are stored once. |
name | The event name, e.g. element_tapped. |
occurred_at | When it happened on the device (ISO 8601). If the phone’s clock is more than 10 minutes ahead, the server’s time is stored instead. |
anonymous_user_id | Random per-device ID. |
identified_user_id | Your user ID after identify, otherwise null. |
session_id | The visit this event belongs to. |
screen | The screen open at the time, with IDs, emails, phone numbers and tokens replaced, e.g. /product/:id. |
platform | ios, android, web or unknown. |
app_version / sdk_version | Your app version, from the appVersion prop (null if you don’t pass it), and the SDK version. |
properties | Event-specific details, listed below. |
Visits & app lifecycle
How often people open your app and how long they stay. This is the foundation every other number is measured against.
app_session_started
Visit started · Automatic. Every time the app is opened: when it is launched, and when someone comes back after more than 2 minutes away. Also when a different person signs in, or the app signs someone out.
Each one is a visit. Comparing visits to people shows how often they come back. It also carries the device details shown on each user’s profile.
| Property | Meaning |
|---|---|
start_reason | cold_start (the app was launched), resumed_after_timeout (came back after more than 2 minutes away) or user_changed (another person signed in, or the signed-in person signed out, so their visits are kept apart) |
away_ms | How long they were away, when they came back after a break |
device_model / device_brand | e.g. iPhone, Pixel 8. Never a serial number or device ID |
os_name / os_version | e.g. iOS 18.1 |
screen_width / screen_height | Screen size in points |
is_tablet | true on tablets |
locale / timezone | e.g. de-DE and Europe/Berlin. Not GPS location |
app_first_opened
First open · Automatic. Once per device, the very first time the app runs with Riveora.
Separates new users from returning ones, so you can see how many new people you get and whether they come back.
app_foregrounded
Came back to the app · Automatic. When someone returns to the app within the same visit, for example after switching apps for a moment.
Separates real time in your app from time it sat in the background.
| Property | Meaning |
|---|---|
away_ms | How long they were away |
app_backgrounded
Left the app · Automatic. When the user leaves the app, locks the phone or switches apps. Not when a system pop-up, like a permission prompt, covers it for a moment.
Pauses screen timers so we never count time the user was not looking.
Screens
Which screens people visit and how long each one is actually on screen. Tells you where attention goes.
screen_viewed
Screen viewed · Automatic. Each time a new screen is shown. With Expo Router this happens on every navigation.
Builds your list of screens automatically and counts how many people reach each one.
| Property | Meaning |
|---|---|
screen | The route, with IDs replaced, e.g. /product/:id. Sent in the event’s screen field, not in properties |
screen_visit_id | Links this view to its matching "screen left" event. Also an event field |
manual | true when your code marked the screen with Riveora.screen() |
screen_visibility_ended
Screen left · Automatic. When the user navigates away from a screen or it closes. Leaving the app only pauses the timer; if they come back after more than 2 minutes, the screen ends in the old visit.
Tells us how long the screen was really visible, which is a better signal of interest than a simple view count.
| Property | Meaning |
|---|---|
foreground_visible_ms | Milliseconds the screen was on screen with the app in front |
tap_count / swipe_count | How many taps and scrolls happened during the visit |
reason | navigated_away, app_background (the visit ended while the app was away), paused or unmount |
Taps, frustration & crashes
Every tap, which button it was, and where on the screen. Also rage taps and crashes. This is what lets you follow each person’s journey and see how every screen is used.
element_tapped
Tap · Automatic. Every time the user taps anything in your app: buttons, links, cards, images, text fields.
Shows what people actually do on each screen and powers each user’s step-by-step journey. Taps on things that aren’t buttons reveal where people expect something to happen.
| Property | Meaning |
|---|---|
element_label | What was tapped, e.g. “Add to cart”. From the accessibility label, else a button’s short text (up to 40 characters, icons and badges left out), else its testID, or the name your app gives it with <RiveoraLabel>. Plain text and text-heavy rows are never used. In lists and grids the text is only used when it’s the same in the nearest items (“Delete”), so names, searches and phrase words are never sent. Single characters, lone numbers and keypad keys get no label. Numbers of 3+ digits are masked; emails and tokens dropped. Text inside <RiveoraIgnore> is never used |
label_source | Where the label came from: accessibility, text, test_id, placeholder (a text field’s hint) or explicit (<RiveoraLabel>) |
element_type | button, input (a text field), switch, text, image or view (any other area) |
element_id | The element’s testID, if your app sets one, e.g. checkout-button. In lists only when the nearest items have the same one, and on keys and list items every digit is masked (pin-key-#) |
component | Your component it lives in, e.g. ProductCard |
has_handler | false when the tapped thing does nothing |
x / y | Where the finger landed, as a share of screen width and height, rounded to 1%. Empty for keypad keys and for the letter keys of an in-app keyboard, so a PIN or a typed word can’t be worked out from where people tapped |
rage_tap
Rage tap · Automatic. When someone taps the same spot 3 or more times within one second (each tap within 40 points of the first).
The clearest sign of frustration: a button that’s slow, broken or gives no feedback.
| Property | Meaning |
|---|---|
tap_count | How many taps were in the burst |
app_error
Crash / error · Automatic. When your app hits an unhandled JavaScript error, including fatal crashes.
Shows which screen and which users were affected, so you can fix what hurts most first.
| Property | Meaning |
|---|---|
error_type | The kind of error, e.g. TypeError |
message | The error message, up to 200 characters, with emails, long numbers, tokens, the query part of web addresses and files on the device masked. No stack trace |
is_fatal | true if the app crashed |
request_failed
Request failed · Automatic. When a request from your app gets an error status (400 or above) or no response at all.
A coupon that won’t apply or a checkout that errors loses sales without crashing. Riveora shows how many people left right after.
| Property | Meaning |
|---|---|
method | GET, POST, … |
host | The server, e.g. api.yourapp.com. IP addresses, local names and personal dynamic-DNS names are shown as (private) |
path | The path with ids, emails, phone numbers and tokens masked. Query strings are never recorded |
status | HTTP status, or 0 if there was no response |
duration_ms | How long it took |
slow_request
Slow request · Automatic. When a request succeeds but takes 3 seconds or longer.
People give up on spinners. Slow product or checkout requests often cost more sales than crashes.
| Property | Meaning |
|---|---|
method | GET, POST, … |
host | The server |
path | The path with ids, emails, phone numbers and tokens masked |
status | HTTP status |
duration_ms | How long it took |
Onboarding
Whether new users finish your onboarding, and which step they leave on. Onboarding is usually the biggest drop-off in an app.
onboarding_started
Onboarding started · Sent by your code. When a new user begins your onboarding.
The starting point of the onboarding funnel. Everyone who starts is counted, so drop-off can be measured.
Riveora.onboarding.start('new_user_v1')| Property | Meaning |
|---|---|
onboarding_flow_id | Which onboarding flow this is |
onboarding_step_viewed
Onboarding step viewed · Sent by your code. Each time a step of the onboarding is shown.
Shows exactly which step people leave on, so you know which one to shorten or rewrite.
Riveora.onboarding.stepViewed('new_user_v1', 'pick_goal', 0)| Property | Meaning |
|---|---|
flow_id | Which onboarding flow |
step_id | A name for the step, e.g. pick_goal |
step_index | Position of the step, starting at 0 |
onboarding_completed
Onboarding completed · Sent by your code. When the user finishes onboarding.
The success moment of the funnel. Completion rate is one of the strongest predictors of retention.
Riveora.onboarding.complete('new_user_v1')| Property | Meaning |
|---|---|
flow_id | Which onboarding flow was completed |
Paywalls
How often your paywall is shown, how long people look at it, and how they leave it. Tells you if the offer is seen before it is dismissed.
paywall_opened
Paywall shown · Sent by your code. When your paywall or upgrade screen appears.
Counts impressions per paywall and records where it was shown from, so you can see which entry points work.
Riveora.paywall.open({ paywallId: 'main_offer', source: 'results_screen' })| Property | Meaning |
|---|---|
paywall_id | Your name for the paywall, or the RevenueCat offering it shows |
offering_id | The RevenueCat offering shown, when you pass one |
paywall_visit_id | Links this view to its matching close |
source_screen | Where the user was when it opened |
trigger | Why it opened, e.g. unlock_more_matches |
paywall_closed
Paywall closed · Sent by your code. When the paywall goes away, whether the user closed it or bought something.
Measures how long people looked at the offer and how they left it. Very short views usually mean the offer was not read.
Riveora.paywall.close(visitId, { reason: 'dismissed' })| Property | Meaning |
|---|---|
paywall_id / paywall_visit_id | Which paywall, and which view of it |
duration_ms | How long the paywall was open |
reason | dismissed (the default), purchased, restored, presentation_failed or background. TrackedPaywall and usePaywallTracking send unmounted when they close because the component went away |
Your own events
Anything specific to your product, like "item saved" or "search performed".
your_event_name
Your own event · Sent by your code. Whenever your code calls Riveora.track(). The event is sent under the name you pass, e.g. item_saved.
Lets you measure actions unique to your product alongside the built-in ones.
Riveora.track('item_saved', { category: 'shoes' })