# iOS開発者ガイド ベータ機能 Mobile Pushは現在ベータ版です。機能、API、実装の詳細は正式リリース前に変更される可能性があります。 ## 概要 このガイドでは、Treasure Data iOS SDKを使用してiOSアプリにEngage Studio Mobile Push通知を統合するための実装要件を提供します。開発チームは次の機能を実装する必要があります: 1. **APNs/FCM連携**: Apple Push Notification ServiceとFirebase Cloud Messaging経由でプッシュ通知を受信 2. **トークン管理**: デバイストークンをTreasure Dataに登録および更新 3. **リッチ通知**: Notification Service Extensionを使用して画像付き通知を表示 4. **イベントトラッキング**: Treasure Data SDKを使用してユーザーインタラクション(配信、開封、削除、リンク)をトラッキング 5. **自動データアップロード**: Treasure Data SDKがイベントのTreasure Dataへのアップロードを自動的に処理 サンプル実装が利用可能 本番環境対応の完全なサンプルアプリケーションがGitHubで公開されています: **[Treasure Data Mobile Push - iOSサンプル](https://github.com/treasure-data/engage-push-notification-sample/tree/main/ios)** サンプルに含まれる内容: - FCMとTreasure Data SDK連携を含む完全なAppDelegate実装 - リッチメディア用のNotification Service Extension - Treasure Data SDKを使用したイベントトラッキング - ディープリンクとWebリンク処理 リポジトリをクローンして実装の参考にしてください。 ## 必要要件 | コンポーネント | 要件 | | --- | --- | | **最小iOSバージョン** | iOS 15.0以降 | | **言語** | Swift (推奨) またはObjective-C | | **必要なフレームワーク** | - Firebase Messaging SDK 12.7.0+ - Treasure Data iOS SDK 1.2.1+ - UserNotificationsフレームワーク - SafariServices (Webリンク処理用) | | **Xcodeバージョン** | Xcode 14.0以降 | | **トラッキングイベント** | `delivery`, `open`, `dismiss`, `deeplink_open`, `link_open`, `token_register` | ## アーキテクチャ概要 iOSアプリ実装は以下のコンポーネントで構成されます: ### 1. AppDelegate設定 **目的:** Firebaseを初期化し通知デリゲートを設定する **主な責務:** - Firebase SDKを初期化 - 通知センターのデリゲートを設定 - ユーザーから通知パーミッションをリクエスト - リモート通知に登録 - フォアグラウンドとバックグラウンドで通知イベントを処理 **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`AppDelegate.swift`を参照してください ### 2. Notification Service Extension **目的:** 通知に画像をダウンロードして添付する **主な責務:** - 表示前に通知を受信 - ペイロードから`image_url`を抽出 - リモートURLから画像をダウンロード - UNNotificationAttachmentを作成 - 通知コンテンツに添付ファイルを追加 **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`NotificationService.swift`を参照してください ### 3. FCM Token Service **目的:** Treasure Dataとのデバイストークン登録を管理する **主な責務:** - FirebaseからFCMトークンを取得 - アプリ起動時にTreasure Dataにトークンを登録 - トークン更新時に再登録 - ユーザーログイン時にトークンとユーザーIDを関連付け - `token_register`イベントをトラッキング **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`FCMTokenService.swift`を参照してください ### 4. Event Queue **目的:** Treasure Dataにアップロードする前にイベントをローカルに保存する **主な責務:** - UserDefaultsにイベントを永続化 - 最大サイズ制限(1000イベント)でFIFOキューを実装 - アップロード用のバッチドレインをサポート - キューオーバーフローを適切に処理 - DispatchQueueを使用したスレッドセーフな操作 **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`EventQueue.swift`を参照してください ### 5. Push Event Uploader **目的:** Treasure Data Ingest APIにイベントをアップロードする **主な責務:** - イベントをバッチアップロード(リクエストあたり最大500件) - 信頼性の高い実行にバックグラウンドキューを使用 - 失敗したアップロードの再試行ロジックを実装 - Treasure Dataポストバック APIにイベントを送信 - アップロード失敗を適切に処理 **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`PushEventUploader.swift`を参照してください ### 6. Deep Link Handler **目的:** 通知からのディープリンクを処理する **主な責務:** - SceneDelegateまたはAppDelegate経由でディープリンクURLを受信 - URLスキームとパスを解析 - ディープリンクに基づいて適切な画面に遷移 - SafariでWeb URLを開く **参照:** [サンプルリポジトリ](https://github.com/treasure-data/mobile-push-samples/tree/main/ios)の`SceneDelegate.swift`を参照してください ## プロジェクトセットアップ ### ステップ1: iOSプロジェクトにFirebaseを追加 1. Firebase Consoleから`GoogleService-Info.plist`をダウンロード 2. ファイルをXcodeプロジェクトに追加: - `GoogleService-Info.plist`をプロジェクトナビゲーターにドラッグ - **Copy items if needed**にチェックが入っていることを確認 - メインアプリターゲットに追加 3. Swift Package Managerを使用してFirebase SDKを追加: - Xcodeで **File** > **Add Packages...** に移動 - 入力: `https://github.com/firebase/firebase-ios-sdk` - バージョン12.0.0以降を選択 (最新: 12.7.0) - 次のproductsを追加: - `FirebaseMessaging` - `FirebaseAnalytics` (オプション) 4. またはCocoaPodsを使用 (`Podfile`に追加): ```ruby platform :ios, '13.0' use_frameworks! target 'YourApp' do pod 'Firebase/Messaging', '~> 12.7' pod 'Firebase/Analytics', '~> 12.7' end ``` その後実行: ```bash pod install ``` ### ステップ2: Xcodeでケイパビリティを設定 1. Project Navigatorでプロジェクトを選択 2. アプリターゲットを選択 3. **Signing & Capabilities**タブに移動 4. **+ Capability**をクリックして追加: - **Push Notifications** - **Background Modes** → **Remote notifications**にチェック ### ステップ3: Notification Service Extensionを作成 (リッチメディア用) 通知で画像をサポートするには、Notification Service Extensionが必要です: 1. Xcodeで **File** > **New** > **Target** に移動 2. **Notification Service Extension**を選択 3. Extension名を入力 (例: `NotificationService`) 4. **Finish**をクリック ### ステップ4: ディープリンク用にInfo.plistを設定 `Info.plist`にURLスキームサポートを追加: ```xml CFBundleURLTypes CFBundleURLSchemes myapp CFBundleURLName com.example.myapp ``` ## データペイロードスキーマ アプリは通知`userInfo`で以下のJSON構造を受信します: ```json { "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" } ``` | フィールド | 型 | 必須 | 説明 | | --- | --- | --- | --- | | `td_campaign_id` | String | Yes | Engage Studioからの一意のキャンペーン識別子 | | `title` | String | Yes | 通知タイトル | | `body` | String | Yes | 通知本文テキスト | | `image_url` | String | No | リッチ通知画像のURL | | `link` | String | No | Safariで開くWeb URL | ## イベントトラッキング アプリは以下のイベントをトラッキングし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はバッチ処理、キューイング、再試行ロジックを自動的に処理します。 完全なスキーマ詳細については[Push Events Table](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table)ドキュメントを参照してください。 ## テスト ### シミュレーターでのテスト (iOS 13+) iOSシミュレーターはiOS 13とXcode 11.4+からプッシュ通知をサポートしています: 1. テストペイロードファイル`test-notification.apns`を作成: ```json { "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" } ``` 1. シミュレーターに送信: ```bash xcrun simctl push booted com.example.myapp test-notification.apns ``` ### 実機でのテスト 1. アプリログからFCMトークンを取得 2. Firebase Console > Cloud Messagingを開く 3. **Send your first message**をクリック 4. タイトルと本文を入力 5. **Send test message**をクリック 6. FCMトークンを入力 7. デバイスに通知が表示されることを確認 ### イベントトラッキングの確認 Treasure Dataでクエリを実行してイベントがログに記録されていることを確認: ```sql SELECT time, type, campaign_id, message_id, platform FROM mobile.push_events WHERE platform = 'ios' ORDER BY time DESC LIMIT 100 ``` ## ユーザーID関連付け プッシュ通知イベントを特定のユーザーとリンクするには、FCMトークン登録時に`user_id`を渡します。 **実装ノート:** - **ログインユーザー**: トークン登録イベントに`user_id`(例: 顧客ID、メールハッシュ値)を含める - **未ログインユーザー**: `user_id`に`nil`を渡す — Treasure Dataはユーザーログイン時に後でトークンを関連付けます - **名前解決**: Treasure Dataは時間経過に伴う`fcm_token`値の照合によってイベントをリンクします ## トラブルシューティング ### 通知が受信されない 1. **APNs証明書を確認**: APNs認証キーがFirebase Consoleにアップロードされているか確認 2. **Bundle IDを確認**: XcodeのBundle IDがFirebase登録と一致するか確認(大文字小文字を区別) 3. **通知パーミッションを確認**: 設定 > 通知でアプリが通知パーミッションを持っているか確認 4. **デバイス登録を確認**: `didRegisterForRemoteNotificationsWithDeviceToken`が呼ばれているか確認 5. **Firebase Consoleでテスト**: Firebase Consoleから直接テスト通知を送信 ### リッチ画像が表示されない 1. **Notification Service Extensionを確認**: Extensionが適切に設定されアプリに追加されているか確認 2. **画像URLを確認**: URLがHTTPSであり画像にアクセス可能か確認 3. **Extensionログを確認**: Console.appを使用してExtensionログを確認 4. **ファイルサイズを確認**: 大きな画像はタイムアウトする可能性あり(制限約10MB) ### イベントがTreasure Dataに表示されない 1. **書き込みキーを確認**: Info.plistの`TDWriteKey`が正しくアクティブであるか確認 2. **エンドポイントを確認**: `TDEndpoint`がリージョン(US、東京、EU)と一致するか確認 3. **テーブル名を確認**: `TDDatabase`と`TDTable`がTreasure Dataに存在するか確認 4. **SDK初期化を確認**: AppDelegateでTreasure Data SDKが初期化されているか確認 5. **ログを有効化**: `TreasureData.enableLogging()`を追加してSDKの動作を確認 6. **手動アップロード**: `TreasureData.sharedInstance().uploadEvents()`を手動で呼び出してみる ### ディープリンクが機能しない 1. **URLスキームを確認**: `Info.plist`に正しい`CFBundleURLTypes`設定があるか確認 2. **ディープリンクをテスト**: Safariでテスト: アドレスバーに`myapp://test`を入力 3. **Scene Delegateを確認**: `scene(_:openURLContexts:)`が実装されているか確認 4. **URI形式を確認**: ディープリンクが登録されたスキームで始まっているか確認 ## セキュリティのベストプラクティス 1. **APIキーを保護**: - 実際の`TDWriteKey`をソース管理にコミットしない - GitにコミットするInfo.plistにはプレースホルダー値を使用 - 必要な設定を別途ドキュメント化 - 書き込み専用キーを使用(マスターキーではない) - 本番アプリではKeychainの使用を検討 2. **ディープリンクを検証**: - ナビゲーション前にディープリンクの宛先を常に検証 - 機密性の高いアクションにURL許可リストを実装 - ディープリンクパラメータをサニタイズ 3. **イベントデータを保護**: - イベントペイロードにPII(個人を特定できる情報)を含めない - 可能な限りハッシュ化または匿名化されたユーザーIDを使用 4. **ネットワークセキュリティ**: - APIエンドポイントには常にHTTPSを使用 - App Transport Security (ATS)を実装 - 本番アプリでは証明書ピン留めを検討 ## サンプルリポジトリ 完全な本番環境対応の実装: **[https://github.com/treasure-data/engage-push-notification-sample/tree/main/ios](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 # 依存関係 ``` ### ビルドと実行手順 #### CocoaPodsを使用する場合 1. 依存関係をインストール: ```bash cd ios pod install ``` 1. Xcodeでワークスペースを開く: ```bash open MyApp.xcworkspace ``` 1. Firebaseを設定: - `GoogleService-Info.plist`をあなたのFirebase設定ファイルに置き換える - Bundle IDをFirebaseアプリと一致するように更新 2. Treasure Dataを設定: - `PushEventUploader.swift`を開く - `YOUR_TD_WRITE_KEY`を実際の書き込み専用APIキーに置き換える - 必要に応じて`TD_DATABASE`と`TD_TABLE`を更新 3. ビルドして実行: - ターゲットデバイス/シミュレーターを選択 - Cmd+Rを押してビルドと実行 #### Swift Package Managerを使用する場合 1. Xcodeで`MyApp.xcodeproj`を開く 2. Firebaseパッケージを追加: - File > Add Packages... - 入力: `https://github.com/firebase/firebase-ios-sdk` - バージョン12.7.0以降を選択 - `FirebaseMessaging`と`FirebaseAnalytics`を追加 3. 上記CocoaPodsの手順3-5に従う ### テストワークフロー #### 事前準備 テストを開始する前に、以下を確認してください: - [ ] iOSアプリが登録されたFirebaseプロジェクト - [ ] Firebase ConsoleにアップロードされたAPNs認証キー - [ ] ダウンロードしてプロジェクトに追加された`GoogleService-Info.plist` - [ ] 作成されたTreasure Dataデータベースとテーブル - [ ] 取得した書き込み専用APIキー - [ ] 物理デバイスまたはiOS 13+シミュレーター #### シミュレーターでのテスト (iOS 13+) 1. テストペイロードファイル`test-notification.apns`を作成: ```json { "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" } ``` 1. シミュレーターでアプリを実行: ```bash # シミュレーターを起動 xcrun simctl boot "iPhone 15" # ビルドして実行 xcodebuild -workspace MyApp.xcworkspace \ -scheme MyApp \ -destination 'platform=iOS Simulator,name=iPhone 15' \ build ``` 1. テスト通知を送信: ```bash xcrun simctl push booted com.example.myapp test-notification.apns ``` 1. 通知が表示され画像が読み込まれることを確認 #### 実機でのテスト 1. USBケーブルでデバイスを接続 2. デバイスでDeveloper Modeを有効化: - 設定 > プライバシーとセキュリティ > Developer Mode 3. Xcodeからアプリをビルドしてインストール 4. XcodeコンソールでFCMトークンを確認: ``` FCM token: [your-token-here] ``` 1. Firebase Consoleからテスト通知を送信: - Firebase Console > Cloud Messagingを開く - "Send your first message"をクリック - タイトルと本文を入力 - "Send test message"をクリック - FCMトークンを貼り付け - "Test"をクリック 2. デバイスに通知が表示されることを確認 #### イベントトラッキングの確認 Treasure Dataにクエリを実行してイベントがログに記録されていることを確認: ```sql 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 ``` 期待されるイベントシーケンス: 1. `token_register` - アプリ起動時 2. `delivery` - 通知受信時 3. `open` - ユーザーが通知をタップ時 4. `link_open` または `deeplink_open` - 通知にリンクが含まれる場合 ### 実装チェックリスト 自分のアプリにプッシュ通知を実装する際は、このチェックリストを使用してください: #### フェーズ1: プロジェクトセットアップ - [ ] 最小デプロイメントターゲットiOS 13.0のiOSプロジェクトを作成 - [ ] XcodeでPush Notificationsケイパビリティを追加 - [ ] Background Modesケイパビリティを追加(Remote notifications) - [ ] Info.plistでディープリンク用のURLスキームを設定 - [ ] プロジェクトにFirebaseを追加(CocoaPodsまたはSPM) - [ ] `GoogleService-Info.plist`をダウンロードして追加 #### フェーズ2: コアコンポーネント - [ ] `AppDelegate`でFirebase初期化を実装 - [ ] `UNUserNotificationCenter`デリゲートを設定 - [ ] Firebase Messagingデリゲートを設定 - [ ] 通知パーミッションをリクエスト - [ ] リモート通知に登録 - [ ] トークン管理用の`FCMTokenService`を実装 - [ ] UserDefaults永続化を使用した`EventQueue`を実装 - [ ] URLSessionを使用した`PushEventUploader`を実装 #### フェーズ3: Notification Service Extension - [ ] Notification Service Extensionターゲットを作成 - [ ] `NotificationService`クラスを実装 - [ ] 画像ダウンロードロジックを追加 - [ ] 画像用の`UNNotificationAttachment`を作成 - [ ] Extensionタイムアウトを適切に処理 #### フェーズ4: イベントトラッキング - [ ] `willPresent`デリゲートで`delivery`イベントを追跡 - [ ] `didReceive response`デリゲートで`open`イベントを追跡 - [ ] 削除された通知の`dismiss`イベントを追跡 - [ ] Webリンクの`link_open`イベントを追跡 - [ ] アプリリンクの`deeplink_open`イベントを追跡 - [ ] アプリ起動時とトークン更新時に`token_register`イベントを追跡 #### フェーズ5: ディープリンク処理 - [ ] SceneDelegateで`scene(_:openURLContexts:)`を実装 - [ ] ディープリンクURLのスキームとパスを解析 - [ ] ディープリンクに基づいて適切な画面に遷移 - [ ] SafariまたはSFSafariViewControllerでWebリンクを処理 - [ ] ディープリンクの宛先を検証 #### フェーズ6: 設定とセキュリティ - [ ] プレースホルダー`TD_WRITE_KEY`を実際のキーに置き換え - [ ] APIキーを`.gitignore`に追加 - [ ] ネットワーク障害のエラーハンドリングを実装 - [ ] 失敗したアップロードの再試行ロジックを実装 - [ ] デバッグ用のログを追加(本番環境では削除) #### フェーズ7: テスト - [ ] シミュレーターで通知配信をテスト - [ ] 実機で通知配信をテスト - [ ] 通知内のリッチメディア(画像)をテスト - [ ] ディープリンクナビゲーションをテスト - [ ] Webリンク開封をテスト - [ ] Treasure Dataにイベントが表示されることを確認 - [ ] バックグラウンドアプリ状態でテスト - [ ] 強制終了アプリ状態でテスト ### ビルドトラブルシューティング #### "No such module 'Firebase'"エラー - CocoaPodsを使用する場合、`.xcworkspace`(`.xcodeproj`ではなく)を開いていることを確認 - 依存関係が不足している場合は`pod install`を実行 - ビルドフォルダをクリーン: Product > Clean Build Folder (Cmd+Shift+K) #### Notification Service Extensionが画像を読み込まない - 画像URLがHTTPSであることを確認 - 画像にアクセス可能であることを確認(ブラウザでURLをテスト) - Console.appでExtensionログを確認 - スキーム設定でExtensionターゲットのメモリ制限を増やしていることを確認 #### イベントがTreasure Dataに表示されない - `TD_WRITE_KEY`が正しいことを確認 - HTTP 200レスポンスのネットワークログを確認 - データベースとテーブル名が設定と一致することを確認 - EventQueueがイベントを永続化していることを確認(UserDefaultsを検査) #### ディープリンクが開かない - Info.plistのURLスキームがディープリンクと一致することを確認 - Safariからディープリンクをテスト: アドレスバーに`myapp://test`を入力 - SceneDelegateで`scene(_:openURLContexts:)`が実装されていることを確認 - iOS 12以下の場合は、代わりにAppDelegateに実装 ## 次のステップ 1. **サンプルリポジトリをクローン**して実装を確認 2. [Mobile Push Setup](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/mobile-push-setup)ガイドに従って**Firebaseを設定** 3. iOSアプリに**コンポーネントを実装** 4. **通知配信とイベントトラッキングをテスト** 5. [Push Events Table](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table)で**イベントデータを確認** 6. [Engage Studio](/ja/products/marketing-cloud/engage-studio/channels/mobile-push)で**最初のキャンペーンを作成** ## 関連ドキュメント - [Mobile Push Setup](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/mobile-push-setup) - FirebaseとAPNs設定 - [Android Developer Guide](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/developer-guide-android) - Android実装ガイド - [Push Events Table](/ja/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table) - イベントスキーマと分析クエリ - [Campaign Creation](/ja/products/marketing-cloud/engage-studio/channels/mobile-push) - Mobile Pushキャンペーンの作成