Developers
Growth infrastructure you configure with AI and run with one line.
One record per person from the first visit to the purchase, consent stored word for word, and follow-up that runs by itself.
One line in your server
Install the package, pass it a secret key, and post what a person did. It has no dependencies, it runs anywhere fetch does, and it never throws.
npm install kicklaceimport { Kicklace } from "kicklace";
const kl = new Kicklace(process.env.KICKLACE_SECRET_KEY!);
await kl.track("signup", { email });
await kl.track("purchase", { email, value: 49, idempotencyKey: invoice.id });
await kl.track({ type: "credit_added", accountId, properties: { credits: 10 } });Kicklace's own names are pageview, signup, download, activated and purchase. A name of your own, like credit_added, lands on the person's timeline and an automation can answer it.
type Outcome =
| { ok: true; status: string; id?: string }
| {
ok: false;
error: string;
message: string;
httpStatus: number;
};Every method resolves, and TypeScript makes you look at ok. error is Kicklace's own code and message is its own sentence, handed on untouched, because the fix is usually inside it. Nothing this package does can throw inside your checkout.
A 5xx and a network failure are tried again; a 4xx never is, because a refusal will not change. Give anything that must land exactly once an idempotencyKey — it is what makes a retried purchase, ours or your own webhook's, land once.
await kl.identify({ email, anonId, name, fields: { phone } });
await kl.subscribe({
email,
list: "product-updates",
consent: "Send me product updates. I can unsubscribe with one click.",
});
await kl.batch([
{ type: "pageview", anonId },
{ type: "identify", email, anonId },
]);A subscription needs the words the person read. subscribe stores that sentence verbatim as the proof, with the day and, if you send it, their IP; without one it is refused. The browser id from the tag is anonId, which is how the visitor who read the pricing page last week and the customer who paid today are one record.
The tag on your site
The events API is what your server knows. The tag is what your website knows: page reads, where somebody came from, and the signup forms it can hear.
import { KicklaceTag } from "kicklace/next";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
<KicklaceTag />
</body>
</html>
);
}<script
async
src="https://www.kicklace.com/api/in/YOUR_KEY/track.js">
</script>The tag takes your public key, wk_…, which is meant to be in a page. Your secret key, sk_live_…, belongs on a server and never in browser code: handed one, <KicklaceTag /> renders nothing and says why in the console. Both keys are under Settings → Your website.
It keeps one random id in the browser's own storage, reads the campaign a visitor arrived on, and can hear your signup forms without touching them. No cookies.
What arrives by itself
Some of what a person does, nobody has to send. Connect the door and it lands as the same event your own code would have posted.
- Stripe
- Payments, refunds and subscriptions, without a handler of your own. A paid invoice becomes a purchase with its amount on the person's timeline, and the lifecycle moves to Purchaser. Paste one address into Stripe and bring back the signing secret.
- Clerk and Kinde
- Sign-ups and sign-ins from the accounts you already have. A new account becomes a person with the lifecycle moved to Account, and a later event with no email address still finds them. One address pasted in, and there is no code to write.
- Vercel
- Deployments, as releases. A production deploy becomes a Release on its own board, and an automation can draft the changelog email from it for you to send. Paste one address into Vercel's webhooks and bring back the secret. Vercel has no webhook for visitors; the tag is what sees them.
- Your own servers
- The package is a wrapper over
POST /api/v1/events, so anything it does you can post by hand with a secret key: events,identify,subscribeand support messages, single or in a batch, each with an idempotency key and an expiry date if you promise one. - Outgoing webhooks
- What Kicklace tells your code. Every trigger — a stage entered, a subscription, a reply — is posted to your address with a
X-Kicklace-Signatureheader signed with your own secret, and tried again when your server is down.
Configure it with Claude
The other half of Kicklace is the configuration layer: point Claude at your workspace and set it up by asking.
Settings → Claude connects it: sign in from Claude, or take a key for another client. From there Claude can look people up, add them, write notes and tasks, make the lists, templates, stages, fields, views and charts your events then feed, and draft an automation for you to read and turn on.
“Set up a Product updates list and write the welcome email for it”
- It never sends an email. It writes the draft and hands you the link.
- It never deletes a record, and it never puts anyone on a list without the words they agreed to.
- Everything it does is in your name, and written down on that same screen.
What you stop maintaining
The parts a small team wires together by hand, and what each one becomes.
- A webhook handler that updates a users table
- Stripe posts to Kicklace instead. The payment lands on the person who made it, and their stage moves with it.
- An events table nobody reads
- The timeline is that table, and it is the same record your follow-up runs on and your charts count.
- A mailing tool with its own copy of the same people
- Lists live on the record, with the sentence each person agreed to stored word for word and a one-click unsubscribe in every email.
- A spreadsheet of sign-ups
- Contacts, with saved views, a board, and an export whenever you want one.
- The glue between them
- One record per person, from the anonymous first visit to the purchase, across devices. There is nothing left to match up afterwards.
Join the waitlist
We are onboarding one company at a time. Leave your email and we will let you know when your workspace is ready.
Billing is not live yet, and nothing is charged. Early customers use Kicklace free while we build it with them.