jeremylongshore/claude-code-plugins-plus-skills
customerio-pack
plugins/saas-packs/customerio-pack/skills/customerio-webhooks-events/SKILL.md
January 22, 2026
Select agents to install to:
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/main/plugins/saas-packs/customerio-pack/skills/customerio-webhooks-events/SKILL.md -a claude-code --skill customerio-webhooks-eventsInstallation paths:
.claude/skills/customerio-webhooks-events/# Customer.io Webhooks & Events
## Overview
Implement webhook handling for Customer.io events including email delivery, opens, clicks, and bounces.
## Prerequisites
- Public endpoint for webhooks
- Webhook signing secret from Customer.io
- Event processing infrastructure
## Instructions
### Step 1: Webhook Event Types
```typescript
// types/customerio-webhooks.ts
export type WebhookEventType =
| 'email_sent'
| 'email_delivered'
| 'email_opened'
| 'email_clicked'
| 'email_bounced'
| 'email_complained'
| 'email_unsubscribed'
| 'email_converted'
| 'push_sent'
| 'push_delivered'
| 'push_opened'
| 'push_bounced'
| 'sms_sent'
| 'sms_delivered'
| 'sms_failed'
| 'in_app_opened'
| 'in_app_clicked';
export interface WebhookEvent {
event_id: string;
object_type: 'email' | 'push' | 'sms' | 'in_app';
metric: string;
timestamp: number;
data: {
customer_id: string;
email_address?: string;
campaign_id?: number;
action_id?: number;
broadcast_id?: number;
newsletter_id?: number;
transactional_message_id?: number;
delivery_id: string;
subject?: string;
link?: string;
recipient?: string;
identifiers?: {
id?: string;
email?: string;
};
};
}
export interface WebhookPayload {
events: WebhookEvent[];
}
```
### Step 2: Webhook Handler with Signature Verification
```typescript
// lib/webhook-handler.ts
import crypto from 'crypto';
import { Request, Response } from 'express';
import type { WebhookPayload, WebhookEvent } from '../types/customerio-webhooks';
export class CustomerIOWebhookHandler {
private signingSecret: string;
constructor(signingSecret: string) {
this.signingSecret = signingSecret;
}
verifySignature(payload: string, signature: string): boolean {
const expectedSignature = crypto
.createHmac('sha256', this.signingSecret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
B