# 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キャンペーンの作成