Skip to content
Docs
FA
Sign in
Start here
  • Overview
  • Quickstart
  • Concepts
Collect data
  • Designing events
  • Event dictionary
  • Placing events
  • Identity
  • Web SDK
  • Android SDK
  • Devices and push
  • Server to server
  • Product catalogue
  • Webhooks
Engage customers
  • Segments
  • Journeys
  • Transactional
  • Consent and caps
  • In-app and inbox
Analyze and export
  • Reports and exports
Developer reference
  • API reference
    • Ingest endpoints
    • Management API
  • Errors
  • Limits
  • OpenAPI
Developer tools
  • MCP server
  • Working with an agent
Privacy and changes
  • Personal data
  • Versioning

An event dictionary for each kind of business

Ready-made event and property lists for online retail, super-apps, fintech, travel, education and subscription media. Copy and start.

This page is written to be copied. Six kinds of business, and for each one a list of events with their properties that you can take as it stands and start with. The reasoning behind the choices is in designing events; if you have not read it, read at least revenue, because that is the one place where a property name changes a number on a person's profile. And to get this list actually running on your own site or app, see placing events. And if you want to recommend products in your messages, the id you put in product_id here has to match the product catalogue.

#How to read this

The "status" column in every table has two values and the difference matters:

  • Standard means the platform declares this name and the panel gives it a Persian label. That is the whole of it.
  • Proposed means the name is our convention. The platform does not know it and treats it like any other name. You may change it; just change it before the first send.

One common misreading, closed here: "standard" does not mean "in the event picker". Until the tenant's real schema loads, the segment builder shows ten fixed names (order_completed, product_viewed, product_added_to_cart, checkout_started, order_refunded, searched, app_opened, signed_up, message_opened, message_clicked) and after that it builds the list from your own events. The journey builder labels only eight. A standard name you have never sent appears in no list at all.

Three things to keep separate about the standard list:

Only three names actually have behaviour. order_completed adds the amount to the profile's total_revenue, increments order_count and moves last_order_at. order_refunded and order_cancelled subtract the absolute amount and decrement the order count, both floored at zero. The rest of the standard names have no behaviour at all.

Standard means recognised, not automatic. No event is sent by itself. The names app_installed, app_opened, app_updated, app_removed, session_started and session_ended are declared in the code as "lifecycle events the SDKs emit automatically", and no SDK emits them. If you want them, send them.

**Do not send the message_* names yourself.** Segmentic's own workers write them, and they are listed under what Segmentic writes.

#The names the platform knows

NamePanel labelWhat the code does
order_completedخریدraises the profile's revenue and order count, moves last_order_at, and is the orders figure in the daily rollup
order_refundedمرجوعیlowers revenue and order count, floored at zero
order_cancelledلغو سفارشthe same as order_refunded
product_viewedمشاهده محصولnothing. A label
product_added_to_cartافزودن به سبدnothing
product_removed_from_cartحذف از سبدnothing
cart_viewedمشاهده سبدnothing
checkout_startedشروع پرداختnothing
searchedجستجوnothing
signed_upثبت‌نامnothing
signed_inورودnothing
app_openedباز کردن اپnothing, and no SDK sends it
page_viewedمشاهده صفحهthe default name of a page message with no name
screen_viewednonethe default name of a screen message with no name

#The properties you put on every event

Before the tables, five rules that are the same across all six businesses.

Do not resend the context. context already carries device, OS, app version, page, campaign and timezone, and the collector puts each in its own column. A platform property on every event is a worse copy of device_type.

Send identifiers as strings. "order_id": "A-100294", not "order_id": 100294. A number is stored as text too, but a string joins against your own system from the start.

Send numbers as numbers and booleans as booleans. "quantity": 3, not "quantity": "3". A numeric-looking string never reaches the numeric map, and a "greater than" filter on it never answers.

Pick one language for property values and stay with it. Values are stored as sent, with Persian normalisation only. gold and طلایی are two values and do not land in the same segment.

Use revenue, total, value, and the pair price with quantity, only on an event where money moved. Revenue is extracted from any event carrying those keys and added to that person's lifetime value. For an amount that is not real money, use another name. The tables below deliberately use unit_price, cart_total and amount, none of which is reserved.

#Online retail

