Skip to main content
Hamla can only act on what it can see. It already sees your website. The script tag watches visits, clicks and carts on its own. But it cannot see inside your system. When someone pays you, cancels, books an appointment or finishes a lesson, that happens in your database. Hamla has no idea it happened. A Hamla event is you telling Hamla: this just happened.
That is the whole idea. Hamla does the rest — it finds Omar, writes it on his timeline, moves him from trial to customer, and if a campaign was waiting for exactly that moment, it starts.

Why it is worth ten minutes of your developer’s time

The first one can send a newsletter. The second one can win him back.

Send your first event

1

Get a secret key

Dashboard → Settings → API keys. You want the secret key — it starts with sk_live_.Keep it on your server. It can write customer data, so treat it like a database password. It must never appear in a web page or a mobile app.
2

Send the event where it happens

In the code you already have — the payment webhook, the booking confirmation, the signup handler — add one call.
On Node.js, npm install @gethamla/node gives you the same thing with queueing and retries built in:
Only two things are required: who (identity — an email, a phone, or your own user id) and what (event — any name you like).type is the optional third. Your event name stays yours, in your own language; type tells Hamla what to do with it, from a list of seven (purchase, refund, booking, lead, checkout_started, fulfilled, cancelled). Leave it out and Hamla infers — an amount means money, and names it already knows keep working — but sending it means nothing is ever guessed. Full list in the events reference.
3

Check it arrived

Open that person’s contact page in Hamla. The event is on their timeline, with the time it happened.That is the loop closed. Everything below is what you can now do with it.

Who the person is

identity answers it, and any one field is enough. You never send all three, and you never need an email. A clinic that has never asked anyone for an email address is a first-class Hamla customer: send the phone, on its own, forever. Send more than one and you do not get two contacts. Hamla merges them into one person and keeps each as a way to find them — so a phone that arrives months later joins the email you sent first, and their whole history stays in one place. That is worth doing whenever you have both.
Identity is not permission. Knowing someone’s phone number is what lets Hamla recognize them; it is not consent to send them an SMS or a WhatsApp message. That is a separate opt-in, and Hamla keeps the two apart on purpose.

And what to call them

Identity says who. It does not say what to call them — and a contact with no name is why Hi {{contact.firstName}} comes out as Hi Friend. Names go through identify, the companion door to track:
Send the name in whatever shape you already store it: name is split on arrival: the first word is the first name, the rest is the family name, so Sara Al Otaibi is greeted as Sara and محمد بن عبد الله as محمد. Send both shapes together and the explicit parts win, field by field. Call it wherever you already know them — signup, checkout, login. Calling it on every login is safe and worth doing: Hamla fills in what is missing and never overwrites a name that is already there, so a correction someone makes in their profile survives.
profile also takes country, city, language and timezone. timezone is what keeps a “one day later” step out of someone’s night — the browser SDK fills it in for you; a server should send it when it knows.

Now use it

Sending the event is step one. Here is what it is for.

1. Start a campaign the second it happens

Open a campaign → When does the campaign start?App event → App: Your app’s eventsEvent name, and type it. That is it. Every person who fires that event from now on gets your message. Not tomorrow, not in the next batch — right then.
The name must match what your code sends, exactly: treatment_completed, not Treatment Completed. Once an event has arrived at least once, it appears in the picker so you can select it instead of typing it.
Under the name there is Can enter again later:
  • Off — each person is enrolled once, ever. Use it for a welcome sequence.
  • On — they can be enrolled again in a later period. Use it for renewals, repeat purchases, monthly check-ups.

2. Build an audience out of it

The moment your first purchase event arrives, two new fields appear in the segment builder under Events: Nobody creates these fields. They exist because you sent the event. Combine the two and you have your best customers going quiet: bought 3+ times, last time more than 60 days ago. That is a win-back list, and it stays correct forever, because your server keeps sending events.
The Events group appears in the builder only after the first event of any kind has arrived. Before that there is nothing to filter on.

3. Make it the campaign’s finish line

