'Configure CI/CD pipelines for Klaviyo integrations with GitHub Actions.
Scanned 5/29/2026
Install to Claude Code
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill klaviyo-ci-integration --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Klaviyo Ci Integration?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremylongshore-klaviyo-ci-integration)More formats (shields.io, HTML) on the badges page.
---
name: klaviyo-ci-integration
description: 'Configure CI/CD pipelines for Klaviyo integrations with GitHub Actions.
Use when setting up automated testing, configuring CI secrets,
or integrating Klaviyo SDK tests into your build pipeline.
Trigger with phrases like "klaviyo CI", "klaviyo GitHub Actions",
"klaviyo automated tests", "CI klaviyo", "klaviyo pipeline".
'
allowed-tools: Read, Write, Edit, Bash(gh:*), Bash(npm:*)
version: 1.0.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags:
- saas
- klaviyo
- email-marketing
- cdp
compatibility: Designed for Claude Code
---
# Klaviyo CI Integration
## Overview
Set up GitHub Actions CI/CD pipelines for Klaviyo integrations with unit tests, integration tests against the real API, and deployment automation.
## Prerequisites
- GitHub repository with Actions enabled
- Klaviyo test API key (from a test/sandbox account)
- `klaviyo-api` SDK and vitest configured
## Instructions
### Step 1: Configure GitHub Secrets
```bash
# Store Klaviyo test credentials as GitHub secrets
gh secret set KLAVIYO_PRIVATE_KEY --body "pk_test_***"
gh secret set KLAVIYO_WEBHOOK_SIGNING_SECRET --body "whsec_test_***"
```
### Step 2: CI Workflow
Create `.github/workflows/klaviyo-ci.yml`:
```yaml
name: Klaviyo Integration CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx tsc --noEmit
- run: npm test -- --coverage
- name: Check Klaviyo SDK version
run: npm list klaviyo-api
integration-tests:
runs-on: ubuntu-latest
needs: unit-tests
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
KLAVIYO_PRIVATE_KEY: ${{ secrets.KLAVIYO_PRIVATE_KEY }}
KLAVIYO_TEST: '1'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Run integration tests
run: npm run test:integration
timeout-minutes: 5
- name: Verify Klaviyo connectivity
run: |
curl -s -w "HTTP %{http_code}\n" -o /dev/null \
-H "Authorization: Klaviyo-API-Key $KLAVIYO_PRIVATE_KEY" \
-H "revision: 2024-10-15" \
"https://a.klaviyo.com/api/accounts/"
```
### Step 3: Unit Test Examples
```typescript
// tests/unit/klaviyo-events.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ApiKeySession, EventsApi, ProfileEnum } from 'klaviyo-api';
vi.mock('klaviyo-api', () => ({
ApiKeySession: vi.fn(),
EventsApi: vi.fn().mockImplementation(() => ({
createEvent: vi.fn().mockResolvedValue({ body: { data: { id: 'EVT_MOCK' } } }),
getEvents: vi.fn().mockResolvedValue({
body: { data: [], links: { next: null } },
}),
})),
ProfileEnum: { Profile: 'profile' },
EventEnum: { Event: 'event' },
}));
describe('Event Tracking', () => {
let eventsApi: EventsApi;
beforeEach(() => {
eventsApi = new EventsApi(new ApiKeySession('pk_test'));
});
it('tracks a purchase event', async () => {
const result = await eventsApi.createEvent({
data: {
type: 'event' as any,
attributes: {
metric: { data: { type: 'metric', attributes: { name: 'Placed Order' } } },
profile: { data: { type: 'profile', attributes: { email: 'test@example.com' } } },
properties: { orderId: 'ORD-TEST-001', value: 99.99 },
time: new Date().toISOString(),
},
},
});
expect(result.body.data.id).toBe('EVT_MOCK');
});
});
```
### Step 4: Integration Test (Gated)
```typescript
// tests/integration/klaviyo-live.test.ts
import { describe, it, expect } from 'vitest';
import { ApiKeySession, AccountsApi, ProfilesApi, ProfileEnum } from 'klaviyo-api';
const SKIP = !process.env.KLAVIYO_TEST || !process.env.KLAVIYO_PRIVATE_KEY;
describe.skipIf(SKIP)('Klaviyo Live API', () => {
const session = new ApiKeySession(process.env.KLAVIYO_PRIVATE_KEY!);
it('authenticates successfully', async () => {
const accountsApi = new AccountsApi(session);
const accounts = await accountsApi.getAccounts();
expect(accounts.body.data).toHaveLength(1);
});
it('creates and cleans up a test profile', async () => {
const profilesApi = new ProfilesApi(session);
const testEmail = `ci-test-${Date.now()}@example.com`;
const created = await profilesApi.createProfile({
data: {
type: ProfileEnum.Profile,
attributes: {
email: testEmail,
firstName: 'CI',
lastName: 'Test',
properties: { source: 'github-actions', timestamp: new Date().toISOString() },
},
},
});
expect(created.body.data.id).toBeTruthy();
expect(created.body.data.attributes.email).toBe(testEmail);
});
});
```
### Step 5: PR Checks Configuration
```yaml
# .github/branch-protection.yml (or set via GitHub UI)
# Required checks: unit-tests
# Integration tests: optional (only on main push)
```
## Output
- Unit tests run on every PR (mocked, no API key needed)
- Integration tests run on main branch pushes (real API)
- SDK version verified in CI
- API connectivity smoke test included
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Secret not found in CI | Missing `gh secret set` | Add secret via repository settings |
| Integration test 429 | Rate limited in CI | Add delays between tests, use dedicated test key |
| Auth failures in CI | Wrong secret name | Verify secret name matches workflow env var |
| Test timeout | Slow Klaviyo response | Increase `timeout-minutes` |
## Resources
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [GitHub Encrypted Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
- [Vitest CI Configuration](https://vitest.dev/guide/ci.html)
## Next Steps
For deployment patterns, see `klaviyo-deploy-integration`.
No comments yet. Be the first to comment!