Event nameStatusWhen to send itProperties
product_viewedstandarda product page openedproduct_id string, product_name string, category string, brand string, unit_price number, currency string, in_stock boolean
searchedstandarda search was submittedquery string, results_count number, sort string, filters string
product_added_to_cartstandardadded to the basketproduct_id string, product_name string, unit_price number, quantity number, cart_size number
product_removed_from_cartstandardremoved from the basketproduct_id string, quantity number, cart_size number
cart_viewedstandardthe basket page openedcart_size number, cart_total number, currency string
checkout_startedstandardthe payment step was enteredcart_size number, cart_total number, currency string, shipping_method string, coupon_code string
order_completedstandardpayment succeededorder_id string, revenue number, currency string, item_count number, shipping_cost number, discount number, coupon_code string, payment_method string
order_refundedstandarda refund was approvedorder_id string, revenue number meaning the amount returned, currency string, reason string
order_cancelledstandardthe order was cancelled before dispatchorder_id string, revenue number, currency string, cancelled_by string
signed_upstandardregistration completedmethod string, referral_code string
signed_instandarda successful sign-inmethod string
order_shippedproposedthe parcel was handed to the carrierorder_id string, carrier string, hours_since_order number
order_deliveredproposedthe parcel reached the customerorder_id string, carrier string, days_since_order number
review_submittedproposeda review was postedproduct_id string, rating number, has_photo boolean
wishlist_item_addedproposedadded to the wish listproduct_id string, unit_price number
back_in_stock_requestedproposedasked to be told when it returnsproduct_id string

The default funnel this list supports: product_viewed, then product_added_to_cart, then checkout_started, then order_completed. The abandoned-basket segment is the same list: anyone with a product_added_to_cart in the last seven days and no order_completed.

One complete order
curl -X POST https://in.segmentic.net/v1/track \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer wk_seg_..." \
  -d '{
    "message_id": "b3d51f28-4c6a-4b1e-9d70-2f8a3c5e7d10",
    "user_id": "u_88123",
    "event": "order_completed",
    "timestamp": "2026-08-07T10:02:41.000Z",
    "properties": {
      "order_id": "A-100294",
      "revenue": 2450000,
      "currency": "IRR",
      "item_count": 3,
      "shipping_cost": 49000,
      "discount": 150000,
      "coupon_code": "NOWRUZ",
      "payment_method": "gateway"
    }
  }'
Response
{"status":"ok","accepted":1}

#Super-app and ride hailing

Event nameStatusWhen to send itProperties
app_openedstandardevery time the app comes to the foreground. You have to send itis_first_open boolean, source string
service_selectedproposedthe user opened one of the super-app's servicesservice string
ride_requestedproposeda ride was requestedride_id string, service_class string, origin_city string, destination_city string, estimated_fare number, surge_multiplier number
ride_acceptedproposeda driver acceptedride_id string, wait_seconds number
ride_cancelledproposedthe ride ended before completionride_id string, cancelled_by string, seconds_to_cancel number
ride_completedproposedthe ride finished and the fare was settledride_id string, revenue number, currency string, distance_km number, duration_minutes number, payment_method string
ride_ratedproposeda rating was submittedride_id string, rating number
order_completedstandarda food or grocery order was paid fororder_id string, revenue number, currency string, vendor_id string, item_count number, service string
wallet_topped_upproposedthe wallet was topped uprevenue number, currency string, method string
promo_appliedproposeda promotion code was appliedcoupon_code string, discount number, service string
support_ticket_openedproposeda support ticket was openedtopic string, service string, ride_id string

Using revenue on wallet_topped_up and ride_completed is deliberate. The code explicitly allows for this: revenue accrues from any event, not only orders, because a customer may model a subscription or a top-up as its own event. Note though that only order_completed increments order_count, so the profile's order count does not count rides.

Put service on every super-app event. Without it you cannot ask for "took a taxi but never ordered food".

#Fintech and payments

Event nameStatusWhen to send itProperties
signed_upstandardregistration completedmethod string, referral_code string
kyc_startedproposedthe user entered the verification flowlevel string, hours_since_signup number
kyc_submittedproposeddocuments were uploadedlevel string, document_type string
kyc_approvedproposedverification passedlevel string, hours_to_approve number
kyc_rejectedproposedverification was refusedlevel string, reason string
card_linkedproposeda bank card was attachedbank string, card_type string
transfer_completedproposedmoney was transferredtransfer_id string, amount number, currency string, destination_type string
bill_paidproposeda bill was paidbill_type string, amount number, currency string
payment_completedproposeda payment at a merchant went throughrevenue number meaning your fee, currency string, merchant_id string, category string, amount number
loan_application_startedproposeda credit application beganamount number, term_months number
loan_approvedproposedcredit was grantedamount number, term_months number, days_to_decision number
investment_order_placedproposeda buy or sell order was placedasset string, side string, amount number