A campaign should stop bothering someone the moment they do the thing you wanted. In the campaign → How the sequence endsWhen an event happens → pick your event. Now anyone who fires subscription_started stops receiving the rest of the sequence. It is checked before every single send. The same event also becomes what the campaign’s success is measured against in your reports.

4. Or just ask

You do not have to build anything. Type it:
“Everyone who finished a treatment last month but has not booked again — send them a reminder.”
Hamla reads the same events and does it.

And two things that happen on their own

  • The person moves through their journey. Some names carry meaning: trial_started, subscription_started and purchase move someone into Decision; subscription_renewed and repeat_purchase move them into Retention. Use those names when they fit and the journey stays honest with no extra work. Your own invented names are still recorded — they just do not move the stage.
  • Everything feeds the numbers. Engagement, scoring and attribution all read your events, so reporting reflects what really happened in your business, not only what happened in a browser.

Events and traits are different things

This is the one distinction worth getting right.
  • Something that happened at a moment is an event. Kept forever, never overwritten. “Upgraded to Pro on Tuesday.”
  • Something that is true right now and can change is a trait. Newest value wins. “Plan is Pro.”
Send both, in the same call:
The first time you send a new trait key, Hamla creates the matching custom field automatically and segments can filter on it immediately. Keys are snake_case, and a field keeps the type it was born with. Rule of thumb: traits answer “who is this person today”, events answer “what have they done”. Most good segments use both.

Two complete examples

A clinic

Your booking system already knows when a treatment finishes. Send it:
Your word is treatment_completed and it stays that way everywhere. type: "purchase" is what makes the 100 JOD count as revenue — a clinic’s money is money. Now, with no further code:
  1. Trigger — a campaign on treatment_completed sends an aftercare message an hour later, with Can enter again later on so it works for every visit.
  2. Segmenttreatment_completed last time more than 180 days ago is everyone due for a check-up.
  3. Finish line — set appointment_booked as the goal, so anyone who rebooks stops getting reminders.

A SaaS

Your billing webhook already fires. Send it:
Now:
  1. Trigger — onboarding starts the instant someone pays.
  2. Segmentplan is pro scopes any campaign to paying customers, and stays correct as people upgrade and churn.
  3. Journeysubscription_started moves them to Decision on its own.
  4. Send subscription_expired on churn with traits: { "subscription_status": "expired" }, and your win-back segment fills itself.

Bring your history with you

You do not have to start from zero. POST /api/sdk/track/batch takes up to 500 past events per request — the same body shape, in an events array, each with its real occurredAt. One loop over your users table gives day-one meaning to a segment like “bought before, quiet for 60 days”.
Backfilled history never sends anything. Imported events fill profiles, counts and segments, but they do not start campaigns and do not fire segment-entry triggers. A year of old purchases must not send a year of messages tonight.Only live events — through /api/sdk/track or hamla.track() — can start a campaign.
Give every row an idempotencyKey (your invoice or order id) and the whole script is safe to re-run.

Common questions

They cover different halves. The script tag sees the browser — visits, sources, on-site behavior. Events know your database — plans, payments, milestones. Either works alone. Together, Hamla sees the whole person.
Yes, for things that genuinely happen in the page: hamla.track('download_ebook', { asset: 'guide.pdf' }). These count as deliberate and can start campaigns, and they need no key.Anything involving money or your own records should come from your server, where the secret key lives and the facts are real.
Same idempotencyKey → counted once, and the response says deduped: true. No key → each send is a separate event, because sometimes people really do buy twice.
Whatever your business actually calls them. Hamla never needs to know your vocabulary in advance — a clinic sends treatment_completed, a school sends lesson_finished.The only reason to borrow one of Hamla’s names is the journey stage: purchase, trial_started, subscription_started, subscription_renewed, repeat_purchase and friends move people forward automatically.
Three usual causes, in order:
  1. The name does not match. It is case- and character-exact.
  2. The event came in through the batch endpoint. Imports never trigger.
  3. The person was already enrolled. Turn on Can enter again later for repeating moments.
Field-by-field details, limits and error responses are in the events reference.