Agent Skills by ALSEL
Anthropic Claudeビジネス・経営⭐ リポ 1品質スコア 53/100

customerio-reference-architecture

Customer.ioのリファレンスアーキテクチャを実装します。統合設計の検討、アーキテクチャの計画、またはエンタープライズパターンの実装時に活用できます。「customer.ioアーキテクチャ」「customer.ioの設計」「customer.ioエンタープライズ」「customer.io統合パターン」といったフレーズで呼び出せます。

description の原文を見る

Implement Customer.io reference architecture. Use when designing integrations, planning architecture, or implementing enterprise patterns. Trigger with phrases like "customer.io architecture", "customer.io design", "customer.io enterprise", "customer.io integration pattern".

SKILL.md 本文

Customer.io リファレンスアーキテクチャ

概要

適切な関心の分離、信頼性、スケーラビリティを備えた Customer.io 統合のためのエンタープライズグレードのリファレンスアーキテクチャです。

アーキテクチャ図

                                    Customer.io
                                        |
                    +-------------------+-------------------+
                    |                   |                   |
              Track API            App API            Webhooks
                    |                   |                   |
                    v                   v                   v
            +-------+-------+   +-------+-------+   +-------+-------+
            |   Event Bus   |   |  Transactional |   | Webhook Handler|
            |   (Kafka)     |   |    Service     |   |   (Express)   |
            +-------+-------+   +-------+-------+   +-------+-------+
                    |                   |                   |
                    v                   v                   v
            +-------+-------+   +-------+-------+   +-------+-------+
            | CustomerIO    |   |    Email       |   |   Event       |
            | Worker        |   |    Templates   |   |   Processor   |
            +-------+-------+   +-------+-------+   +-------+-------+
                    |                   |                   |
                    +-------------------+-------------------+
                                        |
                                        v
                                +-------+-------+
                                |   Data Lake   |
                                |  (BigQuery)   |
                                +---------------+

実装手順

ステップ 1: コアサービスレイヤー

// src/services/customerio/index.ts
import { TrackClient, APIClient, RegionUS } from '@customerio/track';
import { EventEmitter } from 'events';

export interface CustomerIOConfig {
  trackSiteId: string;
  trackApiKey: string;
  appApiKey: string;
  region: 'us' | 'eu';
  environment: 'development' | 'staging' | 'production';
}

export class CustomerIOService extends EventEmitter {
  private trackClient: TrackClient;
  private apiClient: APIClient;
  private config: CustomerIOConfig;

  constructor(config: CustomerIOConfig) {
    super();
    this.config = config;

    this.trackClient = new TrackClient(
      config.trackSiteId,
      config.trackApiKey,
      { region: config.region === 'eu' ? RegionEU : RegionUS }
    );

    this.apiClient = new APIClient(config.appApiKey, {
      region: config.region === 'eu' ? RegionEU : RegionUS
    });
  }

  // ユーザー管理
  async identifyUser(userId: string, attributes: UserAttributes): Promise<void> {
    this.emit('identify:start', { userId, attributes });

    try {
      await this.trackClient.identify(userId, {
        ...attributes,
        _env: this.config.environment,
        _updated_at: Math.floor(Date.now() / 1000)
      });
      this.emit('identify:success', { userId });
    } catch (error) {
      this.emit('identify:error', { userId, error });
      throw error;
    }
  }

  // イベントトラッキング
  async trackEvent(userId: string, event: EventPayload): Promise<void> {
    this.emit('track:start', { userId, event });

    try {
      await this.trackClient.track(userId, {
        name: event.name,
        data: {
          ...event.data,
          _env: this.config.environment
        }
      });
      this.emit('track:success', { userId, event: event.name });
    } catch (error) {
      this.emit('track:error', { userId, event: event.name, error });
      throw error;
    }
  }

  // トランザクションメッセージング
  async sendTransactional(request: TransactionalRequest): Promise<void> {
    return this.apiClient.sendEmail(request);
  }
}

ステップ 2: イベントバス統合

// src/services/customerio/event-bus.ts
import { Kafka, Producer, Consumer } from 'kafkajs';
import { CustomerIOService } from './index';

interface CustomerIOEvent {
  type: 'identify' | 'track' | 'transactional';
  userId: string;
  payload: any;
  timestamp: number;
  correlationId: string;
}

export class CustomerIOEventBus {
  private producer: Producer;
  private consumer: Consumer;
  private service: CustomerIOService;

  constructor(kafka: Kafka, service: CustomerIOService) {
    this.producer = kafka.producer();
    this.consumer = kafka.consumer({ groupId: 'customerio-worker' });
    this.service = service;
  }

  async start(): Promise<void> {
    await this.producer.connect();
    await this.consumer.connect();

    await this.consumer.subscribe({
      topics: ['customerio.identify', 'customerio.track', 'customerio.transactional']
    });

    await this.consumer.run({
      eachMessage: async ({ topic, message }) => {
        const event: CustomerIOEvent = JSON.parse(message.value!.toString());
        await this.processEvent(topic, event);
      }
    });
  }