amount appears here instead of revenue on purpose. The value of a transfer is not your money: call it revenue and every user's total_revenue becomes their account turnover, so the "high-value customer" segment becomes "moves a lot of money around". On payment_completed both appear, because you want both figures: revenue is the fee that is yours and amount is what the user paid.

Do not put card numbers, IBANs, cvv values or payment tokens in properties. Event properties are shown verbatim to your support team on the user timeline and they appear in the CSV export. If you need it, put the last four digits in a separate property such as card_last4.

#Travel and booking

Event nameStatusWhen to send itProperties
searchedstandarda route or stay search was submittedorigin string, destination string, depart_date string, return_date string, passengers number, results_count number
product_viewedstandarda flight, hotel or tour was openedproduct_id string, product_type string, unit_price number, currency string, star_rating number
checkout_startedstandardthe booking flow begancart_total number, currency string, passengers number, product_type string
order_completedstandardthe booking was confirmed and paid fororder_id string, revenue number, currency string, product_type string, origin string, destination string, depart_date string, days_to_departure number
order_cancelledstandardthe booking was cancelledorder_id string, revenue number, refund_amount number, days_to_departure number
trip_startedproposedthe departure day arrivedorder_id string, product_type string, destination string
trip_completedproposedthe trip endedorder_id string, product_type string, nights number
price_alert_createdproposeda price alert was setorigin string, destination string, target_price number
booking_modifiedproposeddates or passengers changedorder_id string, change_type string, fee number

days_to_departure is stored on the event rather than computed at query time. The difference is that months later you can still ask "how many people booked within three days of the flight", whereas with only depart_date you would have to subtract two strings at report time, and a date string in the property map is text.

#Education

Event nameStatusWhen to send itProperties
signed_upstandardregistration completedmethod string, referral_code string
course_viewedproposeda course page openedcourse_id string, course_name string, category string, unit_price number, is_free boolean
course_enrolledproposedenrolment completedcourse_id string, is_free boolean
order_completedstandarda course or subscription was boughtorder_id string, revenue number, currency string, course_id string
lesson_startedproposeda lesson was openedcourse_id string, lesson_id string, lesson_index number
lesson_completedproposeda lesson was watched to the endcourse_id string, lesson_id string, lesson_index number, watch_seconds number
quiz_submittedproposeda quiz was submittedcourse_id string, quiz_id string, score number, passed boolean
assignment_submittedproposedan assignment was handed incourse_id string, assignment_id string, days_late number
certificate_issuedproposeda certificate was issuedcourse_id string, days_to_complete number
course_abandonedproposedno lesson for a while and you have decided that counts as abandonedcourse_id string, last_lesson_index number, days_idle number

course_abandoned has to be decided by your own system and sent from your server; the platform does not manufacture an event out of the absence of one. If you would rather not build it, do the same thing with a journey that waits after lesson_completed.

Do not put course progress on the profile as a trait unless a user only ever has one course. A trait is one value per person, so with two courses the second erases the first.

#Subscription media

Event nameStatusWhen to send itProperties
signed_upstandardan account was createdmethod string
content_viewedproposedplayback or reading startedcontent_id string, content_type string, title string, genre string, is_premium boolean
content_completedproposedwatched or read to the endcontent_id string, watch_seconds number, completion_ratio number
paywall_viewedproposedthe paywall was showncontent_id string, plan_shown string
trial_startedproposeda trial beganplan string, trial_days number
subscription_startedproposedthe subscription went live and was chargedplan string, revenue number, currency string, billing_period string
subscription_renewedproposedan automatic renewal succeededplan string, revenue number, currency string, renewal_number number
subscription_cancelledproposedthe user cancelledplan string, reason string, days_subscribed number
payment_failedproposeda renewal failedplan string, attempt number, failure_code string
download_startedproposeddownloaded for offline viewingcontent_id string, content_type string

The thing that always surprises people in subscriptions: subscription_cancelled returns no money. Only order_refunded and order_cancelled subtract from total_revenue. A cancellation means the next renewal does not happen, not that previous months are refunded, and the profile says exactly that.

