// reference
SDK Reference
The JavaScript/TypeScript SDK ships as @customerlog/sdk, with framework wrappers @customerlog/react and @customerlog/next.
new CustomerLog(config)
route.ts
const customer = new CustomerLog({
apiKey: "cl_xxx", // required — from your project settings
baseUrl: "https://event.customerlog.byorello.space", // optional — override for self-hosting
});
Throws a CustomerLogError if apiKey is missing.
customer.log(options)
Sends an event to your project. Reads like console.log on purpose. Every field except channel and title is optional.
log-options.ts
await customer.log({
channel: "signups", // grouping, e.g. "signups" | "payments" | "errors"
title: "User signed up", // human-readable title
message: "Came in via Google OAuth", // free-text detail
level: "info", // info | success | warning | error
user: { id: "usr_123", email: "jane@doe.com", name: "Jane" },
metadata: { source: "google", plan: "pro" }, // structured key/values
tags: ["growth", "oauth"],
icon: "🚀", // optional emoji
url: "https://example.com/signup",
notify: true, // trigger Slack/email delivery
});
Returns the created event as a Promise<LogResponse>. A failed request (bad API key, quota, network) rejects with a CustomerLogError.
The notify flag
Set notify: truewhen an event should trigger channel delivery (Slack message, email). Leave it off for high-frequency events you only want in the feed, so your team isn't pinged a thousand times a day.
Metadata best practices
- Keep metadata flat and string/number/boolean-friendly.
- Always include an identifier (
user_id,order_id) so events are traceable. - Structured metadata + free text is what makes AI summaries useful later — the same shape is what the digest reads.
Errors and retries
try-catch.ts
import { CustomerLogError } from "@customerlog/sdk";
try {
await customer.log({ channel: "payments", title: "Payment failed" });
} catch (err) {
if (err instanceof CustomerLogError) {
// 4xx/5xx with a server message
console.error(err.status, err.message);
}
}