customerio-known-pitfalls
Customer.ioのアンチパターンを特定して回避できます。 統合の見直し、一般的なミスの防止、既存のCustomer.io実装の最適化が必要な場合に活用してください。 「customer.io mistakes」「customer.io anti-patterns」「customer.io best practices」「customer.io gotchas」といったフレーズでトリガーできます。
description の原文を見る
Identify and avoid Customer.io anti-patterns. Use when reviewing integrations, avoiding common mistakes, or optimizing existing Customer.io implementations. Trigger with phrases like "customer.io mistakes", "customer.io anti-patterns", "customer.io best practices", "customer.io gotchas".
SKILL.md 本文
Customer.io の既知の落とし穴
概要
Customer.io との統合時に発生する一般的な間違いとアンチパターンを回避します。
落とし穴のカテゴリ
1. 認証とセットアップ
落とし穴: Track API に App API キーを使用する
// WRONG: Track API に App API キーを使用
const client = new TrackClient(siteId, appApiKey); // 失敗します!
// CORRECT: Track API キーを使用して追跡
const client = new TrackClient(siteId, trackApiKey);
// App API キーはトランザクション API とレポート API にのみ使用
const apiClient = new APIClient(appApiKey);
落とし穴: ミリ秒単位のタイムスタンプ
// WRONG: JavaScript のミリ秒
{ created_at: Date.now() } // 1704067200000 - 拒否されます!
// CORRECT: Unix 秒
{ created_at: Math.floor(Date.now() / 1000) } // 1704067200
落とし穴: ハードコードされた認証情報
// WRONG: コード内の認証情報
const client = new TrackClient('abc123', 'secret-key'); // セキュリティリスク!
// CORRECT: 環境変数
const client = new TrackClient(
process.env.CUSTOMERIO_SITE_ID!,
process.env.CUSTOMERIO_API_KEY!
);
2. ユーザー識別
落とし穴: 識別前にイベントを追跡する
// WRONG: 識別前に追跡
await client.track(userId, { name: 'signup' }); // ユーザーが存在しません!
await client.identify(userId, { email: 'user@example.com' });
// CORRECT: 常に最初に識別
await client.identify(userId, { email: 'user@example.com' });
await client.track(userId, { name: 'signup' });
落とし穴: ユーザー ID を変更する
// WRONG: メールアドレスが変更されるとユーザー ID も変わる
const userId = user.email; // メール変更 = 新規ユーザー!
// CORRECT: 不変の識別子を使用
const userId = user.databaseId; // UUID または自動採番 ID
落とし穴: 匿名 ID がマージされない
// WRONG: anonymous_id リンクなし
await client.identify(newUserId, { email: 'user@example.com' });
// 匿名アクティビティは孤立します!
// CORRECT: マージのために anonymous_id を含める
await client.identify(newUserId, {
email: 'user@example.com',
anonymous_id: previousAnonymousId
});
3. イベント追跡
落とし穴: 一貫性のないイベント名
// WRONG: 一貫性のないケースと命名規則
await client.track(userId, { name: 'UserSignedUp' });
await client.track(userId, { name: 'user-signed-up' });
await client.track(userId, { name: 'user_signedup' });
// CORRECT: 一貫性のある snake_case
await client.track(userId, { name: 'user_signed_up' });
落とし穴: 一意のイベントが多すぎる
// WRONG: 動的なイベント名は乱雑になる
await client.track(userId, { name: `viewed_product_${productId}` });
// 数千の一意のイベントが作成されます!
// CORRECT: バリエーションにプロパティを使用
await client.track(userId, {
name: 'product_viewed',
data: { product_id: productId }
});
落とし穴: アナリティクスの処理でブロックする
// WRONG: リクエストパスでアナリティクスを待つ
app.post('/signup', async (req, res) => {
const user = await createUser(req.body);
await client.identify(user.id, { email: user.email }); // ブロック!
res.json({ user });
});
// CORRECT: ファイア・アンド・フォーゲット
app.post('/signup', async (req, res) => {
const user = await createUser(req.body);
client.identify(user.id, { email: user.email })
.catch(err => console.error('Customer.io error:', err));
res.json({ user });
});
4. データ品質
落とし穴: 必須属性がない
// WRONG: メール属性がない
await client.identify(userId, { name: 'John' });
// ユーザーはメールを受信できません!
// CORRECT: メールキャンペーン用にメールを常に含める
await client.identify(userId, {
email: 'john@example.com',
name: 'John'
});
落とし穴: 一貫性のない属性タイプ
// WRONG: 時には文字列、時には数値
await client.identify(userId1, { plan: 'premium' });
await client.identify(userId2, { plan: 1 });
// CORRECT: 一貫性のあるタイプ
await client.identify(userId, { plan: 'premium' });
落とし穴: セグメント名またはイベント名に PII を含める
// WRONG: PII が露出
await client.track(userId, { name: `email_${user.email}` });
// セグメントが作成: "email_john@example.com"
// CORRECT: 名前ではなく属性を使用
await client.track(userId, {
name: 'email_action',
data: { email: user.email }
});
5. キャンペーン設定
落とし穴: 配信停止処理がない
## WRONG: 配信停止リンクなし
{{{ unsubscribe_url }}} なしのメールテンプレート
## CORRECT: 常に配信停止を含める
<a href="{{{ unsubscribe_url }}}">Unsubscribe</a>
落とし穴: すべての属性更新でトリガーを実行
# WRONG: すべての識別でトリガーが実行される
trigger:
event: "identify"
# CORRECT: 特定のイベントでトリガーを実行
trigger:
event: "signed_up"
6. 配信の問題
落とし穴: バウンスを無視する
// WRONG: バウンス処理がない
webhooks.on('email_bounced', () => {
// 何もしない
});
// CORRECT: バウンスで抑制または更新
webhooks.on('email_bounced', async (event) => {
await client.suppress(event.data.customer_id);
// またはデータベース内でメールを無効としてマーク
});
落とし穴: 苦情率を監視しない
// WRONG: スパム苦情を無視
// 配信可能性に問題が生じます!
// CORRECT: 苦情をアラート
webhooks.on('email_complained', async (event) => {
// すぐに抑制
await client.suppress(event.data.customer_id);
// チームにアラート
await alertTeam(`Spam complaint from ${event.data.email_address}`);
});
7. パフォーマンスの問題
落とし穴: コネクションプーリングがない
// WRONG: リクエストごとに新しいクライアント
app.get('/api', async (req, res) => {
const client = new TrackClient(siteId, apiKey); // 新しい接続を作成!
await client.identify(userId, data);
});
// CORRECT: クライアントを再利用
const client = new TrackClient(siteId, apiKey);
app.get('/api', async (req, res) => {
await client.identify(userId, data);
});
落とし穴: レート制限がない
// WRONG: 制御されないバースト
for (const user of users) {
await client.identify(user.id, user.data); // 10,000 件のリクエストが一気に!
}
// CORRECT: レート制限
const limiter = new Bottleneck({ maxConcurrent: 10, minTime: 10 });
for (const user of users) {
await limiter.schedule(() => client.identify(user.id, user.data));
}
アンチパターン検出スクリプト
// scripts/audit-integration.ts
interface AuditResult {
issues: string[];
warnings: string[];
score: number;
}
async function auditIntegration(): Promise<AuditResult> {
const result: AuditResult = { issues: [], warnings: [], score: 100 };
// ハードコードされた認証情報をチェック
const files = await glob('**/*.{ts,js}');
for (const file of files) {
const content = await readFile(file, 'utf-8');
if (content.includes('site_') && content.includes('api_')) {
result.issues.push(`Possible hardcoded credentials in ${file}`);
result.score -= 20;
}
}
// ミリ秒単位のタイムスタンプをチェック
if (await hasPattern(/Date\.now\(\)(?!\s*\/\s*1000)/)) {
result.warnings.push('Possible millisecond timestamps detected');
result.score -= 5;
}
// track before identify パターンをチェック
if (await hasPattern(/track\([^)]+\)[\s\S]{0,500}identify\(/)) {
result.issues.push('Track before identify pattern detected');
result.score -= 15;
}
return result;
}
クイックリファレンス
| 落とし穴 | 修正 |
|---|---|
| 誤った API キー | Track API は追跡用、App API はトランザクション用 |
| ミリ秒 | Math.floor(Date.now() / 1000) を使用 |
| 識別前に追跡 | 常に最初に識別 |
| ユーザー ID を変更 | 不変のデータベース ID を使用 |
| メール属性がない | メールキャンペーン用にメールを含める |
| 動的なイベント名 | 代わりにプロパティを使用 |
| リクエストをブロック | ファイア・アンド・フォーゲットパターン |
| バウンス処理がない | バウンス時に抑制 |
| レート制限がない | Bottleneck または類似のツールを使用 |
リソース
まとめ
これらのガイドラインに従うことで、一般的な落とし穴を回避し、信頼性の高い Customer.io 統合を構築できます。このチェックリストに照らして定期的に実装を監査し、問題を早期に発見してください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- Brmbobo
- リポジトリ
- Brmbobo/Web2podcast
- ライセンス
- MIT
- 最終更新
- 2026/1/26
Source: https://github.com/Brmbobo/Web2podcast / ライセンス: MIT
関連スキル
seo-maps
ローカルSEO向けのマップインテリジェンス機能です。ジオグリッドのランク追跡、APIを通じたGBPプロフィール監査、Google・Tripadvisor・Trustpilotなど複数プラットフォームのレビュー分析、Google・Bing・Apple・OSM間のNAP(名前・住所・電話番号)検証、競合他社の半径マッピング、APIデータからのLocalBusinessスキーマ生成が可能です。3段階の機能レベルで対応でき、無料版(Overpass + Geoapify)、DataForSEO(フル機能)、DataForSEO + Google(最大カバレッジ)から選択できます。「maps」「geo-grid」「rank tracking」「GBP audit」「review velocity」「competitor radius」「maps analysis」「local rank tracking」「Share of Local Voice」「SoLV」などのキーワードで利用できます。
seo-content-brief
セクションごとの文字数、競合スコアリング、キーワード密度ガイダンス、ページタイプテンプレートを含む競争力のあるSEOコンテンツブリーフを生成します。新規ページのブリーフと既存ページの改善ブリーフの両方に対応しています。ユーザーが「コンテンツブリーフ」「ブリーフを作成」「コンテンツアウトライン」「ブログブリーフ」「サービスページブリーフ」「ブリーフ〜」「ライティングブリーフ」「コンテンツプラン」「アウトライン〜」などと言った場合に使用します。
rakuten-seo
楽天市場の商品名・キャッチコピーをSEO最適化するスキル。「楽天SEO」「商品名最適化」「楽天の商品名」「キャッチコピー」「楽天のタイトル」「商品名を直して」「楽天検索対策」など、楽天市場の商品名やキャッチコピーの作成・改善・チェックに関するリクエストで必ずこのスキルを使う。既存の商品名の改善も、ゼロからの作成も対応。あらゆるジャンル(食品・ファッション・化粧品・家電・サプリ・インテリア・ベビー・ペット・業務用など)に対応。 【ALSEL独自スキル】株式会社ALSEL が、19年・5,000社超の EC 支援で得たノウハウをもとに開発したオリジナルスキルです。
amazon-seo-jp
Amazon.co.jp商品ページのSEO分析・最適化・自動採点スキル v2.0。 COSMO/Rufus/A10アルゴリズムに基づく採点。セラーセントラル出品レポート(.xlsm)を入力すると、 商品タイトル・箇条書き・検索キーワード・商品説明文を100点満点で採点し、 4項目すべての改善案を日本語で出力する。 トリガー: 「Amazon SEO」「商品ページ採点」「Amazon最適化」 「リスティング改善」「Amazon商品名」「箇条書き改善」 「COSMO対応」「Rufus最適化」「Amazon タイトル」 【ALSEL独自スキル】株式会社ALSEL が、19年・5,000社超の EC 支援で得たノウハウをもとに開発したオリジナルスキルです。
rakuten-bulk-control-csv
楽天RMSの一括登録/一括除外/一括更新用CSV(コントロールカラム,商品管理番号 の2列フォーマット)を作成するスキル。商品DL CSV・商品管理画面のコピペ・Excel・PDFなどから商品管理番号を抽出し、Shift-JIS+LF改行で出力する。「一括除外リスト作って」「楽天の除外CSV」「コントロールカラムnで」「2800円以下の商品をdで」「在庫0の商品を一括削除」「商品管理番号抜いてshift-jsで」「このフォーマットで」など、楽天RMSの商品一括処理用CSVを作るタスクで必ずこのスキルを使う。コントロールカラム値(n=新規/d=削除/u=更新)と抽出条件(全件・価格・在庫・販売状態など)をユーザー指示に応じて柔軟に切り替える。 【ALSEL独自スキル】株式会社ALSEL が、19年・5,000社超の EC 支援で得たノウハウをもとに開発したオリジナルスキルです。
amazon-a-plus-content-brief
Amazon A+コンテンツの構成・モジュール選定・画像指示・比較表・FAQを設計するスキル。「A+コンテンツ作って」「Aプラス構成」「ブランドストーリー」「比較表つきA+」「A+モジュール選定」「Amazonのページに画像入れたい」「A+のヘッダー画像」「A+コンテンツマネージャー」など、Amazon A+コンテンツの企画・設計・改善のリクエストで必ずこのスキルを使う。ベーシック17モジュール/Premium追加機能/画像サイズ規定/文字数目安/審査リジェクト要因を踏まえて、デザイナーに渡せるブリーフ形式で出力。あらゆるジャンル(家電・コスメ・食品・アパレル・日用品・ベビー・ペット等)に対応。※ブランドストア(マルチページ)の設計は別スキル `amazon-brand-store-planner`、タイトル・bullet改善は `amazon-title-bullet-rewriter-jp`、メイン画像のチェックは `amazon-main-image-checker`。 【ALSEL独自スキル】株式会社ALSEL が、19年・5,000社超の EC 支援で得たノウハウをもとに開発したオリジナルスキルです。