#The traits you send with identify

These are the keys the code gives meaning to, and which become real profile columns:

KeyTypeNote
emailstringlower-cased only, with no format validation
phonestringparsed and stored as E.164, plus a derived phone_operator
first_name and last_namestringas sent
genderstringmapped to male, female or other
birthdaydatethe formats 2006-01-02, 2006/01/02 and RFC3339 are accepted; a malformed date is silently dropped
national_idstringthe check digit is verified; an invalid one is dropped entirely
city, region, countrystringfilled from the event's location if you do not send them
languagestringfilled from the first part of locale if you do not send it
timezonestringfilled from the event's context.timezone if you do not send it
push_opt_in, email_opt_in, sms_opt_inbooleanthe true values are true, 1, yes, on and «بله». Everything else is false

A new profile starts with all three consents on. An existing customer base has already consented through your own flow, and defaulting to off would make your first campaign reach nobody.

name and created_at are also declared as reserved keys, but they are not promoted to columns and stay ordinary traits. If you want a full name, send first_name and last_name.

Every other key is a free-form trait and lands in the traits and traits_num maps. A shop usually also sends: loyalty_tier string, loyalty_points number, is_wholesale boolean, preferred_category string.

One complete identify
curl -X POST https://in.segmentic.net/v1/identify \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer wk_seg_..." \
  -d '{
    "message_id": "c74a9e01-5f22-4a8b-8c31-7ee2d9b40a55",
    "user_id": "u_88123",
    "traits": {
      "phone": "09123456789",
      "email": "Hamid@Example.com",
      "first_name": "حمید",
      "city": "تهران",
      "birthday": "1993-04-11",
      "sms_opt_in": true,
      "loyalty_tier": "gold",
      "loyalty_points": 1840
    }
  }'
Response
{"status":"ok","accepted":1}

What that does to the profile: phone becomes +989123456789 and phone_operator is written as mci, email becomes hamid@example.com, loyalty_points lands in both the text and the numeric map so that a "greater than" filter works, and loyalty_tier stays text only.

#What Segmentic writes

These four names are written into your event stream by the platform's own workers. Do not send them yourself, but do build segments and funnels on them like any other event.

NameWhen it is writtenProperties
message_senta campaign message was sent successfullychannel, category, transport, node_id, arm which is treatment or control, can_open, can_click. Plus why_open and why_click when a signal cannot be measured, which are ready-to-print Persian sentences
message_failedthe send failedthe same set, plus reason
message_withheldthe user was chosen for the campaign and deliberately not messagedthe same set, with arm as control and reason naming the hold
message_openedthe open-tracking endpoint was callednone. The campaign's message id lands in source_message_id, and the device and location come from the request the mail client made

The message_id of these events combines the request id and the event name, so that a send and a failure for the same message do not de-duplicate against each other.

message_delivered, message_bounced and unsubscribed are declared as constants and nothing else in the backend uses them: no worker writes them and nothing reads them, so a report built on message_delivered comes back empty. The panel asks for a delivery event anyway. Its messaging dashboard template and the starter metrics for delivery rate, open rate and click rate each need one mapped to a name from your own event schema, and activation does not proceed until you name one, so unless you send a delivery event yourself, that dashboard and those three metrics are never built.

What is missing is the event, not the data. A campaign report counts its own delivered messages from the receipts a transport sends back, the deliverability service reads bounces off the SMTP return path and writes them to the suppression list, and an unsubscribe lands on the person's record in the preference centre and comes back as the suppression reason on the next send. None of that arrives as a row in your event stream.

The attribution worker recognises exactly four names, message_sent, message_withheld, message_opened and message_clicked, and skips every other event it is handed. message_clicked is not written by a worker either: the web SDK raises it when a visitor lands on a link carrying sg_mid, once, until a different message id replaces it. The comparison is against the one id in storage, not against a history of them, so a visitor who lands on one message, then a second, then the first one again reports the first click twice.

Next: identity explains how these events attach to one person, and designing events lists the decisions that cannot be undone.

PreviousDesigning eventsNextPlacing events

On this page

  • How to read this
  • The names the platform knows
  • The properties you put on every event
  • Online retail
  • Super-app and ride hailing
  • Fintech and payments
  • Travel and booking
  • Education
  • Subscription media
  • The traits you send with identify
  • What Segmentic writes

Segmentic

This page is written from the code