Customer.io Upgrade & Migration
Current State
!npm list customerio-node 2>/dev/null | grep customerio || echo 'customerio-node: not installed'
!npm view customerio-node version 2>/dev/null || echo 'Cannot check latest version'
Overview
Plan and execute customerio-node SDK upgrades safely: assess current version, review breaking changes, apply code migrations, and validate with staged rollout.
Prerequisites
- Current SDK version identified (
npm list customerio-node)
- Test environment available
- Version control for rollback
Major Version Migration Reference
Legacy CustomerIO to Modern TrackClient + APIClient
Older versions of customerio-node used a single CustomerIO class. Modern versions split into TrackClient (tracking) and APIClient (transactional/broadcasts).
const CustomerIO = require("customerio-node");
const cio = new CustomerIO(siteId, apiKey);
cio.identify("user-1", { email: "user@example.com" });
cio.track("user-1", { name: "event_name" });
import { TrackClient, APIClient, RegionUS } from "customerio-node";
const cio = new TrackClient(siteId, apiKey, { region: RegionUS });
await cio.identify("user-1", { email: "user@example.com" });
await cio.track("user-1", { name: "event_name", data: {} });
const api = new APIClient(appApiKey, { region: RegionUS });
await api.sendEmail(request);
Key changes:
TrackClient replaces CustomerIO for identify/track
APIClient is new — handles transactional + broadcasts
- Region is now explicit (
RegionUS or RegionEU)
- Methods return Promises (must
await)
- Event tracking uses
{ name, data } object instead of positional args
Instructions
Step 1: Assess Current Version
import { readFileSync, existsSync } from "fs";
function assessVersion() {
const lockPath = "package-lock.json";
if (existsSync(lockPath)) {
const lock = JSON.parse(readFileSync(lockPath, "utf-8"));
const installed =
lock.packages?.["node_modules/customerio-node"]?.version ??
lock.dependencies?.["customerio-node"]?.version ??
"not found in lockfile";
console.log(`Installed: customerio-node@${installed}`);
}
const pkg = JSON.parse(readFileSync("package.json", "utf-8"));
const declared = pkg.dependencies?.["customerio-node"] ?? "not declared";
console.log(`Declared: ${declared}`);
console.log("\nUsage pattern check:");
.();
.();
.();
}
();
Step 2: Review Breaking Changes
Step 3: Create Migration Wrapper
import { TrackClient, APIClient, RegionUS } from "customerio-node";
export class CioMigrationClient {
private trackClient: TrackClient;
private apiClient: APIClient | null;
constructor(config: {
siteId: string;
trackApiKey: string;
appApiKey?: string;
region?: "us" | "eu";
}) {
const region = config.region === "eu"
? (await import("customerio-node")).RegionEU
: RegionUS;
this.trackClient = new TrackClient(config.siteId, config.trackApiKey, {
region,
});
this.apiClient = config.appApiKey
? new APIClient(config.appApiKey, { region })
: null;
}
(: , : <, >): <> {
(attrs. && attrs. > ) {
attrs. = .(attrs. / );
}
..(userId, attrs);
}
(
: ,
: | { : ; ?: <, > },
?: <, >
): <> {
( eventOrOpts === ) {
..(userId, {
: eventOrOpts,
: data ?? {},
});
} {
..(userId, eventOrOpts);
}
}
(): {
(!.) {
();
}
.;
}
}
Step 4: Update and Test
npm install customerio-node@latest
npm test
npx dotenv -e .env.development -- npx vitest run tests/customerio
Step 5: Migration Test Suite
import { describe, it, expect } from "vitest";
import { TrackClient, APIClient, RegionUS } from "customerio-node";
const cio = new TrackClient(
process.env.CUSTOMERIO_SITE_ID!,
process.env.CUSTOMERIO_TRACK_API_KEY!,
{ region: RegionUS }
);
describe("Post-migration validation", () => {
const testId = `migration-test-${Date.now()}`;
it("identify works with new client", async () => {
await expect(
cio.identify(testId, {
email: `${testId}@test.example.com`,
created_at: Math.floor(Date.now() / 1000),
})
).resolves.not.toThrow();
});
it("track works with object format", async () => {
await expect(
cio.(testId, { : , : { : } })
)...();
});
(, () => {
cio.(testId);
(cio.(testId))...();
});
});
Step 6: Staged Rollout with Feature Flag
import { createHash } from "crypto";
function useNewSdk(userId: string, rolloutPercent: number): boolean {
const hash = createHash("md5").update(`cio-migration-${userId}`).digest("hex");
return parseInt(hash.substring(0, 8), 16) % 100 < rolloutPercent;
}
if (useNewSdk(userId, 10)) {
await newClient.identify(userId, attrs);
} else {
await legacyClient.identify(userId, attrs);
}
Migration Checklist
Error Handling
| Issue | Solution |
|---|
TrackClient is not a constructor | Old import style — use import { TrackClient } from "customerio-node" |
region is not defined | Import RegionUS or RegionEU from customerio-node |
| Methods not returning Promises | Upgrade to latest — old versions used callbacks |
TypeError: cio.track is not a function | Using APIClient instead of TrackClient for tracking |
Resources
Next Steps
After successful migration, proceed to customerio-ci-integration for CI/CD setup.