  private async processEvent(topic: string, event: CustomerIOEvent): Promise<void> {
    const startTime = Date.now();

    try {
      switch (event.type) {
        case 'identify':
          await this.service.identifyUser(event.userId, event.payload);
          break;
        case 'track':
          await this.service.trackEvent(event.userId, event.payload);
          break;
        case 'transactional':
          await this.service.sendTransactional(event.payload);
          break;
      }

      // 成功メトリクスを送信
      await this.producer.send({
        topic: 'customerio.processed',
        messages: [{
          key: event.correlationId,
          value: JSON.stringify({
            ...event,
            status: 'success',
            processingTime: Date.now() - startTime
          })
        }]
      });
    } catch (error) {
      // 失敗したイベント用のデッドレターキュー
      await this.producer.send({
        topic: 'customerio.dlq',
        messages: [{
          key: event.correlationId,
          value: JSON.stringify({
            ...event,
            status: 'failed',
            error: error.message,
            processingTime: Date.now() - startTime
          })
        }]
      });
    }
  }

  // 処理するイベントを公開
  async publish(event: CustomerIOEvent): Promise<void> {
    await this.producer.send({
      topic: `customerio.${event.type}`,
      messages: [{
        key: event.userId,
        value: JSON.stringify(event)
      }]
    });
  }
}

ステップ 3: リポジトリパターン

// src/repositories/user-messaging.ts
import { CustomerIOService } from '../services/customerio';
import { UserRepository } from './user';

export interface MessagingPreferences {
  email: boolean;
  push: boolean;
  sms: boolean;
  inApp: boolean;
}

export class UserMessagingRepository {
  constructor(
    private cio: CustomerIOService,
    private users: UserRepository
  ) {}

  async syncUser(userId: string): Promise<void> {
    const user = await this.users.findById(userId);
    if (!user) throw new Error(`User ${userId} not found`);

    const preferences = await this.getPreferences(userId);

    await this.cio.identifyUser(userId, {
      email: user.email,
      first_name: user.firstName,
      last_name: user.lastName,
      created_at: Math.floor(user.createdAt.getTime() / 1000),
      plan: user.subscription?.plan || 'free',
      // 設定
      email_opt_in: preferences.email,
      push_opt_in: preferences.push,
      sms_opt_in: preferences.sms
    });
  }

  async getPreferences(userId: string): Promise<MessagingPreferences> {
    // あなたの設定ストアから読み込み
    return {
      email: true,
      push: false,
      sms: false,
      inApp: true
    };
  }

  async updatePreferences(
    userId: string,
    preferences: Partial<MessagingPreferences>
  ): Promise<void> {
    // ローカルストアを更新
    await this.savePreferences(userId, preferences);

    // Customer.io に同期
    await this.cio.identifyUser(userId, {
      email_opt_in: preferences.email,
      push_opt_in: preferences.push,
      sms_opt_in: preferences.sms
    });
  }
}

ステップ 4: Webhook ハンドラー

// src/webhooks/customerio.ts
import { Router } from 'express';
import { EventEmitter } from 'events';

export class CustomerIOWebhooks extends EventEmitter {
  private router: Router;
  private signingSecret: string;

  constructor(signingSecret: string) {
    super();
    this.signingSecret = signingSecret;
    this.router = Router();
    this.setupRoutes();
  }

  private setupRoutes(): void {
    this.router.post('/', async (req, res) => {
      // 署名を検証
      if (!this.verifySignature(req)) {
        return res.status(401).send('Invalid signature');
      }

      // イベントを処理
      const events = req.body.events || [];

      for (const event of events) {
        this.emit(event.metric, event);
        this.emit('*', event);
      }

      res.status(200).json({ received: events.length });
    });
  }

  getRouter(): Router {
    return this.router;
  }
}

// 使用例
const webhooks = new CustomerIOWebhooks(process.env.WEBHOOK_SECRET!);

webhooks.on('email_delivered', (event) => {
  // 配信ステータスを更新
});

webhooks.on('email_bounced', async (event) => {
  // バウンスを処理 - ユーザーを除外
  await cio.suppress(event.data.customer_id);
});

webhooks.on('*', (event) => {
  // すべてのイベントをデータウェアハウスにストリーム
  await streamToDataWarehouse(event);
});

app.use('/webhooks/customerio', webhooks.getRouter());

ステップ 5: インフラストラクチャアズコード

# terraform/customerio.tf
resource "google_secret_manager_secret" "customerio_site_id" {
  secret_id = "customerio-site-id"

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret" "customerio_api_key" {
  secret_id = "customerio-api-key"

  replication {
    auto {}
  }
}

resource "google_cloud_run_service" "customerio_worker" {
  name     = "customerio-worker"
  location = var.region

  template {
    spec {
      containers {
        image = "gcr.io/${var.project}/customerio-worker:latest"

        env {
          name = "CUSTOMERIO_SITE_ID"
          value_from {
            secret_key_ref {
              name = google_secret_manager_secret.customerio_site_id.secret_id
              key  = "latest"
            }
          }
        }

        env {
          name = "CUSTOMERIO_API_KEY"
          value_from {
            secret_key_ref {
              name = google_secret_manager_secret.customerio_api_key.secret_id
              key  = "latest"
            }
          }
        }
      }
    }
  }
}

