Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create a minimal working Customer.io example. Use when learning Customer.io basics, testing SDK setup, or creating your first identify + track integration. Trigger: "customer.io hello world", "first customer.io message", "test customer.io", "customer.io example", "customer.io quickstart".
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 170% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 113% | 0% |
Create a minimal working Customer.io integration: identify a user (create/update their profile), track an event, and send a transactional email. This covers the three fundamental Customer.io operations.
customerio-node installed (npm install customerio-node)CUSTOMERIO_SITE_ID and CUSTOMERIO_TRACK_API_KEY configuredCUSTOMERIO_APP_API_KEY configured (for transactional email example)typescript// hello-customerio.ts import { TrackClient, RegionUS } from "customerio-node"; const cio = new TrackClient( process.env.CUSTOMERIO_SITE_ID!, process.env.CUSTOMERIO_TRACK_API_KEY!, { region: RegionUS } ); // identify() creates the user if they don't exist, or updates if they do. // The first argument is your internal user ID (immutable — use DB primary key). await cio.identify("user-123", { email: "hello@example.com", // Required for email campaigns first_name: "Jane", last_name: "Doe", plan: "pro", created_at: Math.floor(Date.now() / 1000), // Unix seconds, NOT milliseconds }); console.log("User identified in Customer.io");
Key rules:
id (first arg) should be your immutable database ID — never use email as IDemail attribute is required if you want to send email campaignscreated_at must be Unix timestamp in seconds (not ms) — Math.floor(Date.now() / 1000)typescript// Track a custom event on the user's activity timeline. // Events trigger campaigns — the event name must match exactly in the dashboard. await cio.track("user-123", { name: "signed_up", // snake_case, matches campaign trigger data: { signup_method: "google_oauth", referral_source: "product_hunt", timestamp: Math.floor(Date.now() / 1000), }, }); console.log("Event tracked in Customer.io");
Key rules:
identify() first)name is case-sensitive and must match your campaign trigger exactlysnake_case for event names — signed_up, not Signed Up or signedUpdata properties are accessible in Liquid templates as {{ event.property_name }}typescript// Track events before the user signs up — merge later on identification await cio.trackAnonymous({ anonymous_id: "anon-abc-123", // Your anonymous tracking ID (cookie, device ID) name: "page_viewed", data: { url: "/pricing", referrer: "https://google.com", }, }); console.log("Anonymous event tracked");
When the anonymous user signs up, include anonymous_id in the identify() call to merge their pre-signup activity:
typescriptawait cio.identify("user-123", { email: "hello@example.com", anonymous_id: "anon-abc-123", // Merges anonymous activity });
typescriptimport { APIClient, SendEmailRequest, RegionUS } from "customerio-node"; const api = new APIClient(process.env.CUSTOMERIO_APP_API_KEY!, { region: RegionUS, }); const request = new SendEmailRequest({ to: "hello@example.com", transactional_message_id: "1", // ID from Customer.io dashboard message_data: { // Populates {{ liquid }} variables welcome_name: "Jane", login_url: "https://app.example.com/login", }, identifiers: { id: "user-123" }, // Links delivery to user profile }); const response = await api.sendEmail(request); console.log("Email queued:", response.delivery_id);
first_name, plan, and other attributessigned_up eventtypescript// scripts/hello-customerio.ts import { TrackClient, APIClient, SendEmailRequest, RegionUS } from "customerio-node"; async function main() { // Track API client — identify and track const cio = new TrackClient( process.env.CUSTOMERIO_SITE_ID!, process.env.CUSTOMERIO_TRACK_API_KEY!, { region: RegionUS } ); // 1. Identify await cio.identify("user-hello-world", { email: "hello@example.com", first_name: "Jane", created_at: Math.floor(Date.now() / 1000), }); console.log("1. User identified"); // 2. Track event await cio.track("user-hello-world", { name: "hello_world_completed", data: { sdk: "customerio-node", step: "quickstart" }, }); console.log("2. Event tracked"); // 3. Clean up test user (optional) await cio.suppress("user-hello-world"); console.log("3. Test user suppressed (won't receive messages)"); } main().catch(console.error);
Run: npx tsx scripts/hello-customerio.ts
| Error | Cause | Solution | |-------|-------|----------| | 401 Unauthorized | Invalid credentials | Verify Site ID + Track API Key in dashboard | | 400 Bad Request | Malformed payload | Check attribute types and event name format | | User not in People tab | identify() not called | Always call identify() before track() | | Event not in Activity | Dashboard propagation delay | Wait 1-2 minutes and refresh | | Transactional email fails | Wrong transactional_message_id | Verify the ID matches your template in Customer.io |
After verifying hello world works, proceed to customerio-local-dev-loop to set up your development workflow.
Other measured skills in the registry, with their headline benchmark lift.