# 設定値配信のベストプラクティス

## 設定値配信のベストプラクティス

以下では設定値配信をアプリに組み込む場合のベストプラクティスを紹介しています。\
\&#xNAN;**※Variablesモジュールに関連する内容（fetch()やCompletionについて）については、設定値配信以外のVariablesモジュールを利用する機能も同様です**

## fetch()実行のタイミング

接客サービスのターゲットとして設定されるセグメント/ディメンションに指定されたデータについては、接客のトリガーとなるイベントが発火する前までに送信されている必要性があります。

※[ユーザー解析における強整合性](https://support.karte.io/post/l9sqplRlHKO1bpM6fpgyt) がサポートされているため、イベントの送信順に準拠したユーザー解析が行われます

設定値配信の場合、表示を行う箇所の描画の前にfetch()を実行、もしくは任意のイベントを発火させる必要がありますが、既存のイベント実装内容と合わせて、fetch()を実行するタイミングをご検討ください。

### fetch()実行を避けるべきタイミング

以下のようなタイミングでのfetch()実行は、意図せぬ結果を招く場合があります。

* 描画すべきタイミングに対して、fetch()実行のタイミングが遅い場合
  * fetch()を行った場合には、描画可能になる(=値が参照可能になる)タイミングはネットワーク環境にも依存しますが通常fetch()実行の数百msec後になります。
  * 画面トップのバナー等を描画する場合に、画面描画後に数百msec描画が遅れる場合には画面のがたつき等が生じる場合もあります。
* イベント解析に必要なイベントの送信前にfetch()を行っている
  * たとえば現在地に応じて設定値を出し分けしたい場合に、 `現在地の送信→fetch()`という順序であれば現在地に応じた設定値が取得できますが、`fetch()→現在地の送信`という逆の順番で送信された場合には、過去に送信された現在地（fetch解析時点での現在地の最新値）の内容に依存した設定値が取得されてしまいます。
* fetch()の完了直後に再度fetch()を行っている
  * 後述するCompletionを利用した実装で更新中のキャッシュの参照を避けられますが、fetch()完了直後等で短期間にfetch()自体が連続して発生する状況では、Completionを利用した場合でも更新中のキャッシュが参照されてしまう可能性があります。

[Appendix: 設定値配信の配信メカニズム](#appendix-設定値配信の配信メカニズム) も合わせてご確認ください。

## 設定値のアクションに設定できる内容と、アプリ側で必要になる実装の分類

通常のKARTEのpopupで配信されるアクションでは、以下のような要素でアクションが構成されています。

| popupの構成要素 | 役割                                     |
| ---------- | -------------------------------------- |
| HTML       | 配信されるアクションの表示上の構造                      |
| CSS        | 配信されるアクションのHTMLに対しての装飾                 |
| Script     | 配信されるアクション上で動作するビジネスロジックや、ユーザーからの入力の制御 |
| 変数         | 上記で利用される変数                             |

一方で設定値配信では`変数`のみが設定可能で、これを受け取ったアプリ側では、この値にのみ従って描画を制御する必要があります。

| 設定値配信の構成要素 | 役割              |
| ---------- | --------------- |
| 変数         | アプリ側で表示を行うための変数 |

通常のKARTEのpopupでは、Scriptとして以下のような処理を含んでいる場合もありますが、設定値の場合では以下のようなロジックをアクション上に持たせることができません。

* 変数やユーザー情報変数として動的に参照された値をJavaScriptで加工する
* 紐付けテーブルやアクションテーブルによって動的に参照された値をJavaScriptで加工する
* アクション上のUIからの入力を受け付け、表示の制御を行う

そのため、**従来popup上に実装していたこのような処理を行う必要がある場合は、アプリ側で実装する必要があります。**

## Completionハンドラを利用した実装

設定値配信ではキャッシュされた値を参照する方法として、get, getAllKeys等のメソッドが用意されています。

これらのメソッドは任意のタイミングで実行可能ですが、キャッシュの更新中等で実行された場合には意図しない結果になる可能性があります。\
このようなケースへの対処として、下記に例を挙げるCompletionを利用した実装パターンがあります。

Completionを利用することで、設定値のキャッシュ更新完了時にコールバックの形式で任意の処理を記述できます\
※Androidの場合は、任意のイベント送信のコールバックとして同等の記述が可能です。

{% tabs %}
{% tab title="Swift" %}
{% code overflow="wrap" %}

```swift
// fetch()実行完了時に変数を取得する
Variables.fetch { (isSuccessful) in
    if isSuccessful {
        let variable = Variable(name: "{{variable}}")
        //...
    }
}

// 任意のカスタムイベント送信完了時に変数を取得する
Tracker.track("{{custom_event}}").completion = { isSuccessful in
    if isSuccessful {
        let variable = Variable(name: "{{variable}}")
        //...
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code overflow="wrap" %}

```kotlin
// fetch()実行完了時に変数を取得する
Variables.fetch({ isSuccessful ->
    if (isSuccessful) {
        val variable = Variables.get("{{variable}}")
        // ...
    }
})

// 任意のカスタムイベント送信完了時に変数を取得する
Tracker.track("{{custom_event}}") { isSuccessful ->
    if (isSuccessful) {
        val variable = Variables.get("{{variable}}")
        // ...
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Completionハンドラを利用した実装によって、イベント解析後の最新のセグメント/ディメンション状態での設定値の取得完了後にキャッシュの参照が可能なため、特別な理由がない限りはCompletionハンドラを利用した実装が推奨されます。

[設定値配信でのFetchCompletionの利用](https://app.developers.karte.io/app-faq/implementing-fetch-completion) も合わせてご確認ください。

## 接客サービスの配信停止と、キャッシュされた値の関係

KARTE側で設定された接客サービスは、任意で配信停止、もしくは[配信終了日](https://support.karte.io/post/21V1C8Ivy6bcF84P43tWZr)を過ぎた場合に、接客が配信されなくなります。

一般的なpopupでは配信後に都度表示が行われるため、上記の型式で配信されなくなった場合、表示も行われなくなります。

設定値配信の場合は配信された値はSDKがローカルにキャッシュし、キャッシュされた値を任意でアプリ側から参照し、表示を行います。

そのため、過去配信された値のキャッシュがローカル残存していた場合には、配信停止された(もしくは配信終了日過ぎた)接客が表示されてしまう可能性があります。

このような挙動は、以下のような実装で回避可能です。

* 設定値に由来する描画を行う場合には、直前にかならずfetch()を行いキャッシュを更新する
* 変数として配信終了日を設定し、ローカルに残存してしまった場合にこの変数を利用して表示を制御する
* 任意のタイミングでキャッシュの削除が必要な場合には削除を行う
  * [\[iOS\]変数オブジェクトのキャッシュ削除](https://github.com/plaidev/karte-app-dev-docs/blob/main/japanese/ios-sdk/variables-ios-sdk/README.md#%E5%A4%89%E6%95%B0%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E5%89%8A%E9%99%A4)
  * [\[Android\] 変数オブジェクトのキャッシュ削除](https://github.com/plaidev/karte-app-dev-docs/blob/main/japanese/android-sdk/variables-android-sdk/README.md#%E5%A4%89%E6%95%B0%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E5%89%8A%E9%99%A4)

## 異常系への対応

SDKの動作対象外や、ネットワーク等の環境依存で設定値が取得できない場合が存在します。実装時にはこのようなケースへの考慮も必要です。

またKARTEでは解析結果に応じて接客サービスが返却されない場合もあるため、値が無い場合の描画については適切に設計及び実装が必要です。

また参照時にはデフォルト値の設定が可能なため、何らかの理由で参照できなかった場合にデフォルト値を表示させたい場合にはデフォルト値を設定してください。

参考: [変数取得に失敗した場合の挙動を定める](https://support.karte.io/post/0MTjCYQQZxiaqvsTjSpKb#2-3)

また必要に応じて[タイムアウト](https://app.developers.karte.io/app-faq/implementing-fetch-completion)時の挙動や、タイムアウト時のcallback挙動とキャッシュ更新についてもご確認ください。

## 設定値配信のテスト

設定値配信を利用した施策を実装する場合は、KARTE上の設定とアプリ側の実装の双方が必要になります。\
また通常のpopupと異なり、リリース後に問題が生じた場合に接客サービスの修正だけで対応できる場合も少ないため、アプリ側の実装と合わせてリリース前に入念なテストを行うことを推奨します。

以下がテストで確認すべき観点です。

* 値が存在しない場合の考慮ができているか？
  * ネットワーク不調等の異常系での挙動
  * 正常系で値が参照されなかった場合
* 接客サービスの停止、公開に応じて、適切に設定値の描画が行われているか？
* 値が表示されるときに、最新のキャッシュ状態から描画されているか？
  * 意図せずキャッシュ更新が行われずに値が描画されることはないか？
  * fetch()の完了を待たずにgetするような実装が行われていないか？
* 表示、タップ時にmessage\_open, message\_clickイベントが送信されているか？

## Appendix: 設定値配信の配信メカニズム

設定値配信はイベント送信に応じて接客が配信される形式で、下記のような形式で動作します。

![](https://2393392196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH4XuUv5EgXiqltJXSiRd%2Fuploads%2Fgit-blob-5bcb43408b41cab36ac13274f68d2fac94a0fea2%2F981232ad107117c4cdc953cd3b413ed46b98caa4f638086733bab4714be53544-_2024-11-19_14.18.20.png?alt=media)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://app.developers.karte.io/karte-for-app-best-practices/best-practices-for-variables-module.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
