Testing first? There is no separate test key yet. Every key is live, so an event you send can start a real campaign. Build against a second business you create for testing, and switch the key when you go live.
Building with Lovable, v0 or Bolt for someone without a Hamla account? Start with the claimable install on hamla.io/developers, then come back here once the owner has claimed it, because no secret key is issued before that.
How the pieces fit
The script tag sees the browser. Your server knows the facts. Send both and Hamla sees the whole person.
1
Add the script tag
Copy the snippet from Settings → Website and put it in every page, before It records visits and where they came from, shows popups, and gives every browser a visitor id. A mobile app with no web pages can skip this step.
</head>:2
Create a secret key
Settings → API keys → create a secret key. It starts with Any other language works over plain HTTP. The SDK only adds queueing and retries.
sk_live_.Store it as HAMLA_API_KEY in your server’s environment. It can write customer data, so treat it like a database password: never put it in a web page, a mobile app, or an env var your framework ships to the browser (NEXT_PUBLIC_…, VITE_…).On Node.js, install the SDK:3
Identify people when they sign up
This is the step integrations most often skip, and it decides whether Hamla can ever message the person.Call What it does:
identify from your server at signup, and again at login:- Creates the contact, or enriches the one that already exists. Names and location fill gaps and never overwrite.
- Records that you put this person in Hamla, which is what lets campaigns email them. By identifying someone, you confirm you have permission to market to them, as Hamla’s terms require.
- Links their earlier anonymous visits, including the ad that brought them, when you pass the
visitorIdcookie or call it from the page withhamla.identify({ email }).
4
Send events where they happen
In the code you already have, such as the payment webhook, the booking confirmation or the trial start, add one call:
eventis your own name for the moment, in any language. Triggers and segments match it exactly.typesays what it means (purchase,refund,booking,signup,trial…), so a payment counts as revenue. See the full list.idempotencyKeyis your invoice or order id. A retried webhook is then counted once.traitsis who they are now (their plan, their status). The event is what they did.
track and identify never throw and never block, so a marketing call cannot break a checkout. On serverless platforms, call await hamla.flush() before the function returns so the queue is sent.5
Check it arrived
Use The result tells you whether it landed and what Hamla decided:When
trackNow once, so you can read the answer:ok is false, reason says why (config, invalid_input, http, network or timeout) and status carries the HTTP code. Over plain HTTP you get the same data inside { "success": true, "data": … }.Then open that person in Contacts: the event is on their timeline with the time it happened. warnings lists anything Hamla could not apply, such as a trait of the wrong type, and appears only when there is something to say. Read it on your first request. If it says campaigns will not reach this contact, the person was never identified: go back to step 3.6
Turn the event into a message
Hand it to the business, or do it yourself:
- Ask Hamla: “When someone fires
subscription_started, send them a welcome email with our three best tips.” - Or build it: open a campaign → When does the campaign start? → App event → Your app’s events → type the event name.
Bring your history
Send past signups and payments withPOST /api/sdk/track/batch, up to 500 per request, each with its real occurredAt and an idempotencyKey. History fills profiles, revenue and audiences, and never sends a message. Details in the events reference.
Before you go live
- The secret key is only on your server.
-
identifyruns at signup and login, before or alongside the firsttrack. - Every event that involves money has a
typeand anidempotencyKey. - Serverless functions call
await hamla.flush()before returning. - You switched from your test business’s key to the real one.
When something is off
Every field, limit and error is in the events reference. The longer explanation of events, with examples for a clinic and a SaaS, is in Hamla Events.