A good event makes one observable claim clearly enough that another person can understand, implement, test and reuse it.
The name matters, but the definition matters more. An event called quote.accepted is useful only when the team agrees exactly what acceptance means, when the record is created, which quote and request it belongs to, and what the event does not prove.
Define the claim before the name
Start with a plain-language statement:
A customer successfully accepted a specific provider quote for a service request.
That statement gives the event a subject, action and object. It also exposes questions that a shorter label can hide:
- Does clicking the accept button count, or only a completed state change?
- Can a customer accept more than one quote for the same request?
- What happens if acceptance is reversed?
- Which quote version was accepted?
- Does the event fire again when the page reloads?
- Can acceptance occur through an administrator or offline process?
Until those questions are settled, quote.accepted is a promising name rather than a reliable event.
Anatomy of a good event definition
Event anatomy
What makes an event record useful
A useful event makes one narrow, observable claim and carries only the context needed to interpret and maintain it.
Meaning
-
Observable claim The specific activity or state change the record represents.
-
Event name A stable identifier that describes the fact rather than the interface.
-
What it does not prove The intent, value or downstream outcome that cannot be inferred from this record alone.
Recording rule
-
Fire condition The exact successful condition that creates the record.
-
Non-fire conditions Clicks, failures, retries or nearby states that must not count.
-
Repetition and reversal How duplicates, repeated attempts, replay and state changes are handled.
Context
-
Timestamp and source When the condition occurred and which system is authoritative.
-
Actor, object and unit The identifiers needed to join the record to the correct workflow instance.
-
Purposeful properties Stable dimensions needed for identified questions—not a copy of the source record.
Trust
-
Validation Positive, negative, duplicate and unusual paths that must be tested.
-
Ownership Who maintains the definition and implementation.
-
Privacy and minimisation The smallest appropriate data set, with access and retention expectations.
For quote.accepted, the observable claim is that one customer accepted one specific quote for one service request. The event should fire after the acceptance transaction succeeds and the quote state changes—not when the control is clicked or a confirmation view opens.
Useful identifiers may include request_id, quote_id, provider_id and quote_version. The definition should also state that the event does not prove work was scheduled, completed or satisfactory, and it should specify how failed, repeated and reversed acceptance paths are tested.
The definition turns a label into a testable contract.
Timing changes meaning
An event that fires too early measures intention. An event that fires too late may miss the behaviour the team needed to understand.
For quote acceptance, these moments are not equivalent:
Customer opens quote
→ clicks accept
→ confirms choice
→ acceptance transaction succeeds
→ provider is notified
→ work is scheduled
The correct fire condition depends on the claim. If the event is quote.accepted, the successful state change is normally stronger than the click or confirmation view. Provider notification and scheduling are different behaviours and should be represented separately when they matter.
Do not use one vague “completed” event to cover several states.
Name behaviour, not the interface
| Weak event | Better event | Why it is better |
|---|---|---|
accept_button_clicked |
quote.accepted |
Represents the successful behaviour rather than the control used |
provider_activity |
quote.submitted |
States what the provider did |
success |
service_request.published |
Names the specific state reached |
quote_2_submitted |
quote.submitted with quote_version=2 |
Keeps repetition as context rather than creating another event type |
message_tab_used |
conversation.message_sent |
Describes the meaningful action and survives interface changes |
Interface events can still be useful for a focused usability investigation. They should not become the default language of the measurement system when a more stable behavioural event exists.
Properties should earn their place
Properties make one event reusable across questions and dimensions, but collecting more context is not automatically better.
For quote.submitted, useful properties may include:
request_idquote_idprovider_idquote_versionservice_typerequires_site_visitsubmission_route
Properties should be stable, documented and available at the moment the event fires. Avoid adding free-text quote content, customer contact details, message bodies or addresses to analytics events. The event should carry what is needed for the defined measurement purpose, not a copy of the underlying record.
A good event survives reuse and change
A reliable event should remain meaningful when:
- the interface changes
- another team uses it in a metric
- a new actor or route is introduced
- the workflow repeats
- data is replayed or retried
- the original implementer is no longer available to explain it
That requires ownership, documentation and validation—not merely a tidy naming convention.
Event quality test
Before implementation, ask:
- What observable claim does this event make?
- Which workflow question or decision needs the evidence?
- What exact condition causes it to fire?
- Which actor, object and attempt does it belong to?
- Can retries, repeated steps or state reversals create misleading duplicates?
- Which properties are necessary for interpretation?
- What does the event not prove?
- How will successful, failed and unusual paths be tested?
- Who will review the definition when the workflow changes?
If the team cannot answer those questions, refining the event name will not solve the underlying ambiguity. The event is ready when its claim is narrow enough to test and useful enough to justify maintaining.