# モバイル SDK でのセッショントラッキング

セッションは、アプリが送信するイベントをひとまとまりのユーザーアクティビティ期間としてグループ化する仕組みです。セッションを使うと、ユーザーの滞在時間、1 回の利用で行った操作、コンバージョンが発生した訪問などを、訪問単位で分析できます。Treasure AI のモバイル SDK（Android、iOS、Unity、Cordova、React Native）には、**インスタンスセッション**と**グローバルセッション**という 2 つのセッション機構があり、スコープ、書き込まれる列、セッションの開始・終了イベントを記録するかどうかが異なります。このページでは両方の機構を定義し、それぞれがテーブルに何を書き込むかを示し、適切な使い分けを解説します。インストールや一般的なイベントトラッキングについては、[SDK ごとのセッション API](#sdk-%E3%81%94%E3%81%A8%E3%81%AE%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3-api) にリンクされている各 SDK のページを参照してください。

## グローバルセッションとインスタンスセッションの違い

**インスタンスセッション**は、1 つの `TreasureData` インスタンスにスコープされます。開始時に明示的な開始イベントを、終了時に明示的な終了イベントを、指定したテーブルに記録します。**グローバルセッション**は、アプリ内のすべての `TreasureData` インスタンスで共有されます。グローバルセッション自体はイベントを記録しません。代わりに、アクティブな間にトラッキングされるすべてのイベントに共有の `td_session_id` を付与し、短い中断の後にセッションを再開できるため、短時間のアプリ切り替えを 1 つのセッションとして扱えます。

| 項目  | インスタンスセッション  | グローバルセッション  |
|  --- | --- | --- |
| **スコープ** | 1 つの `TreasureData` インスタンス | アプリ全体 — すべての `TreasureData` インスタンスで共有 |
| **開始と終了の方法** | テーブル名を取るインスタンスメソッド。例: `startSession("demotbl")` と `endSession("demotbl")` | テーブル引数を取らない static（クラスレベル）メソッド。例: Android の `TreasureData.startSession(context)` と `TreasureData.endSession(context)` |
| **`td_session_event` の開始・終了イベントを記録** | はい — 開始時と終了時にそれぞれ 1 レコードを、指定したテーブルに記録 | いいえ — グローバルセッション自体はイベントを一切書き込まない |
| **トラッキングしたイベントへの `td_session_id` の付与** | はい（セッションがアクティブな間） | はい（セッションがアクティブな間）。両方のセッションがアクティブな場合はグローバルセッションの ID が優先される |
| **想定される用途** | 開始・終了レコードによる明示的なセッション境界 — 例: チェックアウトフローを 1 つの単位としてトラッキング | セッションタイムアウトを利用して、短い中断（画面回転、短時間のアプリ切り替え）を 1 つの連続したセッションとして扱う |


## セッションがテーブルに書き込む内容

SDK が管理する専用のセッションテーブルはありません。セッションは、イベントをストリーミングしているテーブルに次の列を追加します。

- `td_session_id` — セッションを識別する UUID 文字列。セッションがアクティブな間にトラッキングされるすべてのイベントに、SDK が自動的に追加します。
- `td_session_event` — `start` または `end`。インスタンスセッションのみが書き込みます。`startSession` と `endSession` はそれぞれ、この列を含むレコードを 1 件、指定したテーブルに追加します。


たとえば、`startSession("demotbl")` を呼び出し、その後 `endSession("demotbl")` を呼び出すと、`demotbl` に次の 2 レコードが生成されます。

```json
[
  {"td_session_id": "cad88260-67b4-0242-1329-2650772a66b1", "td_session_event": "start", "time": 1418880000},
  {"td_session_id": "cad88260-67b4-0242-1329-2650772a66b1", "td_session_event": "end", "time": 1418880123}
]
```

この 2 つの呼び出しの間にトラッキングした他のイベントには、送信先のテーブルがどこであっても同じ `td_session_id` が付与されます。`startSession` と `endSession` にメインのイベントテーブルを渡してセッション境界とイベントを同じテーブルにまとめることも、開始・終了レコード用に専用テーブルを使うこともできます。いずれの場合も、セッションの分析は `td_session_id` でイベントをグループ化して行います。`td_uuid`（デバイス ID）などのオプション列は、有効化していれば併せて出力されます。詳細は [About Mobile Tracking and Mobile SDKs](/products/customer-data-platform/integration-hub/streaming/mobile/about-mobile-tracking-and-mobile-sdks) を参照してください。

## グローバルセッションタイムアウトの仕組み

グローバルセッションは、グローバルの `endSession` を呼び出しても即座には終了しません。セッション ID はセッションタイムアウトの長さ（デフォルト 10 秒）だけ保持されます。そのウィンドウ内にアプリがグローバルの `startSession` を再度呼び出すと、前のセッションが同じ `td_session_id` で再開され、新しいセッションは作成されません。ウィンドウを過ぎると、次の `startSession` で新しいセッション ID が生成されます。これにより、Android の Activity の破棄・再生成や、ユーザーが一時的にアプリを離れた場合でもセッションを継続できます。

主な動作:

- Android と iOS では、セッションを開始する前に `TreasureData.setSessionTimeoutMilli(...)` でウィンドウを変更できます。Unity では再開ウィンドウは 10 秒です。
- グローバルの `endSession` の後は、セッションがまだ再開可能な間でも、グローバルの `getSessionId` は `null` を返します。
- `resetSessionId`（Android と iOS）を呼び出すと、新しいグローバルセッション ID が直ちに生成され、以降のイベントは前のセッションに関連付けられなくなります。
- セッション ID はメモリ内にのみ保持されます。アプリのプロセスが強制終了されると現在のセッション ID は破棄され、タイムアウトに関係なく、次回の起動で新しいセッションが開始されます。
- SDK が自動的にセッションを開始・終了することはなく、アプリがフォアグラウンドにある間に非アクティブでセッションが失効することもありません。セッションが終了するのは、アプリが `endSession` を呼び出したとき、またはプロセスが終了したときだけです。セッション API はアプリのライフサイクルコールバックから呼び出してください — 例: Android の `onStart`/`onStop`、iOS の `applicationDidBecomeActive:`/`applicationDidEnterBackground:`。


Web およびアプリ分析で一般的な慣例は 30 分の非アクティブウィンドウです。この動作にするには、タイムアウトを 30 分に設定し、アプリがフォアグラウンドに出入りするタイミングでグローバルセッションを開始・終了します。

```java
// Android — onCreate 内
TreasureData.setSessionTimeoutMilli(30 * 60 * 1000); // 30 分

// onStart 内 / アプリがフォアグラウンドに入ったとき
TreasureData.startSession(this);

// onStop 内 / アプリがフォアグラウンドから出たとき
TreasureData.endSession(this);
TreasureData.sharedInstance().uploadEvents();
```

この設定では、30 分未満の間隔で発生したフォアグラウンド訪問は 1 つの `td_session_id` を共有し、30 分以上経ってから（またはプロセスが強制終了された後に）戻ると新しいセッションが開始されます。

## session_start と session_end イベントの記録

`td_session_event` レコードを書き込むのはインスタンスセッションだけです。グローバルの `startSession` と `endSession` は、イベントに付与される `td_session_id` を変更するだけで、イベント自体は送信しません。そのため、グローバル API のみでセッションをトラッキングしている場合、テーブルには明示的な開始・終了レコードは存在しません。

グローバル API でセッションを管理しつつ境界イベントも必要な場合 — たとえばセッション開始を分析したい、後続の処理をトリガーしたい場合 — は、セッションを開始・終了するのと同じ箇所で `addEvent` を使って自分で記録します。

```java
// Android
TreasureData.startSession(this);
Map<String, Object> event = new HashMap<>();
event.put("event", "session_start");
TreasureData.sharedInstance().addEvent("demotbl", event);
```

グローバルセッションがアクティブなため、このレコードには現在の `td_session_id` が自動的に付与されます。

セッションタイムアウトとの相互作用に注意してください。ユーザーがタイムアウトウィンドウ内に離脱して戻ってきた場合、訪問ごとに独自の開始・終了レコードが生成されますが、SDK が同じセッションを再開したため、それらはすべて 1 つの `td_session_id` を共有します。これは想定どおりの動作です — 各レコードはフォアグラウンド訪問の境界を示し、共有された ID がそれらの訪問を 1 つのセッションにグループ化します。訪問ごとに別のセッションにしたい場合は、タイムアウトを短くするか、新しいセッションを開始する前に `resetSessionId` を呼び出してください。

## グローバルセッションとインスタンスセッションの併用

両方のセッションタイプを同時に実行することは避けてください。インスタンスセッションとグローバルセッションの両方がアクティブな場合、グローバルセッションが優先されます。トラッキングされるすべてのイベント — インスタンスの `startSession` と `endSession` が書き込む開始・終了レコードを含む — にはグローバルセッションの `td_session_id` が付与され、インスタンスセッションの ID は無視されます。この状態になると SDK は警告をログに出力します。2 つの ID はそれぞれ独立して生成された別の値であり、グローバルセッションがアクティブな間、インスタンスセッションの ID が書き込まれることはありません。

アプリごとに 1 つの機構を選んでください。短い中断をまたいで継続するアプリ全体のセッションが必要ならグローバルセッションを、追加のコードなしで明示的な開始・終了レコードが必要ならインスタンスセッションを使います。

## SDK ごとのセッション API

メソッド名は SDK ごとに異なります。Cordova と React Native のプラグインはインスタンスセッションのみを公開しています。

| SDK  | インスタンスセッション  | グローバルセッション  |
|  --- | --- | --- |
| [Android](/products/customer-data-platform/integration-hub/streaming/mobile/android) | `startSession(table)`、`endSession(table)`、`getSessionId()` | `TreasureData.startSession(context)`、`TreasureData.endSession(context)`、`TreasureData.getSessionId(context)`、`TreasureData.setSessionTimeoutMilli(millis)`、`TreasureData.resetSessionId(context)` |
| [iOS](/products/customer-data-platform/integration-hub/streaming/mobile/ios) | `startSession:`、`endSession:`、`getSessionId` | `[TreasureData startSession]`、`[TreasureData endSession]`、`[TreasureData getSessionId]`、`[TreasureData setSessionTimeoutMilli:]`、`[TreasureData resetSessionId]` |
| [Unity](/int/unity-sdk) | `StartSession(tableName)`、`EndSession(tableName)`、`GetSessionId()` | `StartGlobalSession()`、`EndGlobalSession()`、`GetGlobalSessionId()` |
| [Cordova](/products/customer-data-platform/integration-hub/streaming/mobile/cordova/api) | `startSession(sessionTable, sessionDatabase)`、`endSession(sessionTable, sessionDatabase)` | プラグインでは公開されていません |
| [React Native](/products/customer-data-platform/integration-hub/streaming/mobile/react-native/api) | `startSession(sessionTable, sessionDatabase)`、`endSession(sessionTable, sessionDatabase)` | プラグインでは公開されていません |


## よくある質問

### イベントに td_session_event がないのはなぜですか？

グローバルセッションは `td_session_event` を書き込みません。開始・終了イベントを記録するのは、インスタンスの `startSession(table)` と `endSession(table)` メソッドだけです。グローバルセッション API を使用していて境界レコードが必要な場合は、`addEvent` で自分で追加してください。[session_start と session_end イベントの記録](#session_start-%E3%81%A8-session_end-%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E8%A8%98%E9%8C%B2)を参照してください。

### アプリを強制終了するとグローバルセッション ID はリセットされますか？

はい。セッション ID はメモリ内にのみ保持されるため、アプリを強制終了する（または OS がプロセスを終了する）と、現在のグローバルセッション ID は破棄されます。セッションタイムアウトウィンドウ内であっても、次回の起動では新しい `td_session_id` で新しいセッションが開始されます。

### グローバルセッションとインスタンスセッションは同時に使えますか？

技術的には両方をアクティブにできますが、SDK は警告をログに出力し、インスタンスセッションの ID は無視されます。インスタンスセッション自身の開始・終了レコードを含むすべてのイベントには、グローバルの `td_session_id` が付与されます。アプリごとに 1 つの機構を使用してください。[グローバルセッションとインスタンスセッションの併用](#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%B5%E7%94%A8)を参照してください。

### Mobile In-App Messaging にはどちらのセッションタイプを使うべきですか？

記録したい内容に合った機構を使用してください。In-App Messaging のロジックが明示的なセッション開始・終了イベントをトリガーとする場合、インスタンスセッションはそれらを自動的に提供します。グローバルセッションの場合は境界イベントを自分で記録する必要があります。トリガーフローの仕組みは [Mobile In-App Messaging](/products/marketing-cloud/engage-studio/channels/mobile-inapp) を参照してください。

### アプリではなく SQL でセッションを計算できますか？

はい。イベントにタイムスタンプとユーザーまたはデバイスの識別子がすでにあれば、`TD_SESSIONIZE_WINDOW` ウィンドウ関数を使って、任意の非アクティブタイムアウトに基づきクエリ実行時にセッション ID を割り当てられます。Trino 関数リファレンスの [TD_SESSIONIZE_WINDOW](/products/customer-data-platform/data-workbench/queries/sql-reference/td_trino_function_reference#td_sessionize_window) を参照してください。

## 次のステップ

- [Android SDK](/products/customer-data-platform/integration-hub/streaming/mobile/android) — ライフサイクル全体のコード例
- [iOS SDK](/products/customer-data-platform/integration-hub/streaming/mobile/ios) — Objective-C と Swift の例
- [Unity SDK](/int/unity-sdk) — グローバルセッションとインスタンスセッションの使用方法
- [About Mobile Tracking and Mobile SDKs](/products/customer-data-platform/integration-hub/streaming/mobile/about-mobile-tracking-and-mobile-sdks) — SDK の機能とアカウント設定