jpskill.com
💼 ビジネス コミュニティ

analytics-patterns

イベント追跡や画面追跡、ユーザー属性、Firebase Analyticsなどを活用し、プライバシーにも配慮した分析統合パターンを構築して、ビジネスの意思決定を支援するSkill。

📜 元の英語説明(参考)

Analytics integration patterns - event tracking, screen tracking, user properties, Firebase Analytics, custom analytics providers, and privacy compliance.

🇯🇵 日本人クリエイター向け解説

一言でいうと

イベント追跡や画面追跡、ユーザー属性、Firebase Analyticsなどを活用し、プライバシーにも配慮した分析統合パターンを構築して、ビジネスの意思決定を支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o analytics-patterns.zip https://jpskill.com/download/16400.zip && unzip -o analytics-patterns.zip && rm analytics-patterns.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/16400.zip -OutFile "$d\analytics-patterns.zip"; Expand-Archive "$d\analytics-patterns.zip" -DestinationPath $d -Force; ri "$d\analytics-patterns.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して analytics-patterns.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → analytics-patterns フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

[Skill 名] analytics-patterns

アナリティクス統合パターン

アーキテクチャ

AnalyticsProvider Interface (Kotlin)

interface AnalyticsProvider {
    fun logEvent(name: String, params: Map<String, Any> = emptyMap())
    fun setUserProperty(name: String, value: String)
    fun setUserId(userId: String?)
    fun logScreenView(screenName: String, screenClass: String? = null)
}

AnalyticsProvider Protocol (Swift)

protocol AnalyticsProvider {
    func logEvent(_ name: String, parameters: [String: Any])
    func setUserProperty(_ value: String?, forName name: String)
    func setUserId(_ userId: String?)
    func logScreenView(screenName: String, screenClass: String?)
}

Multi-Provider Analytics Manager

class AnalyticsManager(
    private val providers: List<AnalyticsProvider>,
    private val consentManager: ConsentManager
) {
    fun logEvent(name: String, params: Map<String, Any> = emptyMap()) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.logEvent(name, params) }
    }

    fun setUserProperty(name: String, value: String) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.setUserProperty(name, value) }
    }

    fun setUserId(userId: String?) {
        providers.forEach { it.setUserId(userId) }
    }

    fun logScreenView(screenName: String, screenClass: String? = null) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.logScreenView(screenName, screenClass) }
    }
}

Event Data Classes

sealed class AnalyticsEvent(
    val name: String,
    val params: Map<String, Any> = emptyMap()
) {
    // E-commerce
    class ViewProduct(productId: String, category: String) : AnalyticsEvent(
        name = "view_product",
        params = mapOf("product_id" to productId, "category" to category)
    )

    class AddToCart(productId: String, price: Double, quantity: Int) : AnalyticsEvent(
        name = "add_to_cart",
        params = mapOf("product_id" to productId, "price" to price, "quantity" to quantity)
    )

    class Purchase(orderId: String, total: Double, currency: String) : AnalyticsEvent(
        name = "purchase",
        params = mapOf("order_id" to orderId, "total" to total, "currency" to currency)
    )

    // Engagement
    class Search(query: String, resultCount: Int) : AnalyticsEvent(
        name = "search",
        params = mapOf("query" to query, "result_count" to resultCount)
    )

    class ShareContent(contentType: String, itemId: String) : AnalyticsEvent(
        name = "share_content",
        params = mapOf("content_type" to contentType, "item_id" to itemId)
    )
}

// Usage
analytics.logEvent(AnalyticsEvent.ViewProduct("sku-123", "electronics"))

Android / Firebase Analytics

Setup and Initialization

class FirebaseAnalyticsProvider(context: Context) : AnalyticsProvider {
    private val firebaseAnalytics = FirebaseAnalytics.getInstance(context)

    override fun logEvent(name: String, params: Map<String, Any>) {
        val bundle = Bundle().apply {
            params.forEach { (key, value) ->
                when (value) {
                    is String -> putString(key, value)
                    is Int -> putInt(key, value)
                    is Long -> putLong(key, value)
                    is Double -> putDouble(key, value)
                    is Boolean -> putBoolean(key, value)
                }
            }
        }
        firebaseAnalytics.logEvent(name, bundle)
    }

    override fun setUserProperty(name: String, value: String) {
        firebaseAnalytics.setUserProperty(name, value)
    }

    override fun setUserId(userId: String?) {
        firebaseAnalytics.setUserId(userId)
    }

