Customer.io Hello World
SkillDev tools'Create a minimal working Customer.io example.
Use Customer.io Hello World in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Customer.io Hello World and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the Customer.io Hello World skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by jeremylongshore/tons-of-skills-marketplace in skills/.curated/customerio-hello-world/SKILL.md and read by Ahel’s review.
Output
- A verified synthetic profile/event or message example in a non-production workspace.
- A minimal receipt showing environment, validation result, and cleanup without retaining recipient data.
Examples
Create a development-only profile using a synthetic identifier, submit one schema-valid event, and confirm its arrival in the development workspace. Remove the test profile or let its documented TTL expire. Never use a real customer email or production segment as a tutorial target.
Overview
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.
Prerequisites
customerio-nodeinstalled (npm install customerio-node)CUSTOMERIO_SITE_IDandCUSTOMERIO_TRACK_API_KEYconfiguredCUSTOMERIO_APP_API_KEYconfigured (for transactional email example)
Instructions
Step 1: Identify a User (Create/Update Profile)
// 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 IDemailattribute is required if you want to send email campaignscreated_atmust be Unix timestamp in seconds (not ms) —Math.floor(Date.now() / 1000)- All custom attributes are stored on the user profile and usable in segments + Liquid templates
Step 2: Track an Event
// 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:
- User must be identified before tracking events (call
identify()first) - Event
nameis case-sensitive and must match your campaign trigger exactly - Use
snake_casefor event names —signed_up, notSigned UporsignedUp dataproperties are accessible in Liquid templates as{{ event.property_name }}
Step 3: Track an Anonymous Event
// 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:
await cio.identify("user-123", {
email: "hello@example.com",
anonymous_id: "anon-abc-123", // Merges anonymous activity
});
Step 4: Send a Transactional Email
import { 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);
Step 5: Verify in Dashboard
- Go to https://fly.customer.io
- Navigate to People and search for "hello@example.com"
- Verify the profile shows
first_name,plan, and other attributes - Click the Activity tab to see the
signed_upevent - Check Deliveries for the transactional email
Complete Example
// 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 Handling
| 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 |
Resources
Next Steps
After verifying hello world works, proceed to customerio-local-dev-loop to set up your development workflow.
Signals
- GitHub stars
- 3k
- Forks
- 415
- Last commit
- Oct 2026
Ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
customerio-hello-world- Source
- github.com/jeremylongshore/tons-of-skills-marketplace
github.com/jeremylongshore/tons-of-skills-marketplace
Related picks
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptnodejs-backend-patterns
Skill · wshobson
The pick for Noderun-node-tests
Skill · hiroro-work
The pick for Nodeteach
Skill · mattpocock
More in Dev toolscaveman
Skill · juliusbrussee
More in Dev tools