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本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
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
$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. 下の青いボタンを押して
analytics-patterns.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
analytics-patternsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
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_caseconsistently - 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)