    override fun logScreenView(screenName: String, screenClass: String?) {
        val bundle = Bundle().apply {
            putString(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
            screenClass?.let { putString(FirebaseAnalytics.Param.SCREEN_CLASS, it) }
        }
        firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle)
    }
}

Screen Tracking with Lifecycle Observer

@Composable
fun TrackScreen(screenName: String, analytics: AnalyticsManager) {
    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) {
                analytics.logScreenView(screenName)
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
    }
}

// Usage in a screen composable
@Composable
fun ProductListScreen(analytics: AnalyticsManager) {
    TrackScreen("product_list", analytics)
    // Screen content...
}

iOS Analytics

Firebase Analytics Provider

final class FirebaseAnalyticsProvider: AnalyticsProvider {
    func logEvent(_ name: String, parameters: [String: Any]) {
        Analytics.logEvent(name, parameters: parameters)
    }

    func setUserProperty(_ value: String?, forName name: String) {
        Analytics.setUserProperty(value, forName: name)
    }

    func setUserId(_ userId: String?) {
        Analytics.setUserID(userId)
    }

    func logScreenView(screenName: String, screenClass: String?) {
        Analytics.logEvent(AnalyticsEventScreenView, parameters: [
            AnalyticsParameterScreenName: screenName,
            AnalyticsParameterScreenClass: screenClass ?? ""
        ])
    }
}

Screen Tracking with SwiftUI

struct AnalyticsScreenModifier: ViewModifier {
    let screenName: String
    @EnvironmentObject var analytics: AnalyticsManager

    func body(content: Content) -> some View {
        content.onAppear {
            analytics.logScreenView(screenName: screenName)
        }
    }
}

extension View {
    func trackScreen(_ name: String) -> some V
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Analytics Integration Patterns

Architecture

AnalyticsProvider Interface (Kotlin)

interface AnalyticsProvider {
    fun logEvent(name: String, params: Map<String, Any> = emptyMap())
    fun setUserProperty(name: String, value: String)
    fun setUserId(userId: String?)
    fun logScreenView(screenName: String, screenClass: String? = null)
}

AnalyticsProvider Protocol (Swift)

protocol AnalyticsProvider {
    func logEvent(_ name: String, parameters: [String: Any])
    func setUserProperty(_ value: String?, forName name: String)
    func setUserId(_ userId: String?)
    func logScreenView(screenName: String, screenClass: String?)
}

Multi-Provider Analytics Manager

class AnalyticsManager(
    private val providers: List<AnalyticsProvider>,
    private val consentManager: ConsentManager
) {
    fun logEvent(name: String, params: Map<String, Any> = emptyMap()) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.logEvent(name, params) }
    }

    fun setUserProperty(name: String, value: String) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.setUserProperty(name, value) }
    }

    fun setUserId(userId: String?) {
        providers.forEach { it.setUserId(userId) }
    }

    fun logScreenView(screenName: String, screenClass: String? = null) {
        if (!consentManager.hasAnalyticsConsent()) return
        providers.forEach { it.logScreenView(screenName, screenClass) }
    }
}

Event Data Classes

sealed class AnalyticsEvent(
    val name: String,
    val params: Map<String, Any> = emptyMap()
) {
    // E-commerce
    class ViewProduct(productId: String, category: String) : AnalyticsEvent(
        name = "view_product",
        params = mapOf("product_id" to productId, "category" to category)
    )

    class AddToCart(productId: String, price: Double, quantity: Int) : AnalyticsEvent(
        name = "add_to_cart",
        params = mapOf("product_id" to productId, "price" to price, "quantity" to quantity)
    )

    class Purchase(orderId: String, total: Double, currency: String) : AnalyticsEvent(
        name = "purchase",
        params = mapOf("order_id" to orderId, "total" to total, "currency" to currency)
    )

    // Engagement
    class Search(query: String, resultCount: Int) : AnalyticsEvent(
        name = "search",
        params = mapOf("query" to query, "result_count" to resultCount)
    )

    class ShareContent(contentType: String, itemId: String) : AnalyticsEvent(
        name = "share_content",
        params = mapOf("content_type" to contentType, "item_id" to itemId)
    )
}

// Usage
analytics.logEvent(AnalyticsEvent.ViewProduct("sku-123", "electronics"))

Android / Firebase Analytics

Setup and Initialization

class FirebaseAnalyticsProvider(context: Context) : AnalyticsProvider {
    private val firebaseAnalytics = FirebaseAnalytics.getInstance(context)

