8 アプリ内メッセージの実装
8.1 アプリ内メッセージとは
アプリ内メッセージとは、アプリ起動中のユーザーに向けてポップアップなどのメッセージを表示させることができる機能です。
この機能を使用することで、下記のようなことが実現できます。
- お知らせを OFF にしているユーザーに対してアプローチを行う
- (お知らせを ON にするように設定画面への遷移を促す、など)
- アプリのトップ画面を開いた際、キャンペーンなどのバナーを表示させる
- 商品をカートに入れたユーザーに対しクーポンを付与するようなバナーを表示させる
アプリ内メッセージはイベントトラッキングをつけた契機でメッセージの表示を行います。
そのため、事前にイベントトラッキングをつけておくようにしておけば必要になったタイミングで自由にメッセージの表示を行うことができます。
また、現在使用されておりますイベントトラッキングがありましたらそちらを対象にしたメッセージの表示も行えます。
8.1.1 推奨するイベント
アプリ内メッセージには、「推奨イベント」と呼ばれるイベントプリセットがあります。
「ログイン後」や「チュートリアル完了後」といったタイミングでは、新しくイベントを定義するよりも、上記プリセットをご利用いただくとスムーズに実装できます。
8.1.2 ご利用上の注意
8.1.2.1 組み込みに関する注意
本バージョンのSDKにおいて、アプリ内メッセージは SceneDelegate を使用する App 上では正常に動作しません。
原理上、実装を工夫することで表示できる可能性がありますが、本バージョンのSDKでは SceneDelegate 上の組み込みに関しては、各種検証が十分に行えていないこともあり、サポート対象外とさせていただきます。
8.1.2.2 通信に関する注意
アプリ内メッセージは表示の際にサーバーとの通信が発生します。
そのため、通信状況などによって表示が遅れたり、まれに表示自体が失敗することがあります。
アプリ内メッセージをトリガーにしないでください
「アプリ内メッセージが表示されていないとログインが行われない」といったように、後続処理のトリガーとしてアプリ内メッセージを利用した場合、 通信状況によってはアプリに対するユーザーエクスペリエンスを著しく低下させてしまう場合があります ので、そのような実装は行わないでください。
8.2 アプリ内メッセージの仕様
8.2.1 イベントアクション条件リスト
アプリ内メッセージは、任意のイベントが発生したことを契機に、ユーザーに対してメッセージの表示を行います。
この契機の一覧は内部で管理されており、以後この一覧を「イベントアクション条件リスト」と呼びます。
すなわち「イベントアクション条件リスト」には、どのメッセージがどのタイミングで表示されるべきであるか、が管理されています。
本ドキュメントでは、「イベントアクション条件リスト」を「条件リスト」と略記することがあります。
ただし、条件リストはメッセージのIDのみを管理しており、具体的なメッセージの内容は保持していません。
メッセージを表示するタイミングになった段階で初めてサーバーにIDを通知し、実際にアプリ内メッセージで表示するコンテンツを取得します。
8.2.2 処理の流れ
アプリ内メッセージが表示されるまでのおおまかな流れを以下に示します。
なお、図中の黒丸内数字は、説明のカッコ内の数値と対応しています。
また、図中の※印は省略可能な処理です。
バージョン 6.1.0 のガイドにおいて図をより詳しいものに変更しましたため、図中の一部の番号がバージョン 6.0.3 以前のものとは異なるものに変更されております。
チェックの一例
- 配信期間と回数制限などの条件を満足しているか(8)
- アプリがフォアグラウンド状態であるか
- 組み込み側からのチェック(9)(10) 後述の「デリゲート」の項を参照
エラーが発生した場合は、図では一部省略していますが、組み込み側でリトライ処理を制御できます。
組み込み側のチェックについては後述の「デリゲート」の項をご参照ください。
8.3 ご利用方法
8.3.1 受信処理の組み込み
アプリ内メッセージは、契機となる イベントトラッキングの付与 が正しく組み込まれていれば、本SDKを組み込むだけで受信できるようになります。
CoreData バージョンにご注意ください
主に SDK を旧バージョンからアップデートした場合において、CoreDataモデルバージョンが最新になっていない場合があります。
CoreData モデルバージョンは必ず 最新バージョン に設定してください。
最新になっていない場合、アプリ内メッセージを正常に受け取れないだけでなく、App実行時にクラッシュを引き起こす原因にもなります。
アプリ内メッセージの表示処理に割り込み処理を追加したい場合は、後述の 8.3.3 デリゲート に記した実装が必要です。
8.3.2 イベントトラッキングの付与
アプリ内メッセージを表示させるためには、必ずイベントトラッキングを付与する必要があります。
イベントトラッキングの付与には下記のメソッドを呼び出してください。
[[PopinfoReceiver sharedReceiver] trackEvent:@"イベントキー名" value:@{
@"testName1": @"testVal1",
@"testName2": @"testVal2"
}];
PopinfoReceiver.shared.trackEvent("イベントキー名", value: [
"testName1": "testVal1",
"testName2": "testVal2"
])
第1引数には、イベントのキー名を指定します。
第2引数には、イベントのキーに対する値を辞書型で格納します。
付与を行うイベントにつきましては「推奨イベント」も参考に組み込んでください。
また、推奨イベント app.top、app.first、app.update を付与するサンプルコードを以下に示します。
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (IS_FIRST_INSTALL && IS_AFTER_TUTORIAL) {
// チュートリアル突破後に初めてトップ画面を開いた場合
[[PopinfoReceiver sharedReceiver] trackEvent:@"app.first" value:nil];
} else if (IS_APP_UPDATED) {
// アプリをアップデート後にトップ画面を開いた場合
[[PopinfoReceiver sharedReceiver] trackEvent:@"app.update" value:nil];
} else {
// 通常時、トップ画面を開いた場合
[[PopinfoReceiver sharedReceiver] trackEvent:@"app.top" value:nil];
}
@end
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if isFirstInstall() && isAfterTutorial() {
// チュートリアル突破後に初めてトップ画面を開いた場合
PopinfoReceiver.shared.trackEvent("app.first", value: nil)
} else if isAppUpdated() {
// アプリをアップデート後にトップ画面を開いた場合
PopinfoReceiver.shared.trackEvent("app.update", value: nil)
} else {
// 通常時、トップ画面を開いた場合
PopinfoReceiver.shared.trackEvent("app.top", value: nil)
}
}
}
このサンプルではトップ画面を開いた際のアプリの状態によって、付与するイベントを分けています。
コード内において、 IS_FIRST_INSTALL や isFirstInstall() のような各種条件判定メソッドの具体的な実装は省略しています。
OSダイアログにご注意ください
許諾ダイアログのようなiOS由来のダイアログと、アプリ内メッセージが両方表示されてしまわないよう、 イベントを付与するタイミング にはご注意ください。
たとえば、loadSettings をコールするタイミングで上記のようなイベントをつけた場合、iOS のダイアログと同時にアプリ内メッセージが表示されてしまいます。
8.3.3 デリゲート
公開されている各種デリゲートを利用し、アプリ内メッセージの一部の処理に割り込むことが出来ます。
デリゲートメソッドを利用するためには、まず以下のように実装を行います。
PopinfoReceiverと同様にPopinfoEventActionReceiverのクラスのインスタンスとプロトコルの宣言を行います。- App 起動時にコールされる
application:didFinishLaunchingWithOptions:内で同クラスのインスタンスを生成します。
@interface AppDelegate : NSObject <UIApplicationDelegate, UNUserNotificationCenterDelegate, PopinfoReceiverDelegate> {
PopinfoReceiver *popinfoReceiver;
PopinfoEventActionReceiver *popinfoEventActionReceiver;
}
// ...
@end
@implementation AppDelegate
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
popinfoReceiver = [PopinfoReceiver sharedReceiver];
popinfoReceiver.delegate = self;
popinfoEventActionReceiver = [PopinfoEventActionReceiver sharedReceiver];
popinfoEventActionReceiver.delegate = self;
// ...省略...
}
// ...
@end
class AppDelegate: UIApplicationDelegate, UNUserNotificationCenterDelegate, PopinfoReceiverDelegate, PopinfoEventActionReceiverDelegate {
var popinfoReceiver: PopinfoReceiver!
var popinfoEventActionReceiver: PopinfoEventActionReceiver!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.popinfoReceiver = PopinfoReceiver.shared
self.popinfoReceiver.delegate = self
self.popinfoEventActionReceiver = PopinfoEventActionReceiver.shared
self.popinfoEventActionReceiver.delegate = self
// ...省略...
}
// ...省略...
}
これで、デリゲートメソッドを利用するための準備が整いました。
詳細については、 PopinfoEventActionReceiver.h およびAPIドキュメントをご参照ください。
本項において「条件」は、特に説明がない限り「アプリ内メッセージを表示するための条件」を指すものとします。
8.3.3.1 アプリ内メッセージの組み込み側承認
SDK でのアプリ内メッセージ判定が終わった後(シーケンス図における(9))に以下がコールバックされます。
- (BOOL)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
shouldFireActionByEvent:(NSString *__nonnull)event
withCategories:(NSArray<NSString *> *__nonnull)categories;
これを実装すると、アプリ側でアプリ内メッセージを表示させるかの最終判断を行うことができます。
- (BOOL)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
shouldFireActionByEvent:(NSString *__nonnull)event
withCategories:(NSArray<NSString *> *__nonnull)categories
{
// ORIGINAL_CHECK_RESULT_FOR の実装は省略
return ORIGINAL_CHECK_RESULT_FOR(event, categories);
}
func popinfoEventActionReceiver(_ popinfoEventActionReceiver: PopinfoEventActionReceiver, shouldFireActionByEvent event: String, withCategories categories: [String]) -> Bool {
// originalCheckResult の実装は省略
originalCheckResult(event: event, categories: categories)
}
実装しなかった場合は、 YES が返却されたものとして取り扱われます。
8.3.3.2 条件合致通知エラー時の処理
条件合致通知に失敗した際(シーケンス図における(13))に、下記がコールバックされます。
- (BOOL)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
shouldRetryOnErrorAtSendEvent:(NSString *__nonnull)event
withCategories:(NSArray<NSString *> *__nonnull)categories
onRetryCount:(NSInteger)retryCount;
これを実装することで、条件合致通知失敗時にリトライを行うことが出来ます。
- (BOOL)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
shouldRetryOnErrorAtSendEvent:(NSString *__nonnull)event
withCategories:(NSArray<NSString *> *__nonnull)categories
onRetryCount:(NSInteger)retryCount
{
// ORIGINAL_POLICY_OF_RETRY_WITH の実装は省略
return ORIGINAL_POLICY_OF_RETRY_WITH(event, categories, retryCount);
}
func popinfoEventActionReceiver(_ popinfoEventActionReceiver: PopinfoEventActionReceiver, shouldRetryOnErrorAtSendEvent event: String, withCategories categories: [String], onRetryCount retryCount: Int) -> Bool {
// originalPolicyOfRetryWith の実装は省略
originalPolicyOfRetryWith(event: event, categories: categories, retryCount: retryCount)
}
8.3.5 APIの設定値変更 にて、設定された最大回数を超えて、リトライが行われることはありません。
イベントアクションの発火が行われなかった場合、発火回数のカウントはされません。
実装しなかった場合は、NO が返却されたものとして取り扱われ、リトライ処理は行われません。
8.3.3.3 アプリ内メッセージ表示直前の校閲
アプリ内メッセージが表示される直前(シーケンス図における(15))にて、以下がコールバックされます。
- (NSString *__nonnull)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
copyeditInAppMsgHtmlString:(NSString *__nonnull)htmlString
withEvent:(NSString *__nonnull)event
categories:(NSArray<NSString *> *__nonnull)categories;
これを実装すると、アプリ内メッセージを表示する直前にコンテンツを編集することが出来ます。
たとえば、コンテンツに$userのような仮置の文字列を入れ、デバイスに登録したユーザー情報(氏名など)と置き換えることで、個人宛のメッセージを表示するような実装ができます。
- (NSString *__nonnull)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
copyeditInAppMsgHtmlString:(NSString *__nonnull)htmlString
withEvent:(NSString *__nonnull)event
categories:(NSArray<NSString *> *__nonnull)categories
{
// userName はすでに定義されているものとします
return [htmlString stringByReplacingOccurrencesOfString: @"{$user}さん、こんにちは" withString: [NSString stringWithFormat:@"%@さん、こんにちは", userName]]);
}
func popinfoEventActionReceiver(_ popinfoEventActionReceiver: PopinfoEventActionReceiver, copyeditInAppMsgHtmlString htmlString: String, withEvent event: String, categories: [String]) -> String {
// userName はすでに定義されているものとします
htmlString.replacingOccurrences(of: "{$user}さん、こんにちは", with: "\(userName)さん、こんにちは")
}
実装しなかった場合は、受け取ったコンテンツをそのままユーザーに表示します。
8.3.3.4 コンテンツ内のボタン押下時処理
アプリ内メッセージのボタンが押された際に以下がコールされます。
- (void)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
receivedTapActionAndGetUrl:(NSString *__nonnull)url;
これを実装することで、ボタンに指定した URL を受け取り、アプリ側でその内容によって処理を分けたりすることができます。
- (void)popinfoEventActionReceiver:(PopinfoEventActionReceiver *__nonnull)popinfoEventActionReceiver
receivedTapActionAndGetUrl:(NSString *__nonnull)url
{
// START_PROCESS_USING はすでに定義されているものとします
START_PROCESS_USING(url);
}
func popinfoEventActionReceiver(_ popinfoEventActionReceiver: PopinfoEventActionReceiver, receivedTapActionAndGetUrl url: String) {
// startProcessUsing はすでに定義されているものとします
startProcessUsing(url: url)
}
実装しなかった場合は、ボタンに定義された処理のみが実行されます。
8.3.4 デバッグモード
PopinfoConfiguration.m において popinfoTestLogUse を YES
に設定すると、アプリ内メッセージを表示するためのイベントが発生したタイミングで、コンソールにイベントのキー名を表示することが出来ます。
コンソール表示の書式
<キー名> matched. (現在の1日の表示回数,1日の最大表示回数)(トータル表示回数、トータル最大表示回数)
コンソール表示の例
<app.top> matched. (1,5)(1,-)
これはapp.top がマッチした際の例です。
- は無制限を表します。
8.3.5 APIの設定値変更
アプリ内メッセージにおいては、 以下の設定値を変更することができます。
付属のファイル SdkSettings.plist において、該当箇所を下記条件に従って変更してください。
| キー | 説明 | 初期値 | 最小値 | 最大値 |
|---|---|---|---|---|
EventActionApiCallMaxWaitSec |
アプリ内メッセージ用のAPIコールにおけるタイムアウト値(単位: 秒) | 10 | 5 | 60 |
EventActionApiRetryCountLimit |
アプリ内メッセージ用APIのコールが失敗した際に、再試行を行う回数の最大値 | 5 | 0 | 10 |
変更後の値がそれぞれの最小値以下または最大値以上だった場合は、初期値が適用されますのでご注意ください。
8.4 イベントトラッキングで推奨するイベント
アプリでイベントをつける際、推奨するイベントの一覧となります。
なお、イベントを付与する方法については「追加機能 8.イベントトラッキングのカスタマイズ」をご参照ください。
パラメータの付与は、必須ではありません。
推奨イベントの付与例
例として、商品をカートに入れたときのイベント場合は、以下のような実装になります。
パラメータが複数のイベントを付与する際は下記のように追加してください。
[[PopinfoReceiver sharedReceiver] trackEvent:@"shop.add_to_cart" value:@{
@"item_name": @"name",
@"quantity": @"1",
@"price": @"500",
@"currency": @"jpy"
}];
PopinfoReceiver.shared.trackEvent("shop.add_to_cart", value: [
"item_name": "name",
"quantity":"1",
"price": "500",
"currency": "jpy"
])
8.4.1 アプリ共通イベント
| イベントタイミング | イベント名 | パラメータ | 備考 |
|---|---|---|---|
| チュートリアル開始時 | app.tutorial_begin | ||
| チュートリアル終了時 | app.tutorial_complete | ||
| チュートリアル突破後、トップ画面に到達 | app.first | トップ画面でユーザーの任意操作が可能になったとき。初回起動判定はアプリ側で行う必要がある | |
| アプリ更新後にトップ画面を開いたとき | app.update | トップ画面でユーザーの任意操作が可能になったとき。アプリ更新判定はアプリ側で行う必要がある | |
| アプリのトップ画面を開いたとき | app.top | トップ画面でユーザーの任意操作を可能になったとき。初回時、更新時と重ならないよう注意 | |
| ログインしたとき | app.login | ログインが完了したあと | |
| 会員登録が完了したとき | app.sign_up | 会員登録が完了したあと | |
| マイページを開いたとき | app.mypage | ユーザー専用のページがある場合 | |
| お気に入り登録をしたとき | app.favorite | お気に入り登録が完了したあと | |
| アプリのお知らせページを開いたとき | app.news | news_id | 任意のお知らせを確認した場合(プッシュ通知とは別) |
| お問い合わせページを開いたとき | app.generate_lead |
8.4.2 ショッピング系アプリ
| イベントタイミング | イベント名 | パラメータ | 備考 |
|---|---|---|---|
| 支払い情報を追加したとき | shop.add_payment_info | ||
| 商品の詳細を確認したとき | shop.detail | item_id | |
| 商品をカートに入れたとき | shop.add_to_cart | item_id, quantity, item_name, price | |
| 商品の購入手続きを開始時 | shop.begin_checkout | item_id, quantity, item_name, price | |
| 商品の購入手続きが完了時 | shop.ecommerce_purchase | item_id, quantity, item_name, price, transaction_id | |
| 商品の購入をキャンセルとき | shop.purchase_cancel | item_id, quantity, item_name, price | |
| 払い戻しが行われたとき | shop.purchase_refund | transaction_id | |
| 商品の検索を行ったとき | shop.search | search_term | |
| クーポンのページを開いたとき | shop.coupon_view | coupon_id | |
| クーポンを利用した時 | shop.coupon_use | coupon_id |
8.4.3 鉄道系アプリ
| イベントタイミング | イベント名 | パラメータ | 備考 |
|---|---|---|---|
| 運行状況を確認したとき | train.info | train_line | |
| 乗り換え案内を開いたとき | train.transfer_guide | boarding_station, getting_off_station | |
| 時刻表を確認したとき | train.timetable | train_line | |
| 路線図を確認したとき | train.route_map | train_line | |
| 駅構内図を確認したとき | train.station_map | statioin | |
| マイ駅設定を追加したとき | train.add_station | statioin |