resource "google_pubsub_topic" "customerio_events" {
  name = "customerio-events"
}

resource "google_bigquery_dataset" "customerio" {
  dataset_id = "customerio_events"
  location   = var.region
}

resource "google_bigquery_table" "delivery_events" {
  dataset_id = google_bigquery_dataset.customerio.dataset_id
  table_id   = "delivery_events"

  schema = file("${path.module}/schemas/delivery_events.json")

  time_partitioning {
    type  = "DAY"
    field = "timestamp"
  }
}

アーキテクチャの原則

  1. 関心の分離: Track API、App API、Webhook は別々のサービスで処理されます
  2. イベント駆動型: 信頼性の高い非同期処理のためにメッセージキューを使用します
  3. べき等性: すべての操作は安全に再試行できます
  4. 可観測性: 監視とデバッグのためにイベントが発行されます
  5. インフラストラクチャアズコード: すべてのリソースは Terraform で定義されています

出力結果

  • コア Customer.io サービスレイヤー
  • イベントバス統合(Kafka)
  • ユーザーメッセージング用のリポジトリパターン
  • 署名検証を備えた Webhook ハンドラー
  • Terraform インフラストラクチャコード

リソース

次のステップ

アーキテクチャの実装後、customerio-multi-env-setup を使用してマルチ環境設定に進みます。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
Brmbobo
リポジトリ
Brmbobo/Web2podcast
ライセンス
MIT
最終更新
2026/1/26

Source: https://github.com/Brmbobo/Web2podcast / ライセンス: MIT

関連スキル

Anthropic Claudeビジネス・経営⭐ リポ 20,903

3-statement-model

3種類の財務諸表テンプレート(損益計算書、貸借対照表、キャッシュフロー計算書)を作成・記入・完成させることができます。モデルテンプレートの記入、既存のモデル枠組みの完成、財務モデルへのデータ入力、部分的に完成した損益/貸借/キャッシュフロー枠組みの完成、または既存テンプレート構造内での統合財務諸表の連携に対応しています。3種類の財務モデルテンプレートの記入、完成、またはデータ入力に関するご依頼で自動的に機能します。

by anthropics
汎用ビジネス・経営⭐ リポ 1,982

strategic-decision

CEO・経営層向けの戦略的意思決定支援です。前提条件に異議を唱え、問題を診断し、確実な戦略を設計できます。4つのモード(AGGRESSIVE:大きな夢を見る、SELECTIVE:基盤を維持しつつ有望な拡張を厳選、DIAGNOSTIC:最大限の厳密性、VALIDATION:本質に絞る)を備えています。創業者、経営幹部、プロダクトリーダーが製品開発、成長戦略、市場戦略、技術選定、リソース配分に関する戦略的判断が必要な場面で活用できます。

by LeoYeAI
汎用ビジネス・経営⭐ リポ 521

value-realization

エンドユーザーが製品アイデアから明確な価値を感じるかどうかを分析します。以下の場面で活用できます:製品コンセプトの議論、機能の評価、製品改善の方向性提示、マーケティング戦略の企画、導入・継続率の問題分析、コピーが価値を伝えているかの検証、機能と利用シーンの対応付け、または製品方向性・ポジショニング・エンドユーザーの需要の有無が不確かな場合(例:「これは良いアイデアか」「この製品をどう思うか」「ユーザーは必要とするか」「この機能は何に役立つのか」「機能の価値をどう説明するか」「このコピーをどう思うか」「利用シーンを作成する手助けが欲しい」「ユーザーが継続利用しない理由は何か」「どうポジショニングすべきか」)。

by Done-0
Anthropic Claudeビジネス・経営⭐ リポ 42,795

creating-financial-models

このスキルは、投資判断に必要な高度な財務モデリング機能を提供します。DCF分析、感度分析、モンテカルロシミュレーション、シナリオプランニングなど、複数の分析手法を組み合わせることで、より正確で信頼性の高い財務予測が可能になります。

by anthropics
汎用ビジネス・経営⭐ リポ 4,194

pestel-analysis

政治的、経済的、社会的、技術的、環境的、法的な外部要因を分析します。市場環境の変化が製品、ロードマップ、または戦略に大きな影響を与える可能性がある場合に活用できます。

by deanpeters
Anthropic Claudeビジネス・経営⭐ リポ 380

chemical_safety_assessment

化学安全性評価 - 化学物質の安全性を評価します。PubChemの化合物情報、FDAの医薬品データ、ADMET予測、ChEMBLの構造警告を活用します。このスキルを使用することで、化合物名から一般情報を取得したり、医薬品名から警告および注意事項を取得したり、分子のADMETを予測したり、化合物の構造警告を検出したりできます。4つのSCPサーバーから4つのツールを統合しています。

by SpectrAI-Initiative
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: Brmbobo · Brmbobo/Web2podcast · ライセンス: MIT