Mobile Pushは現在ベータ版です。機能、API、実装の詳細は正式リリース前に変更される可能性があります。
このガイドでは、Treasure Data iOS SDKを使用してiOSアプリにEngage Studio Mobile Push通知を統合するための実装要件を提供します。開発チームは次の機能を実装する必要があります:
- APNs/FCM連携: Apple Push Notification ServiceとFirebase Cloud Messaging経由でプッシュ通知を受信
- トークン管理: デバイストークンをTreasure Dataに登録および更新
- リッチ通知: Notification Service Extensionを使用して画像付き通知を表示
- イベントトラッキング: Treasure Data SDKを使用してユーザーインタラクション(配信、開封、削除、リンク)をトラッキング
- 自動データアップロード: Treasure Data SDKがイベントのTreasure Dataへのアップロードを自動的に処理
本番環境対応の完全なサンプルアプリケーションがGitHubで公開されています:
Treasure Data Mobile Push - iOSサンプル
サンプルに含まれる内容:
- FCMとTreasure Data SDK連携を含む完全なAppDelegate実装
- リッチメディア用のNotification Service Extension
- Treasure Data SDKを使用したイベントトラッキング
- ディープリンクとWebリンク処理
リポジトリをクローンして実装の参考にしてください。
| コンポーネント | 要件 |
|---|---|
| 最小iOSバージョン | iOS 15.0以降 |
| 言語 | Swift (推奨) またはObjective-C |
| 必要なフレームワーク |
|
| Xcodeバージョン | Xcode 14.0以降 |
| トラッキングイベント | delivery, open, dismiss, deeplink_open, link_open, token_register |
iOSアプリ実装は以下のコンポーネントで構成されます:
目的: Firebaseを初期化し通知デリゲートを設定する
主な責務:
- Firebase SDKを初期化
- 通知センターのデリゲートを設定
- ユーザーから通知パーミッションをリクエスト
- リモート通知に登録
- フォアグラウンドとバックグラウンドで通知イベントを処理
参照: サンプルリポジトリのAppDelegate.swiftを参照してください
目的: 通知に画像をダウンロードして添付する
主な責務:
- 表示前に通知を受信
- ペイロードから
image_urlを抽出 - リモートURLから画像をダウンロード
- UNNotificationAttachmentを作成
- 通知コンテンツに添付ファイルを追加
参照: サンプルリポジトリのNotificationService.swiftを参照してください
目的: Treasure Dataとのデバイストークン登録を管理する
主な責務:
- FirebaseからFCMトークンを取得
- アプリ起動時にTreasure Dataにトークンを登録
- トークン更新時に再登録
- ユーザーログイン時にトークンとユーザーIDを関連付け
token_registerイベントをトラッキング
参照: サンプルリポジトリのFCMTokenService.swiftを参照してください
目的: Treasure Dataにアップロードする前にイベントをローカルに保存する
主な責務:
- UserDefaultsにイベントを永続化
- 最大サイズ制限(1000イベント)でFIFOキューを実装
- アップロード用のバッチドレインをサポート
- キューオーバーフローを適切に処理
- DispatchQueueを使用したスレッドセーフな操作
参照: サンプルリポジトリのEventQueue.swiftを参照してください
目的: Treasure Data Ingest APIにイベントをアップロードする
主な責務:
- イベントをバッチアップロード(リクエストあたり最大500件)
- 信頼性の高い実行にバックグラウンドキューを使用
- 失敗したアップロードの再試行ロジックを実装
- Treasure Dataポストバック APIにイベントを送信
- アップロード失敗を適切に処理
参照: サンプルリポジトリのPushEventUploader.swiftを参照してください
目的: 通知からのディープリンクを処理する
主な責務:
- SceneDelegateまたはAppDelegate経由でディープリンクURLを受信
- URLスキームとパスを解析
- ディープリンクに基づいて適切な画面に遷移
- SafariでWeb URLを開く
参照: サンプルリポジトリのSceneDelegate.swiftを参照してください
Firebase Consoleから
GoogleService-Info.plistをダウンロードファイルをXcodeプロジェクトに追加:
GoogleService-Info.plistをプロジェクトナビゲーターにドラッグ- Copy items if neededにチェックが入っていることを確認
- メインアプリターゲットに追加
Swift Package Managerを使用してFirebase SDKを追加:
- Xcodeで File > Add Packages... に移動
- 入力:
https://github.com/firebase/firebase-ios-sdk - バージョン12.0.0以降を選択 (最新: 12.7.0)
- 次のproductsを追加:
FirebaseMessagingFirebaseAnalytics(オプション)
またはCocoaPodsを使用 (
Podfileに追加):
platform :ios, '13.0'
use_frameworks!
target 'YourApp' do
pod 'Firebase/Messaging', '~> 12.7'
pod 'Firebase/Analytics', '~> 12.7'
endその後実行:
pod install- Project Navigatorでプロジェクトを選択
- アプリターゲットを選択
- Signing & Capabilitiesタブに移動
- + Capabilityをクリックして追加:
- Push Notifications
- Background Modes → Remote notificationsにチェック
通知で画像をサポートするには、Notification Service Extensionが必要です:
- Xcodeで File > New > Target に移動
- Notification Service Extensionを選択
- Extension名を入力 (例:
NotificationService) - Finishをクリック
Info.plistにURLスキームサポートを追加:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
</dict>
</array>アプリは通知userInfoで以下のJSON構造を受信します。カスタムデータフィールドに加えて、Engage Studioは配信トラッキングと削除トラッキングを有効化するcontent-availableフィールドとcategoryフィールドを含む標準のAPNs apsディクショナリを含めます(後述の配信トラッキングと削除トラッキングのためのAPNsフィールドを参照):
{
"aps": {
"alert": {
"title": "Special Offer!",
"body": "Get 20% off your next purchase"
},
"content-available": 1,
"category": "default"
},
"td_campaign_id": "cmp_20251214_promo",
"title": "Special Offer!",
"body": "Get 20% off your next purchase",
"image_url": "https://cdn.example.com/banner.png",
"link": "https://example.com/promo"
}| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
aps.content-available | Integer | Yes | Engage Studioにより1に設定されます。通知を受信したときにiOSにアプリをバックグラウンドで短時間起動するよう指示し、アプリがフォアグラウンドにない場合でもdeliveryイベントを記録できるようにします。 |
aps.category | String | Yes | Engage Studioによりdefaultに設定されます。アプリが登録する通知カテゴリを識別し、ユーザーが通知を削除したときにコールバックを受信できるようにすることで、dismissトラッキングを有効化します。 |
td_campaign_id | String | Yes | Engage Studioからの一意のキャンペーン識別子 |
title | String | Yes | 通知タイトル |
body | String | Yes | 通知本文テキスト |
image_url | String | No | リッチ通知画像のURL |
link | String | No | Safariで開くWeb URL |
Engage Studioは、アプリが配信イベントと削除イベントをトラッキングできるように、すべてのiOSプッシュ通知のapsディクショナリに2つのフィールドを自動的に追加します:
content-available: 1— 通知をバックグラウンド更新通知としてマークします。iOSは受信時にアプリをバックグラウンドで短時間起動するため、アプリがフォアグラウンドにない場合でもdeliveryイベントを記録できます。AppleのPushing background updates to your appを参照してください。category: default— 通知を通知カテゴリに関連付けます。アプリがカスタム削除アクションを許可する一致するカテゴリを登録すると、ユーザーが通知をスワイプして削除したときにiOSがデリゲートを呼び出し、dismissトラッキングを有効化します。AppleのGenerating a remote notificationを参照してください。
これらのペイロードフィールドはEngage Studioにより自動的に送信されるため、キャンペーンの設定は不要です。ただし、配信イベントと削除イベントを実際にキャプチャするには、後述の必要なアプリ側のセットアップを完了する必要があります。
アプリは以下のイベントをトラッキングしTreasure Dataに送信する必要があります:
| イベントタイプ | トラッキングタイミング | 必須フィールド |
|---|---|---|
delivery | 通知が受信され表示されたとき | campaign_id, message_id, platform, time |
open | ユーザーが通知をタップしたとき | campaign_id, message_id, platform, time, user_id |
dismiss | ユーザーが通知を削除したとき | campaign_id, message_id, platform, time, user_id |
link_open | ユーザーがWebリンクをタップしたとき | campaign_id, message_id, platform, time, user_id, value (URL) |
deeplink_open | ユーザーがディープリンクをタップしたとき | campaign_id, message_id, platform, time, user_id, value (URI) |
token_register | FCMトークンが取得または更新されたとき | fcm_token, platform, time, user_id (ログイン時) |
すべてのイベントはTreasure Data SDKにより、設定されたTreasure Dataエンドポイントに自動的に送信されます。SDKはバッチ処理、キューイング、再試行ロジックを自動的に処理します。
(アプリがバックグラウンドにある場合の)deliveryイベントとdismissイベントは、Engage Studioがペイロードに追加するcontent-availableフィールドとcategoryフィールドに依存します。これらのイベントをキャプチャするには、後述の配信トラッキングと削除トラッキングの有効化のセットアップを完了する必要があります。
完全なスキーマ詳細についてはPush Events Tableドキュメントを参照してください。
Engage Studioは、iOSプッシュペイロードにcontent-available: 1とcategory: defaultを自動的に追加します。これらをdeliveryイベントとdismissイベントに変換するには、アプリで以下を実装する必要があります。
ステップ5: XcodeでのCapabilitiesの設定で説明されているように、アプリターゲットでBackground Modes → Remote notificationsを有効化します。これにより、content-available: 1を持つ通知が到着したときにiOSがアプリをバックグラウンドで起動できるようになり、deliveryイベントを記録できます。
通知が削除されたときにiOSがアプリに通知するように、識別子defaultと.customDismissActionオプションを持つUNNotificationCategoryを登録します。通知センターを設定するとき(たとえばapplication(_:didFinishLaunchingWithOptions:)内)にカテゴリを設定します:
let defaultCategory = UNNotificationCategory(
identifier: "default",
actions: [],
intentIdentifiers: [],
options: [.customDismissAction]
)
UNUserNotificationCenter.current().setNotificationCategories([defaultCategory])identifierはペイロードで送信されるcategoryの値(default)と一致する必要があります。
ユーザーが通知をスワイプして削除すると、iOSはアクション識別子としてUNNotificationDismissActionIdentifierを指定してuserNotificationCenter(_:didReceive:withCompletionHandler:)を呼び出します。そこでdismissイベントをトラッキングします:
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
switch response.actionIdentifier {
case UNNotificationDismissActionIdentifier:
// User dismissed the notification
TrackingService.shared.track(event: "dismiss", userInfo: userInfo)
case UNNotificationDefaultActionIdentifier:
// User tapped the notification
TrackingService.shared.track(event: "open", userInfo: userInfo)
default:
break
}
completionHandler()
}アプリがバックグラウンドにある間にcontent-available: 1を持つ通知が到着すると、iOSはapplication(_:didReceiveRemoteNotification:fetchCompletionHandler:)を呼び出します。そこでdeliveryイベントを記録します。フォアグラウンドの通知はwillPresentデリゲートですでにトラッキングされているため、deliveryイベントの重複記録を避けるには、呼び出しをapplicationState != .activeでガードしてください:
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
// ここではバックグラウンド配信のみをトラッキングします。
// フォアグラウンド配信は重複イベントを避けるため willPresent デリゲートでトラッキングします。
if application.applicationState != .active {
TrackingService.shared.track(event: "delivery", userInfo: userInfo)
}
completionHandler(.newData)
}カテゴリ登録と配信/削除トラッキングの完全な実装については、サンプルリポジトリのAppDelegate.swiftを参照してください。
iOSシミュレーターはiOS 13とXcode 11.4+からプッシュ通知をサポートしています:
- テストペイロードファイル
test-notification.apnsを作成:
{
"Simulator Target Bundle": "com.example.myapp",
"aps": {
"alert": {
"title": "Test Notification",
"body": "This is a test message"
},
"sound": "default",
"badge": 1
},
"campaign_id": "test_campaign",
"message_id": "test_001",
"deeplink": "myapp://test"
}- シミュレーターに送信:
xcrun simctl push booted com.example.myapp test-notification.apns- アプリログからFCMトークンを取得
- Firebase Console > Cloud Messagingを開く
- Send your first messageをクリック
- タイトルと本文を入力
- Send test messageをクリック
- FCMトークンを入力
- デバイスに通知が表示されることを確認
Treasure Dataでクエリを実行してイベントがログに記録されていることを確認:
SELECT
time,
type,
campaign_id,
message_id,
platform
FROM mobile.push_events
WHERE platform = 'ios'
ORDER BY time DESC
LIMIT 100プッシュ通知イベントを特定のユーザーとリンクするには、FCMトークン登録時にuser_idを渡します。
実装ノート:
- ログインユーザー: トークン登録イベントに
user_id(例: 顧客ID、メールハッシュ値)を含める - 未ログインユーザー:
user_idにnilを渡す — Treasure Dataはユーザーログイン時に後でトークンを関連付けます - 名前解決: Treasure Dataは時間経過に伴う
fcm_token値の照合によってイベントをリンクします
- APNs証明書を確認: APNs認証キーがFirebase Consoleにアップロードされているか確認
- Bundle IDを確認: XcodeのBundle IDがFirebase登録と一致するか確認(大文字小文字を区別)
- 通知パーミッションを確認: 設定 > 通知でアプリが通知パーミッションを持っているか確認
- デバイス登録を確認:
didRegisterForRemoteNotificationsWithDeviceTokenが呼ばれているか確認 - Firebase Consoleでテスト: Firebase Consoleから直接テスト通知を送信
- Notification Service Extensionを確認: Extensionが適切に設定されアプリに追加されているか確認
- 画像URLを確認: URLがHTTPSであり画像にアクセス可能か確認
- Extensionログを確認: Console.appを使用してExtensionログを確認
- ファイルサイズを確認: 大きな画像はタイムアウトする可能性あり(制限約10MB)
- 書き込みキーを確認: Info.plistの
TDWriteKeyが正しくアクティブであるか確認 - エンドポイントを確認:
TDEndpointがリージョン(US、東京、EU)と一致するか確認 - テーブル名を確認:
TDDatabaseとTDTableがTreasure Dataに存在するか確認 - SDK初期化を確認: AppDelegateでTreasure Data SDKが初期化されているか確認
- ログを有効化:
TreasureData.enableLogging()を追加してSDKの動作を確認 - 手動アップロード:
TreasureData.sharedInstance().uploadEvents()を手動で呼び出してみる
- URLスキームを確認:
Info.plistに正しいCFBundleURLTypes設定があるか確認 - ディープリンクをテスト: Safariでテスト: アドレスバーに
myapp://testを入力 - Scene Delegateを確認:
scene(_:openURLContexts:)が実装されているか確認 - URI形式を確認: ディープリンクが登録されたスキームで始まっているか確認
APIキーを保護:
- 実際の
TDWriteKeyをソース管理にコミットしない - GitにコミットするInfo.plistにはプレースホルダー値を使用
- 必要な設定を別途ドキュメント化
- 書き込み専用キーを使用(マスターキーではない)
- 本番アプリではKeychainの使用を検討
- 実際の
ディープリンクを検証:
- ナビゲーション前にディープリンクの宛先を常に検証
- 機密性の高いアクションにURL許可リストを実装
- ディープリンクパラメータをサニタイズ
イベントデータを保護:
- イベントペイロードにPII(個人を特定できる情報)を含めない
- 可能な限りハッシュ化または匿名化されたユーザーIDを使用
ネットワークセキュリティ:
- APIエンドポイントには常にHTTPSを使用
- App Transport Security (ATS)を実装
- 本番アプリでは証明書ピン留めを検討
完全な本番環境対応の実装:
https://github.com/treasure-data/engage-push-notification-sample/tree/main/ios
リポジトリに含まれる内容:
- インラインドキュメント付きの完全なソースコード
- XcodeGenプロジェクト設定
- Swift Package Manager依存関係管理
- Treasure Data SDK連携の例
- テスト手順
- セキュリティのベストプラクティス
このセクションでは、サンプルアプリケーションのビルドとテストの詳細な手順を提供します。
サンプルリポジトリは以下のディレクトリ構造に従います:
ios/
├── MyApp/
│ ├── AppDelegate.swift # Firebase初期化、通知デリゲート
│ ├── SceneDelegate.swift # ディープリンクルーティング
│ ├── ViewController.swift # メインUI
│ ├── Models/
│ │ ├── FCMTokenService.swift # トークン登録
│ │ ├── EventQueue.swift # ローカルイベント保存
│ │ └── PushEventUploader.swift # TDへのバッチアップロード
│ ├── Assets.xcassets
│ ├── Info.plist
│ └── GoogleService-Info.plist # Firebase設定
├── NotificationService/ # リッチメディア用Extension
│ └── NotificationService.swift
├── MyApp.xcodeproj/
└── Podfile # 依存関係- 依存関係をインストール:
cd ios
pod install- Xcodeでワークスペースを開く:
open MyApp.xcworkspaceFirebaseを設定:
GoogleService-Info.plistをあなたのFirebase設定ファイルに置き換える- Bundle IDをFirebaseアプリと一致するように更新
Treasure Dataを設定:
PushEventUploader.swiftを開くYOUR_TD_WRITE_KEYを実際の書き込み専用APIキーに置き換える- 必要に応じて
TD_DATABASEとTD_TABLEを更新
ビルドして実行:
- ターゲットデバイス/シミュレーターを選択
- Cmd+Rを押してビルドと実行
Xcodeで
MyApp.xcodeprojを開くFirebaseパッケージを追加:
- File > Add Packages...
- 入力:
https://github.com/firebase/firebase-ios-sdk - バージョン12.7.0以降を選択
FirebaseMessagingとFirebaseAnalyticsを追加
上記CocoaPodsの手順3-5に従う
テストを開始する前に、以下を確認してください:
- iOSアプリが登録されたFirebaseプロジェクト
- Firebase ConsoleにアップロードされたAPNs認証キー
- ダウンロードしてプロジェクトに追加された
GoogleService-Info.plist - 作成されたTreasure Dataデータベースとテーブル
- 取得した書き込み専用APIキー
- 物理デバイスまたはiOS 13+シミュレーター
- テストペイロードファイル
test-notification.apnsを作成:
{
"Simulator Target Bundle": "com.example.myapp",
"aps": {
"alert": {
"title": "テスト通知",
"body": "これはテストメッセージです"
},
"sound": "default",
"badge": 1
},
"campaign_id": "test_campaign",
"message_id": "test_001",
"deeplink": "myapp://test",
"image_url": "https://example.com/image.jpg"
}- シミュレーターでアプリを実行:
# シミュレーターを起動
xcrun simctl boot "iPhone 15"
# ビルドして実行
xcodebuild -workspace MyApp.xcworkspace \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 15' \
build- テスト通知を送信:
xcrun simctl push booted com.example.myapp test-notification.apns- 通知が表示され画像が読み込まれることを確認
USBケーブルでデバイスを接続
デバイスでDeveloper Modeを有効化:
- 設定 > プライバシーとセキュリティ > Developer Mode
Xcodeからアプリをビルドしてインストール
XcodeコンソールでFCMトークンを確認:
FCM token: [your-token-here]Firebase Consoleからテスト通知を送信:
- Firebase Console > Cloud Messagingを開く
- "Send your first message"をクリック
- タイトルと本文を入力
- "Send test message"をクリック
- FCMトークンを貼り付け
- "Test"をクリック
デバイスに通知が表示されることを確認
Treasure Dataにクエリを実行してイベントがログに記録されていることを確認:
SELECT
time,
type,
campaign_id,
message_id,
platform,
user_id
FROM mobile.push_events
WHERE platform = 'ios'
AND time > td_time_add(now(), '-1h', 'JST')
ORDER BY time DESC
LIMIT 20期待されるイベントシーケンス:
token_register- アプリ起動時delivery- 通知受信時open- ユーザーが通知をタップ時link_openまたはdeeplink_open- 通知にリンクが含まれる場合
自分のアプリにプッシュ通知を実装する際は、このチェックリストを使用してください:
- 最小デプロイメントターゲットiOS 13.0のiOSプロジェクトを作成
- XcodeでPush Notificationsケイパビリティを追加
- Background Modesケイパビリティを追加(Remote notifications)
- Info.plistでディープリンク用のURLスキームを設定
- プロジェクトにFirebaseを追加(CocoaPodsまたはSPM)
-
GoogleService-Info.plistをダウンロードして追加
-
AppDelegateでFirebase初期化を実装 -
UNUserNotificationCenterデリゲートを設定 - Firebase Messagingデリゲートを設定
- 通知パーミッションをリクエスト
- リモート通知に登録
- トークン管理用の
FCMTokenServiceを実装 - UserDefaults永続化を使用した
EventQueueを実装 - URLSessionを使用した
PushEventUploaderを実装
- Notification Service Extensionターゲットを作成
-
NotificationServiceクラスを実装 - 画像ダウンロードロジックを追加
- 画像用の
UNNotificationAttachmentを作成 - Extensionタイムアウトを適切に処理
-
willPresentデリゲートでdeliveryイベントを追跡 -
.customDismissActionを持つdefault通知カテゴリを登録 - バックグラウンド配信のためにBackground Modes(Remote notifications)が有効になっていることを確認
-
didReceiveRemoteNotificationでバックグラウンドのdeliveryイベントを追跡 -
didReceive responseデリゲートでopenイベントを追跡 -
didReceive responseでUNNotificationDismissActionIdentifierのdismissイベントを追跡 - Webリンクの
link_openイベントを追跡 - アプリリンクの
deeplink_openイベントを追跡 - アプリ起動時とトークン更新時に
token_registerイベントを追跡
- SceneDelegateで
scene(_:openURLContexts:)を実装 - ディープリンクURLのスキームとパスを解析
- ディープリンクに基づいて適切な画面に遷移
- SafariまたはSFSafariViewControllerでWebリンクを処理
- ディープリンクの宛先を検証
- プレースホルダー
TD_WRITE_KEYを実際のキーに置き換え - APIキーを
.gitignoreに追加 - ネットワーク障害のエラーハンドリングを実装
- 失敗したアップロードの再試行ロジックを実装
- デバッグ用のログを追加(本番環境では削除)
- シミュレーターで通知配信をテスト
- 実機で通知配信をテスト
- 通知内のリッチメディア(画像)をテスト
- ディープリンクナビゲーションをテスト
- Webリンク開封をテスト
- Treasure Dataにイベントが表示されることを確認
- バックグラウンドアプリ状態でテスト
- 強制終了アプリ状態でテスト
- CocoaPodsを使用する場合、
.xcworkspace(.xcodeprojではなく)を開いていることを確認 - 依存関係が不足している場合は
pod installを実行 - ビルドフォルダをクリーン: Product > Clean Build Folder (Cmd+Shift+K)
- 画像URLがHTTPSであることを確認
- 画像にアクセス可能であることを確認(ブラウザでURLをテスト)
- Console.appでExtensionログを確認
- スキーム設定でExtensionターゲットのメモリ制限を増やしていることを確認
TD_WRITE_KEYが正しいことを確認- HTTP 200レスポンスのネットワークログを確認
- データベースとテーブル名が設定と一致することを確認
- EventQueueがイベントを永続化していることを確認(UserDefaultsを検査)
- Info.plistのURLスキームがディープリンクと一致することを確認
- Safariからディープリンクをテスト: アドレスバーに
myapp://testを入力 - SceneDelegateで
scene(_:openURLContexts:)が実装されていることを確認 - iOS 12以下の場合は、代わりにAppDelegateに実装
- サンプルリポジトリをクローンして実装を確認
- Mobile Push Setupガイドに従ってFirebaseを設定
- iOSアプリにコンポーネントを実装
- 通知配信とイベントトラッキングをテスト
- Push Events Tableでイベントデータを確認
- Engage Studioで最初のキャンペーンを作成
- Mobile Push Setup - FirebaseとAPNs設定
- Android Developer Guide - Android実装ガイド
- Push Events Table - イベントスキーマと分析クエリ
- Campaign Creation - Mobile Pushキャンペーンの作成