    override fun logEvent(name: String, params: Map<String, Any>) {
        val bundle = Bundle().apply {
            params.forEach { (key, value) ->
                when (value) {
                    is String -> putString(key, value)
                    is Int -> putInt(key, value)
                    is Long -> putLong(key, value)
                    is Double -> putDouble(key, value)
                    is Boolean -> putBoolean(key, value)
                }
            }
        }
        firebaseAnalytics.logEvent(name, bundle)
    }

    override fun setUserProperty(name: String, value: String) {
        firebaseAnalytics.setUserProperty(name, value)
    }

    override fun setUserId(userId: String?) {
        firebaseAnalytics.setUserId(userId)
    }

    override fun logScreenView(screenName: String, screenClass: String?) {
        val bundle = Bundle().apply {
            putString(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
            screenClass?.let { putString(FirebaseAnalytics.Param.SCREEN_CLASS, it) }
        }
        firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle)
    }
}

Screen Tracking with Lifecycle Observer

@Composable
fun TrackScreen(screenName: String, analytics: AnalyticsManager) {
    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) {
                analytics.logScreenView(screenName)
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
    }
}

// Usage in a screen composable
@Composable
fun ProductListScreen(analytics: AnalyticsManager) {
    TrackScreen("product_list", analytics)
    // Screen content...
}

iOS Analytics

Firebase Analytics Provider

final class FirebaseAnalyticsProvider: AnalyticsProvider {
    func logEvent(_ name: String, parameters: [String: Any]) {
        Analytics.logEvent(name, parameters: parameters)
    }

    func setUserProperty(_ value: String?, forName name: String) {
        Analytics.setUserProperty(value, forName: name)
    }

    func setUserId(_ userId: String?) {
        Analytics.setUserID(userId)
    }

    func logScreenView(screenName: String, screenClass: String?) {
        Analytics.logEvent(AnalyticsEventScreenView, parameters: [
            AnalyticsParameterScreenName: screenName,
            AnalyticsParameterScreenClass: screenClass ?? ""
        ])
    }
}

Screen Tracking with SwiftUI

struct AnalyticsScreenModifier: ViewModifier {
    let screenName: String
    @EnvironmentObject var analytics: AnalyticsManager

    func body(content: Content) -> some View {
        content.onAppear {
            analytics.logScreenView(screenName: screenName)
        }
    }
}

extension View {
    func trackScreen(_ name: String) -> some View {
        modifier(AnalyticsScreenModifier(screenName: name))
    }
}

// Usage
struct ProductListView: View {
    var body: some View {
        List { /* ... */ }
            .trackScreen("product_list")
    }
}

App Tracking Transparency (ATT)

import AppTrackingTransparency

func requestTrackingPermission() async -> ATTrackingManager.AuthorizationStatus {
    await ATTrackingManager.requestTrackingAuthorization()
}

// Call after app launch delay (Apple requirement)
func onAppBecomeActive() {
    Task {
        let status = await requestTrackingPermission()
        switch status {
        case .authorized:
            analytics.enableFullTracking()
        case .denied, .restricted:
            analytics.enableLimitedTracking()
        case .notDetermined:
            break
        @unknown default:
            break
        }
    }
}

Event Naming Conventions

Pattern Example Notes
noun_verb product_viewed Past tense for completed actions
noun_verb cart_item_added Include context noun
feature_action search_performed Feature-scoped
screen_action settings_opened Screen-scoped

Rules:

  • Use snake_case consistently
  • Max 40 characters per event name
  • Max 25 custom parameters per event
  • Prefix custom events to avoid Firebase reserved names

User Property Design

// Set on login
analytics.setUserProperty("subscription_tier", "premium")
analytics.setUserProperty("account_age_days", "365")
analytics.setUserProperty("preferred_language", "en")

Properties should be low-cardinality (not unique per user). Use for segmentation, not identification.


Privacy: Consent Management

class ConsentManager(private val prefs: SharedPreferences) {
    fun hasAnalyticsConsent(): Boolean = prefs.getBoolean("analytics_consent", false)
    fun hasAdConsent(): Boolean = prefs.getBoolean("ad_consent", false)

    fun updateConsent(analytics: Boolean, ads: Boolean) {
        prefs.edit()
            .putBoolean("analytics_consent", analytics)
            .putBoolean("ad_consent", ads)
            .apply()
        // Disable Firebase collection if consent revoked
        FirebaseAnalytics.getInstance(context).setAnalyticsCollectionEnabled(analytics)
    }
}

GDPR/CCPA checklist:

  • Show consent dialog before any tracking
  • Allow granular opt-in/opt-out
  • Provide data deletion request mechanism
  • Do not track until consent is given
  • Log consent timestamps for audit
  • Respect platform-level tracking preferences (ATT on iOS)