# Nubrickのメリット

#### *<mark style="color:blue;">モバイルアプリの開発には、多くの役割を跨いだ手間が存在する。</mark>*

モバイルアプリ市場はますます成長していますが、それでもなおモバイルアプリの開発やグロースは難しいとされています。特にプロダクトマネージャーや個人開発者が、ユーザー維持率やCVR（コンバージョン率）を向上させるために着手し開発すべきことは多く存在します。 例えば下記などがそうです。

* アプリのオンボーディング最適化
* 各種キャンペーンの実施
* A/Bテスト
* アプリ内サーベイ
* アプリアナリティクス

ここ数年、Firebase、Amplitude、Mixpanelなどのモバイル開発ツールがこれらの課題を解決するために広く使われています。

しかし、それでもモバイルアプリの開発はチームや個人にとって簡単なものではありません。その理由は次の通りです：

* これらのツールを使うためには、技術的なスキルが必要なことが多い。
* ただボタンの色を変えるだけのために、プロダクトマネージャーやデザイナーだけで完結できず、毎回エンジニアにチケットを切らなければならないことがある。
* エンジニアは低優先度のタスクが増えることで、アプリ全体の管理が煩雑になり、トラフィックの処理などの本質的な開発に集中できないことがある。

Nubrickはこれらの問題を解決し、皆さんを悩みから解放します。

***

### コンセプト

Nubrickは、モバイルアプリケーションの構築・管理を支援するツールです。Firebaseのように、UI/UXレベルでのA/Bテストやアナリティクス、アプリケーション設定の管理を`ほんの数秒`で行うための機能を提供します。

それだけではありません。Nubrickは、Figmaのような直感的なGUIを提供することで、開発者だけでなく、プロジェクトに関わる全員が簡単にモバイルアプリケーションを構築・管理できるようにします。

<figure><img src="/files/hIRnFo4gUa9xBuLvt9Oo" alt=""><figcaption></figcaption></figure>

***

### エクスペリメント

Nubrickの主な機能は「エクスペリメント」で、これを使用してアプリケーションの一部または全体のA/Bテスト、リモートコンフィグ、フィーチャーフラグ、デイリーキャンペーンなどを行うことができます。

実験には3つのタイプがあります：

#### 1. アプリ内メッセージ（In-App Messaging Experiment）

アプリケーション内でトリガーされたときにモーダルとして表示されるエクスペリメントです。Nubrick SDKをインストールすると、指定したトリガーイベントが発生した際に、特定の情報を表示するモーダルやアプリ内アンケート、利用規約モーダルなどが表示されます。

#### 2. 埋め込み（Embeddable Experiment）

アプリケーションにコンポーネントとして埋め込むことができるエクスペリメントです。一度埋め込むと、アプリ内でネイティブUIとして表示され、その後はコードを変更せずにその内容を瞬時に変更することができます。例えば、バナー、カルーセル、カードなど、必要なUIコンポーネントに使用できます。

#### 3. リモートコンフィグ（Remote Config） <a href="#remote-config" id="remote-config"></a>

アプリケーションの設定を管理するために使用されるリモート設定です。Firebase Remote Configのように、リモートで設定値を変更し、アプリケーションに反映させることができます。これを機能フラグや設定の変更に使用することができます。また、大規模な機能のテストを少数のユーザーグループに対して行う際にも役立ちます。<br>

### さあ、早速始めよう。

{% content-ref url="/pages/8Bu62PafsoHDkNYjy9C1" %}
[クイックスタート](/start/quickstart)
{% endcontent-ref %}


# 実現できるソリューション

Nubrickでは、アプリ内のネイティブUIを非常に高い柔軟性で管理できます。これにより、さまざまなソリューションを迅速に実現することができます。

<figure><img src="/files/RlimCqKkxRrwBOdnsCIz" alt=""><figcaption></figcaption></figure>

例えば、以下のようなユースケースに対応できます：

#### アプリのチュートリアル表示（オンボーディング）

アプリの初回起動時にユーザーに対してチュートリアルを表示し、使い方をガイドします。これにより、ユーザーのエンゲージメントを高め、アプリの利用促進が可能です。

#### アップデート通知

新しいバージョンのリリース時にユーザーにアップデート通知を表示し、アプリの最新機能を告知します。ユーザーのアクティブ化を促進できます。

#### アプリ内サーベイ

ユーザーからのフィードバックを収集するためにアプリ内サーベイを表示できます。これにより、ユーザーの意見や要望を反映させた改善を行いやすくなります。

#### バナーや広告の運用

アプリ内でのバナーや広告を表示し、プロモーションや広告キャンペーンを展開できます。ターゲットユーザーに向けたカスタマイズも簡単に行えます。

#### ユーザーに合わせたレコメンド

ユーザーの行動や過去のアクションに基づいて、個別のレコメンドを表示できます。これにより、ユーザーごとのパーソナライズド体験を提供し、エンゲージメントを高めることができます。

#### 商品のクーポン連携

アプリ内で提供する商品やサービスに対して、特定のユーザーに向けたクーポンを配布し、プロモーションを行うことができます。これにより、販売促進やユーザーの購買を促進できます。


# クイックスタート

このページではNubrickの利用ステップについて記載します

## Step1：アカウント作成

<https://dashboard.nubrick.app/signup>

初めて利用する方は上記URLにアクセスし、Signupの設定を行ってください。

既存プロジェクトへの新規ユーザーを招待したい場合は、アカウント作成後に招待が可能となりますので先にSignupの設定をお願いします。

## Step2：開発/初期実装

### 2-1：SDKをインストールする

{% content-ref url="/pages/JjjojIyKxaiBPzzLwvtg" %}
[SDKのインストール](/start/install)
{% endcontent-ref %}

上記URLにアクセスし、iOS・Android・Flutterから貴社の開発環境に合わせてインストールをお願いします。

### 2-2：（任意）埋め込み/プロダクトツアーを利用する場合はコードを実装する

* 埋め込み/プロダクトツアーを利用する場合にコードの実装が必要となります
  * このタイミングでのコード実装は必須ではありませんが、埋め込み/プロダクトツアーを利用する場合開発作業を効率よく進めたい場合に対応を推奨します
* コードの実装方法は各SDKリファレンスを確認してください
  * iOS：[NubrickSDK](/reference/ios/nubricksdk)
  * Android：[NubrickSDK](/reference/android/nubricksdk)
  * Flutter：[NubrickEmbedding](/reference/flutter/nubrickembedding) / [NubrickAnchor](/reference/flutter/nubrickanchor)

### 2-3：アプリリリース

* 必要なSDKのインストールとコードの実装が完了したら、アプリのリリースを実行してください

{% hint style="info" %}
ここまで完了すれば、後は管理画面でエクスペリメントを設定するだけで簡単にネイティブ画面のUIUXのABテスト、配信が可能になります！

エクペリメントを設定してみましょう！
{% endhint %}

## Step3：エクスペリメントの作成と配信

エクスペリメントの新規作成（実施する機能を選択する）をし、各エクスペリメントの配信条件を設定したら配信してみましょう！

{% content-ref url="/pages/oistVhWohCNgbmOUKRZK" %}
[アプリ内メッセージ(In-App Messaging)](/experiment_menu/modal)
{% endcontent-ref %}

{% content-ref url="/pages/cjvKPC8bHBQDjT4VAps0" %}
[アプリ内埋め込み (Embeddable Experiment)](/experiment_menu/embed)
{% endcontent-ref %}

{% content-ref url="/pages/jYBPNMb92CFGdB9VNbCj" %}
[プロダクトツアー (Product Tour)](/experiment_menu/tour)
{% endcontent-ref %}


# SDKのインストール

下記から、各プラットフォームに向けてNubrickのインストールを行いましょう。

<table data-view="cards"><thead><tr><th></th><th data-type="content-ref"></th></tr></thead><tbody><tr><td>for iOS</td><td><a href="/pages/ak0VOn5i1o1jVwyl4aDe">/pages/ak0VOn5i1o1jVwyl4aDe</a></td></tr><tr><td>for Android</td><td><a href="/pages/Xwi2Plk1l0LgtZcHCwq2">/pages/Xwi2Plk1l0LgtZcHCwq2</a></td></tr><tr><td>for Flutter</td><td><a href="/pages/lzkMDoyrIyRxaACjVUw4">/pages/lzkMDoyrIyRxaACjVUw4</a></td></tr></tbody></table>


# iOS

## サポート環境

* iOS 15.0 以上
* Xcode 16.1 以上

***

## Step 1. パッケージをインストールする

Swift Package ManagerまたはCocoaPodsが利用できます。

* [Swift Package Manager](https://github.com/plaidev/nubrick-ios/releases/latest)
* [CocoaPods](https://cocoapods.org/pods/Nubrick)

{% tabs %}
{% tab title="Swift Package Manager 🐦‍🔥" %}

1. Xcode上のメニューから、`File > Add Package Dependencies...` を選択する
2. `Search or Enter Package URL` の検索フィールドに次のURLを入力する
   1. `https://github.com/plaidev/nubrick-ios`
3. バージョンを選択し、インストールする
   1. ※基本的には最新バージョンを利用することを推奨しています。
      {% endtab %}

{% tab title="CocoaPods 🥥" %}
プロジェクトの Podfile に以下を追記します。

```ruby
target 'YourAppTarget' do
    pod 'Nubrick'
end
```

ターミナルから `pod install` を実行します。

```bash
pod install
```

{% hint style="warning" %}
ビルドに失敗した場合は、[Cocoapods エラーの解決方法](https://github.com/plaidev/nativebrik/blob/main/support-docs/ja/troubleshooting/cocoapods-error.md)を参照してください。
{% endhint %}
{% endtab %}
{% endtabs %}

## Step 2. Nubrick SDK を初期化する

{% hint style="warning" %}
`NubrickSDK.initialize(...)` は、`embedding` / `overlay` / `remoteConfig` / `dispatch` など他の API を使う前に、必ず 1 回だけ実行してください。\
SwiftUI では `@main` の `App` struct の `init()`、UIKit ではアプリ起動時（`AppDelegate` など）での初期化を推奨します。
{% endhint %}

### SwiftUI

`@main` の `init()` で SDK を初期化し、ルートビューを `NubrickProvider { ... }` で包んでオーバーレイ配信を表示できる状態にします。

```swift
import Nubrick
import SwiftUI

@main
@MainActor
struct YourApp: App {
    init() {
        NubrickSDK.initialize(projectId: "<YOUR_NUBRICK_PROJECT_ID>")
    }

    var body: some Scene {
        WindowGroup {
            NubrickProvider {
                ContentView()
            }
        }
    }
}
```

埋め込みコンポーネントは `NubrickSDK.embedding` で表示できます。

```swift
struct ContentView: View {
    var body: some View {
        VStack {
            NubrickSDK.embedding("ID_OF_YOUR_EMBEDDING")
                .frame(height: 240)
        }
    }
}
```

### UIKit

アプリ起動時に SDK を初期化し、`overlayViewController()` を画面ツリーに追加してオーバーレイ配信を表示できる状態にします。

```swift
import Nubrick
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        NubrickSDK.initialize(projectId: "<YOUR_NUBRICK_PROJECT_ID>")
        return true
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let overlay = NubrickSDK.overlayViewController()
        self.addChild(overlay)
        self.view.addSubview(overlay.view)
        overlay.didMove(toParent: self)

        let embeddingView = NubrickSDK.embeddingUIView("ID_OF_YOUR_EMBEDDING")
        self.view.addSubview(embeddingView)
    }
}
```


# Android

## サポート環境

* Android minSdk 26 以上
* Android Gradle Plugin 8.0 以上

***

## Step 1. パッケージをインストールする

Nubrick SDK は Maven Central から追加できます。

* [Maven Central](https://central.sonatype.com/artifact/app.nubrick/nubrick)

{% tabs %}
{% tab title="Gradle (Groovy)" %}
`build.gradle` に以下を追加します。

```gradle
dependencies {
  implementation 'app.nubrick:nubrick:<LATEST_VERSION>'
}
```

{% endtab %}

{% tab title="Gradle (Kotlin DSL)" %}
`build.gradle.kts` に以下を追加します。

```kotlin
dependencies {
  implementation("app.nubrick:nubrick:<LATEST_VERSION>")
}
```

{% endtab %}

{% tab title="Apache Maven" %}
`pom.xml` に以下を追加します。

```xml
<dependency>
  <groupId>app.nubrick</groupId>
  <artifactId>nubrick</artifactId>
  <version>${LATEST_VERSION}</version>
</dependency>
```

{% endtab %}
{% endtabs %}

## Step 2. Nubrick SDK を初期化する

{% hint style="warning" %}
`NubrickSDK.initialize(...)` は、`Embedding` / `RemoteConfig` / `dispatch` など他の API を使う前に、必ず 1 回だけ実行してください。
{% endhint %}

### Jetpack Compose

アプリ全体で 1 回だけ初期化するため、`Application` の `onCreate` で SDK を初期化し、`Activity` 側ではルート Composable を `NubrickProvider { ... }` で包みます。

```kotlin
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import app.nubrick.nubrick.Config
import app.nubrick.nubrick.NubrickProvider
import app.nubrick.nubrick.NubrickSDK

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        NubrickSDK.initialize(
            context = this,
            config = Config(projectId = "<YOUR_NUBRICK_PROJECT_ID>")
        )
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            NubrickProvider {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    NubrickSDK.Embedding(
                        id = "ID_OF_YOUR_EMBEDDING",
                        modifier = Modifier.height(240.dp)
                    )
                }
            }
        }
    }
}
```

既存の `Application` クラスがある場合は、その `onCreate` で `NubrickSDK.initialize(...)` を実行してください。\
`Application` クラスがない場合、新規作成して `AndroidManifest.xml` の `android:name` に指定してください。

### Java / XML

Java と Android View を利用する場合も、`Application` の `onCreate` で SDK を初期化します。

```java
import android.app.Application;

import app.nubrick.nubrick.Config;
import app.nubrick.nubrick.NubrickSDK;

public final class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        Config config = new Config("<YOUR_NUBRICK_PROJECT_ID>");
        NubrickSDK.initialize(this, config);
    }
}
```

埋め込みコンポーネントは `NubrickEmbeddingView` で表示します。ポップアップなどのオーバーレイ配信を表示するには、アプリのコンテンツより上に `NubrickOverlayView` を 1 つ配置してください。

```xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <app.nubrick.nubrick.view.NubrickEmbeddingView
            android:id="@+id/nubrick_embedding"
            android:layout_width="match_parent"
            android:layout_height="240dp"
            app:nubrickExperimentId="ID_OF_YOUR_EMBEDDING" />
    </LinearLayout>

    <app.nubrick.nubrick.view.NubrickOverlayView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
```


# Flutter

## サポート環境

### Android

* Android minSdk 26 以上
* Android Gradle Plugin: 8.0 以上

### iOS

* iOS 15.0 以上
* Xcode 16.1 以上

***

## Step 1. パッケージをインストールする

<https://pub.dev/packages/nubrick_flutter> にパッケージが公開されています。

以下のコマンドを実行してパッケージをインストールしてください。

{% code title="Terminal" %}

```bash
flutter pub add nubrick_flutter
```

{% endcode %}

または、直接`pubspec.yaml`を編集し、`pub get`を実行することでもインストールできます。

{% code title="pubspec.yaml" %}

```yaml
dependencies:
  nubrick_flutter: <LATEST_VERSION>
```

{% endcode %}

{% code title="Terminal" %}

```bash
flutter pub get
```

{% endcode %}

***

## Step 2. Nubrick SDKを初期化する

{% code title="main.dart" %}

```dart
import 'package:nubrick_flutter/nubrick_flutter.dart';
import 'package:nubrick_flutter/provider.dart';
import 'package:nubrick_flutter/user.dart';

// ...

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize Nubrick Client
  Nubrick.initialize("<PROJECT_ID>");

  // Run your app
  runApp(const MyApp());
}

class _YourAppState extends State<YourApp> {
  @override
  void initState() {
    super.initState();

    // Set user's properties to use them in the nubrick experiment
    final user = NubrickUser();
    await user.setProperties({
      'prefecture': "Tokyo",
      'environment': const bool.fromEnvironment('dart.vm.product')
          ? 'production'
          : 'development',
    });
  }

  @override
  Widget build(BuildContext context) {
    // Add NubrickProvider to your root widget
    return NubrickProvider(
      child: MaterialApp(
        // ...
      ),
    );
  }
}
```

{% endcode %}

## Step 3.a (Android only) Set up Platform Specific Code

To get it working on Android, you need to make a small change to your MainActivity.kt file.

{% code title="MainActivity.kt" %}

```kt
package com.example.app

import io.flutter.embedding.android.FlutterFragmentActivity

// 1. Extend FlutterFragmentActivity instead of FlutterActivity
class MainActivity: FlutterFragmentActivity()
```

{% endcode %}

and, set the minimum android sdk version to 26 in your android/app/build.gradle file.

{% code title="android/app/build.gradle" %}

```gradle
android {
    defaultConfig {
        // Set the minimum sdk version to 26
        minSdkVersion 26
    }
}
```

{% endcode %}

finally, set the kotlin version to >= 1.9.10 in your settings.gradle file.

{% code title="settings.gradle" %}

```gradle
plugins {
    // ...
    id "org.jetbrains.kotlin.android" version "1.9.10" apply false
}
```

{% endcode %}

## Step 3.b. (iOS only) Set up Platform Specific Code

To get it working on iOS, you need to change a minimum deployments to 15.0 in your ios/Runner.xcodeproj/project.pbxproj file.

1. In Xcode, navigate to `Runner.xcodeproj > TARGETS > Runner > General > Minimum Deployments`
2. Change the `minimum deployments` to `15.0`

Once you're finished, you can start using Nubrick.


# クイックスタート

まずは、アカウントの発行を行い、最初のモーダルを表示してみましょう。

<table data-view="cards"><thead><tr><th></th><th data-type="content-ref"></th></tr></thead><tbody><tr><td><ol><li>Make your Account</li></ol></td><td><a href="/pages/kU8rMp5OjWyvByiKhNAj">/pages/kU8rMp5OjWyvByiKhNAj</a></td></tr><tr><td><ol start="2"><li>Try In-App-Message</li></ol></td><td><a href="/pages/TW8JhHERUIZB7FAlJB4Z">/pages/TW8JhHERUIZB7FAlJB4Z</a></td></tr></tbody></table>


# アカウントの発行

### 1. アカウントを作成

[https://nativebrik.com/signup](https://app.nativebrik.com/signup) にアクセスします。

サービス利用規約、個人情報保護方針をチェックした上で、Googleでサインイン、またはメールアドレスとパスワードを入力し次へ進みます。

### 2. 認証コードを確認

`notifications@nativebrik.com`から、「XXXXXX is your verification code」 という件名のメールが届きます。

メールに記載されている認証コードをコピーして入力画面にペースト、次へ進みます。

{% hint style="warning" %}
メールが届かない場合は迷惑メールフォルダもご確認ください。迷惑メールフォルダに入っている場合はメール上部の「問題ない」をクリック後、認証コードをご利用ください。
{% endhint %}

<figure><img src="/files/1gGAE4zUZfvdBuz7bOSQ" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/fG9jTuPdJiV26q1wVBk4" alt=""><figcaption></figcaption></figure>

下記の画面が表示されれば成功です。

<figure><img src="/files/GcGwTDrSZkaXvhbQx83b" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Closed β期間はプロジェクト作成が権限上不可となっているため、Nubrickメンバーからプロジェクトへの招待をお待ちください。
{% endhint %}

### 3. 招待リンクからプロジェクトに参加する<br>

Nubrickメンバーから、プロジェクトへの招待リンクを受け取ります。

招待リンクをクリックすると、プロジェクト名が記載された下記のような画面が表示されます。

<figure><img src="/files/TBojcqC685aZzAan0UDE" alt=""><figcaption></figcaption></figure>

`Accept invite`をクリックし、先ほど作成したアカウントでログインを行い、管理画面が表示されたら完了です。

<figure><img src="/files/4nEJ0ba6yHhd51Vop2iJ" alt=""><figcaption></figcaption></figure>


# モーダルを表示する

クイックスタートへようこそ！

{% hint style="info" %}
SDKのインストールがまだの方は、最初に下記を参考の上、作成をお願いします。

<https://docs.nativebrik.com/start/install>
{% endhint %}

ここからは、日常的に使用するNubrickの使い方を紹介します。まずは、モーダル（アプリ内メッセージ）を作成し、ユーザーに新しい機能を通知する方法を学びます。

{% hint style="success" %}
このセクションで学ぶこと

アプリ全体のうち10%のユーザーに向けて、新しい機能を通知するモーダル（アプリ内メッセージ）を作成できるようになる。
{% endhint %}

***

### Step 1. やりたいことを思い浮かべる <a href="#step-1-design-what-you-want-to-do" id="step-1-design-what-you-want-to-do"></a>

ここでは、アプリの新しい機能をユーザーに知らせたいと仮定します。この目的のために、アプリ内メッセージを使ってユーザーに通知する方法を検討します。メッセージの内容は次のようにデザインします：

* 新機能のお知らせ
  * 「新機能が追加されました！」というメッセージ
  * 「今すぐチェック」などのボタン

<figure><img src="/files/46u8Tf5NrdvErLG7mKeg" alt="" width="188"><figcaption></figcaption></figure>

また、すべてのユーザーにメッセージを表示するのではなく、10%のユーザーに表示するように設定します。これにより、メッセージの効果を小さなユーザーグループでテストし、必要に応じて改善を加えることができます。

***

### Step 2. エクスペリメントを作成・設定する <a href="#step-2-create-and-configure-an-experiement" id="step-2-create-and-configure-an-experiement"></a>

ログイン後、ダッシュボードページにアクセスし、以下の手順に従ってエクスペリメントを作成します。

1. **「エクスペリメント」ページに移動**します。
2. **「新規作成」ボタン**をクリックし、「アプリ内メッセージ」を選択します。
3. エクスペリメント設定ページが表示されるので、以下の設定を行います：
   * エクスペリメント名に「新機能のお知らせメッセージ（10%のユーザー）」と入力
   * トリガーを「一度だけ」に設定し、「アプリ起動時」を選択
   * 配信割合を「10%」に設定

<figure><img src="/files/Tzh7bp8pPVFgQ52ZNVLO" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/BaC6HirG6Boo46mpn4mh" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/EJjZSZSj0emrZDJ2T3r0" alt=""><figcaption></figcaption></figure>

次に、`「バリアント」`の「モーダルを新規作成」をクリックし、メッセージのデザインを行います。

<figure><img src="/files/R7qLjg5ZwM9C2IClgRg0" alt=""><figcaption></figcaption></figure>

最後に、「Confirm」ボタンをクリックしてデザインを保存し、「保存」ボタンをクリックして設定を完了します。

<figure><img src="/files/VXuBSli2tQ1sQSDXehre" alt=""><figcaption></figcaption></figure>

***

### Step 3. エクスペリメントを実行する <a href="#step-3-run-the-experiment" id="step-3-run-the-experiment"></a>

エクスペリメント設定ページに戻ると、作成したエクスペリメントの設定内容とそのアナリティクスが表示されます。

<figure><img src="/files/qODoz0Wlp0Nuy1sGInfB" alt=""><figcaption></figcaption></figure>

**「配信する」ボタン**をクリックすると、エクスペリメントが開始され、数秒後にアプリに反映されます。

***

### Step 4. iOS/Androidアプリで確認する <a href="#step-4-check-it-on-your-iosandroid-app" id="step-4-check-it-on-your-iosandroid-app"></a>

エクスペリメントが反映されたら、実際にiOSまたはAndroidのアプリでメッセージが表示されるか確認します。アプリを起動すると、新機能のお知らせモーダルが表示されるはずです。

<figure><img src="/files/adNnKnlQISGbX9l5X1G1" alt="" width="375"><figcaption></figcaption></figure>


# アプリ内埋め込みを作成する

このページでは、エンベデッドコンポーネント（アプリ内埋め込み）を作成し、ユーザーに重要な情報を通知したりレコメンドを行う方法を学びます。

{% hint style="success" %}
このセクションで学ぶこと

特定の期間に行う限定キャンペーンを、ユーザーへ通知するエンベデッドコンポーネント（アプリ内埋め込み）を作成できるようになる。
{% endhint %}

***

### Step 1. やりたいことを思い浮かべる <a href="#step-1-design-what-you-want-to-do" id="step-1-design-what-you-want-to-do"></a>

ここでは、期間限定のキャンペーンを、アプリの画面上部でユーザーに知らせたいと仮定します。この目的のために、アプリ内埋め込みを使ってユーザーに通知する方法を検討します。メッセージの内容は次のようにデザインします：

* 期間限定キャンペーン
  * 「期間限定」というバナー
  * アプリの画面のファーストビューに埋め込む

<figure><img src="/files/VdDLO5OV5vWI7Jn8WYx3" alt="" width="375"><figcaption></figcaption></figure>

また、埋め込みを長期で表示するのではなく、期間を限定して表示するように設定します。これにより、キャンペーンバナーのCTR向上や、過剰なキャンペーン通知による体験阻害を抑えることができます。　

***

### Step 2. アプリ側でコードを1行挿入する <a href="#step-2-create-and-configure-an-experiement" id="step-2-create-and-configure-an-experiement"></a>

（下記はiOSでの例になります）

[エクスペリメントに関するドキュメント](/reference/ios/nubricksdk)を参考に、アプリ内でキャンペーンを挿入したい部分に、NubrickSDKのコードを挿入します。

{% hint style="info" %}
コード側では、エクスペリメントIDまたは、次のステップで説明する任意のカスタムIDを設定し、使用できます。場所ごとにカスタムIDを事前に設定しておくことをお勧めします。これにより、コードを編集せずに、`Nubrick` の管理画面で柔軟にエクスペリメントを変更できます。
{% endhint %}

```swift
struct YourView: View {
    var body: some View {
        NubrickSDK.embedding("<EXPERIMENT_ID> or <EXPERIMENT_CUSTOM_ID>")
            .frame(height: 200)
    }
}
```

***

### Step 3. エクスペリメントを作成・設定する <a href="#step-2-create-and-configure-an-experiement" id="step-2-create-and-configure-an-experiement"></a>

ログイン後、ダッシュボードページにアクセスし、以下の手順に従って実験を作成します。

1. **「エクスペリメント」ページに移動**します。
2. **「新しいエクスペリメントを作成」ボタン**をクリックし、「エンベデッドコンポーネント」を選択します。
3. エクスペリメント設定ページが表示されるので、以下の設定を行います：
   * エクスペリメント名に「キャンペーンバナー（期間限定）」と入力
   * ID Alias（エイリアス）に、先ほどコードに入力したカスタムIDを入力
   * 配信割合を「100%」に設定
   * 配信スケジュールで、特定の日時を選択
   * 配信期間で、配信する日数を入力

<figure><img src="/files/oIWG48DM67ugvMOJ47iV" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/PUqinJL9AwJEU8CdRJLZ" alt=""><figcaption></figcaption></figure>

次に、`「バリエーション設定」`の「コンポーネントを新規作成」をクリックし、埋め込みのデザインを行います。

{% hint style="warning" %}
Nubrickでは、テキストのColorを指定しない際、\
iOS, Androidの外観モードに合わせて文字色を変更する仕様となっております。

エディタ上では黒色のテキストも、アプリユーザーの端末がダークモードの場合は、文字色が白色になりますので、\
アプリ側でダークモードの対応をされていない場合は、お手数ですが、明示的にColorの指定をお願いいたします。
{% endhint %}

<figure><img src="/files/K7lteK0S7zghPVTQf5Vt" alt=""><figcaption></figcaption></figure>

最後に、「確認」ボタンをクリックしてデザインを保存し、「エクスペリメントを保存」ボタンをクリックして設定を完了します。

<figure><img src="/files/g7M1iAtC8dC5b32QEkhJ" alt=""><figcaption></figcaption></figure>

***

### Step 4. エクスペリメントを実行する <a href="#step-3-run-the-experiment" id="step-3-run-the-experiment"></a>

エクスペリメント設定ページに戻ると、作成したエクスペリメントの設定内容とそのアナリティクスが表示されます。

<figure><img src="/files/ganWe3RWAVSA0rVLkwSM" alt=""><figcaption></figcaption></figure>

**「エクスペリメントをデプロイ」ボタン**をクリックすると、エクスペリメントが開始され、対象期間にアプリに反映されます。

***

### Step 5. iOS/Androidアプリで確認する <a href="#step-4-check-it-on-your-iosandroid-app" id="step-4-check-it-on-your-iosandroid-app"></a>

エクスペリメントが反映されたら、実際にiOSまたはAndroidのアプリで埋め込みが表示されるか確認します（上記の設定では、特定の期間になっているので、開発環境では現在の期間またはImmediateを選択してご確認ください）。

アプリを起動すると、期間限定のキャンペーンバナーが、指定した位置に表示されるはずです。

<figure><img src="/files/ySB4U4n1XFKxpW6n9Xvk" alt="" width="375"><figcaption></figcaption></figure>


# プロダクトツアーを作成する

このページでは、プロダクトツアー（ツールチップによるアプリ内ガイド）を作成し、ユーザーにアプリの使い方やアップデートを伝える方法を学びます。

{% hint style="success" %}
このセクションで学ぶこと

アプリに初回来訪したユーザーに、プロダクトの使い方を伝え、リテンションアップにどれだけ寄与したかを計測する。
{% endhint %}

***

### Step 1. やりたいことを思い浮かべる <a href="#step-1-design-what-you-want-to-do" id="step-1-design-what-you-want-to-do"></a>

ここでは、初回来訪したユーザーに対して、アプリ内で任意の要素をユーザーにハイライトし、実際に触れてもらうことを目的とします。メッセージの内容は次のようにデザインします：

* 「初回来訪ユーザー向けのプロダクトツアー」

  * 全部で下記3つのガイドを順番に表示させるツアーを作成する。
  * それぞれのガイドは、特定のボタンやUIをハイライトするものとする。
    * 現段階ではイメージとして、ピンク色の部分で示しています。

  <figure><img src="/files/cmDnjRkrPjt5wmkO03Jk" alt=""><figcaption></figcaption></figure>

また、今回はハイライトされたボタンやバナーなどの要素自体を押下してもらうことで、次のガイドに進めるような設定にします。\
これにより、ユーザーの体験を可能な限り阻害しない形で、「アプリ内のKPIを意図的に上昇させる」ことが可能となります。

***

### Step 2. アプリ側でガイドしたいUIに、アンカーをつける <a href="#step-2-create-and-configure-an-experiement" id="step-2-create-and-configure-an-experiement"></a>

（下記はFlutterでの例になります）

[アンカーに関するドキュメント](/reference/flutter/nubrickanchor)を参考に、アプリ内でガイドを挿入したい部分に、NubrickAnchorのコードを挿入します。

{% hint style="info" %}
ハイライトしたい要素ごとにアンカーのIDを事前に設定しておくことをお勧めします。これにより、その後はコードを編集せずに、`Nubrick` の管理画面で柔軟にプロダクトツアーを変更できます。
{% endhint %}

下記では、対象のUIウィジェットに任意のIDのアンカーをつけています。今回であれば、3つのガイドを作成するので、`FLOAT_BUTTON`、`SEARCH_BUTTON` 、`HABIT_CARD` という名前のアンカーを作成しておきましょう。

```dart
// 例：1つ目（左）の、フローティングボタンに対するガイド
NubrickAnchor(
  "FLOAT_BUTTON",
  child: ElevatedButton(
    child: Text('FLOAT_BUTTON anchor'),
  ),
)
```

```dart
// 例：2つ目（中央）の、検索ボタンに対するガイド
NubrickAnchor(
  "SEARCH_BUTTON",
  child: ElevatedButton(
    // それぞれの子要素
  ),
)
```

```dart
// 例：3つ目（右）の、習慣化バナーカードに対するガイド
NubrickAnchor(
  "HABIT_CARD",
  child: ElevatedButton(
    // それぞれの子要素
  ),
)
```

***

### Step 3. エクスペリメントを作成・設定する <a href="#step-2-create-and-configure-an-experiement" id="step-2-create-and-configure-an-experiement"></a>

ログイン後、ダッシュボードページにアクセスし、以下の手順に従って実験を作成します。

1. **「エクスペリメント」ページに移動**します。
2. **「新規作成」ボタン**をクリックし、**「プロダクトツアー」**&#x3092;選択します。

<figure><img src="/files/0yxW7QRjKWNJIGlz9BCk" alt=""><figcaption></figcaption></figure>

3. エクスペリメント設定ページが表示されるので、以下の設定を行います：

* エクスペリメント名に「新規ユーザー向けのプロダクトツアー」と入力
* トリガーで 「Only once」、「User visits for the first time」 を選択
* 配信割合を「100%」に設定
* 配信スケジュールで、Immediate（今すぐ）を選択
* 配信期間で、配信する日数を入力

<figure><img src="/files/tO6BrRUO8DIkiD9FRQtw" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/IHwYKGWVstBXMV7AicCm" alt=""><figcaption></figcaption></figure>

4. 次に、`「バリアント」`の「ツールチップを新規作成」をクリックし、ツールチップのデザインを行います。

* まず、左のフローティングバーの上部をホバーし、`Tooltip` を選択しエディタに配置します。
* その後、配置したそれぞれのTooltipに対し、コード側で設定したAnchor IDを入力します。
  * 今回であれば、それぞれのTooltipに対して、3つのIDを付与します。
* 配置したTooltipをそれぞれ矢印で繋ぎ、最後のTooltipは`x` ボタンに繋ぎます。
* また、各Tooltipを選択し、右バーの`Tooltip Navigate On Tap`の部分で、Targetに対し`On Anchor Tap (default)` を設定し、対象の要素が押下された際にガイドを進めるようにします。
  * Targetに対し、On Screen Tapを設定すると、画面上のどこかをタップするとガイドが進むようになります。

<figure><img src="/files/XMj9YWLtXg8dwV5Eeydo" alt=""><figcaption></figcaption></figure>

5. 各Tooltipの流れが作れたら、配置したTooltipの中身のデザインや文言を修正していきます。

{% hint style="warning" %}
Nubrickでは、テキストのColorを指定しない際、\
iOS, Androidの外観モードに合わせて文字色を変更する仕様となっております。

エディタ上では黒色のテキストも、アプリユーザーの端末がダークモードの場合は、文字色が白色になりますので、\
アプリ側でダークモードの対応をされていない場合は、お手数ですがエディタ上部のボタンを切り替えながら確認し、明示的にColorの指定をお願いいたします。
{% endhint %}

<figure><img src="/files/FkGqCtLVT23SL2Qp0PvR" alt=""><figcaption></figcaption></figure>

最後に、「Confirm」 ボタンをクリックしてデザインを保存し、エクスペリメントを 「保存」 ボタンをクリックして設定を完了します。

<figure><img src="/files/q99v1bVThG2TJkrMbSiX" alt=""><figcaption></figcaption></figure>

***

### Step 4. エクスペリメントを実行する <a href="#step-3-run-the-experiment" id="step-3-run-the-experiment"></a>

エクスペリメント設定ページに戻ると、作成したエクスペリメントの設定内容とそのアナリティクスが表示されます。

<figure><img src="/files/5BW0GWvZvjhwgqw8RP5A" alt=""><figcaption></figcaption></figure>

**「配信する」ボタン**をクリックすると、エクスペリメントが開始され、対象期間にアプリに反映されます。

***

### Step 5. iOS/Androidアプリで確認する <a href="#step-4-check-it-on-your-iosandroid-app" id="step-4-check-it-on-your-iosandroid-app"></a>

エクスペリメントが反映されたら、実際にiOSまたはAndroidのアプリでプロダクトガイドが表示されるか確認します。

アプリを起動すると、ガイド内で指定した要素がハイライトされ、それぞれのTooltipが、アニメーションのように順番に表示されます🎉

<figure><img src="/files/3eWsIwfcEtm0MXa9ej8S" alt=""><figcaption></figcaption></figure>


# 施策の効果を振り返る


# ABテストを行う


# アプリ内メッセージ(In-App Messaging)

## アプリ内メッセージとは

ネイティブ画面で表示できるモーダルクリエイティブです。

Medium、Large、MediumLarge(最初Medium表示でLargeサイズに拡大可能)の3つの表示パターンから選択可能で、エディタ内で自由にクリエイティブを作成することが可能です。

## ユースケース

#### 1. 実施中のキャンペーンやセールの情報をご案内

* バナーでは埋もれてしまうようなキャンペーンやセールの情報をアプリ内メッセージを使って表示させることでよりユーザーの目に止まるような配信が可能になります

#### 2. 新機能リリース、アプリアップデートのご案内

* アプリのアップデートで搭載された新機能やアップデート情報をアプリ内メッセージを使って表示させることで、便利な機能をしっかりユーザーにお知らせすることが可能です
* 1ユーザーに対して1回のみ、n日に1回などの配信頻度機能で表示頻度のコントロールもおすすめです

#### 3. 特定のユーザーに絞って広告表示

* 対象ユーザーを絞って、その広告に興味のありそうなユーザーにのみ適切な広告を表示することも可能です
  * 会員ランク、居住地、性別、年齢など会員情報などで取得しているデータを連携いただければ対象ユーザーで条件を設定することが可能です


# アプリ内埋め込み (Embeddable Experiment)

## アプリ内埋め込みとは

アプリ側の指定された場所にコードを一行実装するだけで、その場所に自由にコンテンツを表示させることを可能とする機能です。

埋め込み箇所にコードを一度実装してしまえば、あとはNubrickの管理画面から自由に埋め込み箇所に表示するコンテンツを変更することが可能です。

これにより、これまでネイティブ画面のバナー画像を変更するたびに必要だったリリース作業が不要となります

## コード実装

{% content-ref url="/pages/xL9SggiO07fN4SUuvjmL" %}
[実装ガイド](/experiment_menu/embed/embedding_guide)
{% endcontent-ref %}

## ユースケース

#### 1. キャンペーンやセール、特集などのバナー表示

* バナーの表示エリアをNubrickの埋め込み機能を使って用意すると、管理画面からの操作でいつでもバナー内容を変更することが可能になります
* クリエイティブやコンテンツのABテストなども柔軟に行うことが可能です

#### 2. カルーセル表示を使って、商品、キャンペーンの複数表示

* 埋め込み機能ではバナー表示だけでなくカルーセルなど自由なコンテンツ表現が可能です
* 開発では時間がかかってしまいそうなコンテンツ表示を簡単に作成してみましょう

#### 3. アラートメッセージなどのテキスト追加

* 例えばログイン時の注意事項などがあればユーザーが迷いやすいぽいんとにアラートメッセージを出せれば離脱率を減らせるのでは？と思ったことはありませんか？アプリではちょっとしたテキスト追加にも開発とリリースが必要です
* 埋め込み機能ではテキスト表示も可能なので、ちょっとしたテキスト追加なども可能になります


# 実装ガイド

`Nubrick` のエディタで作成された埋め込みエクスペリメントを、アプリ内の特定の場所に埋め込むことができます。

{% hint style="info" %}
コード側では、エクスペリメントIDまたは任意のカスタムID（IDエイリアス）を設定し、使用できます。\
場所ごとにカスタムIDを事前に設定しておくことをお勧めします。これにより、コードを編集せずに、`Nubrick` の管理画面で柔軟にエクスペリメントを変更できます。
{% endhint %}

## 基本的な使い方 <a href="#basic-usage" id="basic-usage"></a>

{% tabs %}
{% tab title="iOS (SwiftUI)" %}

```swift
NubrickSDK.embedding("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
```

{% endtab %}

{% tab title="iOS (UIKit)" %}

```swift
let view = NubrickSDK.embeddingUIView("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
self.addSubview(view)
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}

```kotlin
import app.nubrick.nubrick.NubrickSDK

NubrickSDK.Embedding("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
```

{% endtab %}

{% tab title="Android (Java / XML)" %}

```xml
<app.nubrick.nubrick.view.NubrickEmbeddingView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:nubrickExperimentId="EXPERIMENT_ID_OR_EXPERIMENT_ID_ALIAS" />
```

{% endtab %}

{% tab title="Flutter" %}

```dart
import 'package:nubrick_flutter/embedding.dart';

NubrickEmbedding("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
```

{% endtab %}
{% endtabs %}

## 埋め込みコンポーネントのサイズ

埋め込みコンポーネントのサイズは、次の2種類の指定方法があります

### 1. アプリ側で指定する

アプリ内で明示的にサイズを指定することで、親レイアウトとの整合が取りやすく、エディタ側での高さ未指定によるレイアウト崩れなど、意図しない挙動を防ぐことができます。 高さの異なるコンテンツを配信するユースケースがない場合は、こちらの方法を推奨しております。

{% tabs %}
{% tab title="iOS (SwiftUI)" %}

```swift
NubrickSDK.embedding("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
    .frame(height: 200)
```

{% endtab %}

{% tab title="iOS (UIKit)" %}

```swift
let view = NubrickSDK.embeddingUIView("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>")
view.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
self.addSubview(view)
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}

```kotlin
import app.nubrick.nubrick.NubrickSDK

NubrickSDK.Embedding(
    "<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>",
    modifier = Modifier.height(200f.dp),
)
```

{% endtab %}

{% tab title="Android (Java / XML)" %}

```xml
<app.nubrick.nubrick.view.NubrickEmbeddingView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:nubrickExperimentId="EXPERIMENT_ID_OR_EXPERIMENT_ID_ALIAS" />
```

{% endtab %}

{% tab title="Flutter" %}

```dart
import 'package:nubrick_flutter/embedding.dart';

NubrickEmbedding("<EXPERIMENT_ID or EXPERIMENT_ID_ALIAS>", height: 200)
```

{% endtab %}
{% endtabs %}

### 2. エディタ側で指定する

アプリ側の変更なしで、異なるサイズの施策を配信したり、A/Bテストを実施することが可能です。

エディタ上で該当のframeを選択した状態で、右のパネルからframeのサイズを変更できます。

<figure><img src="/files/9SeEhdWhoGj9S35iNlA6" alt="Frame size setting"><figcaption></figcaption></figure>

### ⚠️ 高さの指定ミスに注意

アプリ側でもエディタ側でもサイズが指定されていない場合、**親ビューの制約に従う（fill）** 挙動になります。

* 親がサイズを持っている場合は、その領域いっぱいに表示されます
* 親が軸方向に無制限な場合（`VStack` / `Column` / スクロール内など）は、高さが潰れる・レイアウトが崩れることがあります

また、アプリ側とエディタ側で異なる数値が指定されている場合も、予期しない表示となるおそれがあるため、ご注意ください。

### 埋め込みコンポーネントのサイズを取得する

`onSizeChange` を使うと、埋め込みコンポーネントの実サイズ（`fill` / `fixed`）を受け取れます。\
このコールバックは、実際の埋め込みページが表示されたときだけ呼ばれます。読み込み中や `not found` の状態では呼ばれません。

`fill` は固定サイズを適用しない（親ビューの制約に従う）ことを表します。

{% tabs %}
{% tab title="iOS (SwiftUI)" %}

```swift
NubrickSDK.embedding(
    "<EXPERIMENT_ID>",
    onSizeChange: { width, height in
        print(width, height)
    }
)
```

{% endtab %}

{% tab title="iOS (UIKit)" %}

```swift
let view = NubrickSDK.embeddingUIView(
    "<EXPERIMENT_ID>",
    onSizeChange: { width, height in
        print(width, height)
    }
)
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}

```kotlin
NubrickSDK.Embedding(
    "<EXPERIMENT_ID> or <EXPERIMENT_CUSTOM_ID>",
    onSizeChange = { width, height ->
        println("width=$width, height=$height")
    }
)
```

{% endtab %}

{% tab title="Android (Java / XML)" %}

```java
NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setOnSizeChangeListener((width, height) -> {
    System.out.println("width=" + width + ", height=" + height);
});
```

{% endtab %}
{% endtabs %}

## イベントハンドラーの追加

埋め込みタイプのエクスペリメントに、イベントハンドラーを追加することができます。

{% tabs %}
{% tab title="iOS (SwiftUI)" %}

```swift
NubrickSDK.embedding("<EXPERIMENT_ID>", onEvent: { event in
    print(event)
})
.frame(height: 200)
```

{% endtab %}

{% tab title="iOS (UIKit)" %}

```swift
let view = NubrickSDK.embeddingUIView("<EXPERIMENT_ID>", onEvent: { event in
    print(event)
})
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}

```kotlin
import app.nubrick.nubrick.NubrickSDK

NubrickSDK.Embedding(
    "<EXPERIMENT_ID> or <EXPERIMENT_CUSTOM_ID>",
    onEvent = { event ->
        println("Event: ${event.name}, deepLink: ${event.deepLink}")
    }
)
```

{% endtab %}

{% tab title="Android (Java / XML)" %}
XML で `NubrickEmbeddingView` に ID を設定し、Java でイベントリスナーを登録します。

```xml
<app.nubrick.nubrick.view.NubrickEmbeddingView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nubrick_embedding"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:nubrickExperimentId="EXPERIMENT_ID_OR_EXPERIMENT_ID_ALIAS" />
```

```java
import app.nubrick.nubrick.view.NubrickEmbeddingView;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setOnEventListener(event -> {
    System.out.println(
        "Event: " + event.getName() + ", deepLink: " + event.getDeepLink()
    );
});
```

{% endtab %}

{% tab title="Flutter" %}

```dart
NubrickEmbedding(
  "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
  height: 200,
  onEvent: (event) {
    print("Nubrick Embedding Event: ${event.payload}");
  },
),
```

{% endtab %}
{% endtabs %}

## ローディング状態のカスタマイズ

読み込み中、失敗、完了の各フェーズでビューをカスタマイズできます。

{% tabs %}
{% tab title="iOS (SwiftUI)" %}
`SwiftUIEmbeddingPhase` を使って各フェーズをハンドリングします。

```swift
NubrickSDK.embedding("<EXPERIMENT_ID>", onEvent: nil) { phase in
    switch phase {
    case .loading:
        Text("loading")
    case .notFound:
        Text("not found")
    case .failed:
        Text("error")
    case .completed(let view):
        view.frame(height: 200)
    }
}
```

{% endtab %}

{% tab title="iOS (UIKit)" %}
`UIKitEmbeddingPhase` を使って各フェーズをハンドリングします。

```swift
let view = NubrickSDK.embeddingUIView("<EXPERIMENT_ID>", onEvent: nil) { phase in
    switch phase {
    case .loading:
        return UIActivityIndicatorView()
    case .notFound:
        return UILabel()
    case .failed:
        return UILabel()
    case .completed(let component):
        return component
    }
}
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}
`content` パラメータを使って `EmbeddingLoadingState` をハンドリングします。

```kotlin
import app.nubrick.nubrick.NubrickSDK
import app.nubrick.nubrick.component.EmbeddingLoadingState

NubrickSDK.Embedding("<EXPERIMENT_ID> or <EXPERIMENT_CUSTOM_ID>") { state ->
    when (state) {
        is EmbeddingLoadingState.Loading -> CircularProgressIndicator()
        is EmbeddingLoadingState.Completed -> state.view()
        is EmbeddingLoadingState.NotFound -> Text("Not found")
        is EmbeddingLoadingState.Failed -> Text("Error")
    }
}
```

{% endtab %}

{% tab title="Android (Java / XML)" %}
`NubrickEmbeddingView` は読み込み状態を内部で処理し、読み込みが完了した埋め込みコンポーネントを表示します。読み込み状態ごとのビューをカスタマイズする場合は、アプリモジュールで Kotlin/Jetpack Compose を有効にし、埋め込み部分だけを `NubrickSDK.Embedding(...)` で実装して、`ComposeView` を介して既存の XML レイアウトに組み込んでください。
{% endtab %}

{% tab title="Flutter" %}
`builder` を使って各フェーズをハンドリングします。

```dart
NubrickEmbedding(
  "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
  builder: (context, phase, child) {
    case ExperimentPhase.loading:
      return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()));
    case ExperimentPhase.completed:
      return const SizedBox(height: 200, child: child);
    case ExperimentPhase.notFound:
      return const SizedBox(height: 200, child: Center(child: Text("Experiment not found.")));
    default:
      return const SizedBox.shrink();
  },
),
```

{% endtab %}
{% endtabs %}

## 引数の渡し方

`arguments` としてパラメータを渡すと、コンポーネント内で展開される動的な変数として利用することができます。

{% tabs %}
{% tab title="iOS (SwiftUI)" %}

```swift
NubrickSDK.embedding(
    "<EXPERIMENT_ID>",
    arguments: ["item_id": itemId]
)
.frame(height: 200)
```

{% endtab %}

{% tab title="iOS (UIKit)" %}

```swift
let view = NubrickSDK.embeddingUIView(
    "<EXPERIMENT_ID>",
    arguments: ["item_id": itemId]
)
```

作成後に `arguments` を更新する場合は、返された `UIView` を `NubrickEmbeddingUpdatable` にキャストして `update(arguments:)` を呼び出します。

```swift
(view as? NubrickEmbeddingUpdatable)?.update(arguments: ["item_id": itemId])
```

{% endtab %}

{% tab title="Android (Kotlin / Compose)" %}

```kotlin
import app.nubrick.nubrick.NubrickSDK

NubrickSDK.Embedding(
    "<EXPERIMENT_ID> or <EXPERIMENT_CUSTOM_ID>",
    arguments = mapOf("item_id" to itemId)
)
```

{% endtab %}

{% tab title="Android (Java / XML)" %}
XML で ID を設定した `NubrickEmbeddingView` に、Java から `arguments` を渡します。

```java
import app.nubrick.nubrick.view.NubrickEmbeddingView;

import java.util.Collections;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setArguments(
    Collections.singletonMap("item_id", itemId)
);
```

{% endtab %}

{% tab title="Flutter" %}

```dart
NubrickEmbedding(
  "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
  height: 200,
  arguments: {
    'item_id': itemId,
  },
),
```

{% endtab %}
{% endtabs %}


# エイリアスID（Alias ID）活用ガイド

Nubrickの「アプリ内埋め込み」機能では、通常のエクスペリメント（配信キャンペーン）ごとに発行される固有の embeddingID とは別に、任意の文字列を指定できる「エイリアスID（Alias ID）」を設定することが可能です。 本ガイドでは、エイリアスIDを活用するメリット、設定時のシステムルールと命名のコツ、および運用上の注意点について解説します。

### 1. エイリアスIDを設定するメリット

通常、アプリ内埋め込みを行うには、エクスペリメント作成後に発行される固有のID（`embeddingID`）をアプリのソースコードに埋め込む必要があります。しかし、エイリアスIDを設定することで、以下の2つの大きなメリットが生まれます。

#### ① 複数のエクスペリメントを横断して、同じIDを使い回せる

* **課題:** 通常の `embeddingID` はエクスペリメントごとに新しく発行されるため、キャンペーンを切り替えるたびにアプリ側のコード修正（IDの書き換え）や再リリースが必要になってしまいます。
* **メリット:** 「特定の埋め込み枠（例：ホーム画面の上部バナー枠）」に対して1つのエイリアスIDをコード側に実装しておけば、管理画面側で紐付けるエクスペリメントを切り替えるだけで、**アプリのアップデートをすることなく、新しいキャンペーンやA/Bテストを何度でも実施・更新**できるようになります。

#### ② エクスペリメントの完成を待たずに、先行して開発（コード実装）を進められる

* **課題:** 通常は「管理画面でエクスペリメントの配信設定を完了させる」→「発行された `embeddingID` を確認する」→「エンジニアに実装を依頼する」という順番になり、手戻りや待ち時間が発生します。
* **メリット:** 事前にビジネスサイドとエンジニアの間で「ここにこのエイリアスIDを使う」と決めておけば、**管理画面での詳細なクリエイティブや配信設定が完了していなくても、エンジニアは先行してアプリの実装を進めることができます。** これにより、施策公開までのリードタイムを大幅に短縮できます。

### 2. システムルールと命名のコツ

エイリアスIDを設定する際は、以下のシステム仕様（必須ルール）を遵守する必要があります。チーム全体（PM・デザイナー・エンジニア）で一目で役割が理解できるよう、推奨ルールに沿って命名してください。

#### ⚠️ エイリアスIDのシステム仕様（必須ルール）

* **使用可能文字:** **半角英数字（a-z, A-Z, 0-9）**、**ハイフン（-）**、**アンダースコア（\_）** のみ
* *※全角文字、日本語、スペース、その他の記号（/ や . など）は使用できません。*
* **文字数制限:** **100文字以内**ですがあまり長いと管理や運用が難しいため、30文字以内を推奨します

#### 💡 推奨ルール：「ページ名（画面名）\_場所名（コンポーネント名）」

アプリ内の「どこに埋め込む枠なのか」が明確にわかるように命名します

**良い例:**

* `home_top_banner` （16文字 / ホーム画面の上部バナー枠）
* `mypage_mid_notice` （17文字 / マイページの中央お知らせ枠）
* `cart_bottom_recommend` （21文字 / カート画面の下部おすすめ枠）

**避けるべき例:**

* `test_id_1` （どこにある、何の枠かがわからない）
* `summer_campaign_2026` （期間限定の施策名をIDにしてしまうと、秋の施策で使い回す際にコードと実態がズレて混乱を招く）
* `home_screen_top_main_marketing_banner_area` （44文字 / 長いためわかりづらい）

### 3. エイリアスIDを使用する場合の注意事項

運用をスムーズに行うため、以下の点にご注意ください。

#### ⚠️ エイリアスIDの管理・共有は各社様で実施をお願いします

* 現在、Nubrickの管理画面上には、設定されているエイリアスIDを一覧で確認・検索する機能がありません。
* そのため、どの画面のどの枠に何のエイリアスIDを紐付けたか、およびアプリ側へどのIDを実装済みかについては、各社様にてスプレッドシート等で管理シートを作成いただき、チーム内やエンジニアとの間で共有・管理を行っていただきますようお願いいたします。

#### ⚠️ IDの重複に注意

* エイリアスIDは、原則としてアプリ内で一意（ユニーク）に設定することを推奨します。別の画面の全く違う枠に同じエイリアスIDを設定してしまうと、意図しないコンテンツが表示される原因となります。上述の管理シート等を用いて、重複が発生しないよう運用ルールを設けることをお勧めします。
* なお、管理画面上では同一のエイリアスIDを複数の施策に設定することは可能です。重複がある場合は、エイリアスIDの設定画面に警告が表示され、同じIDを使用している他のエクスペリメント名へのリンクが確認できます。

#### 重複したエイリアスIDが設定されている場合の挙動

複数の施策に同じエイリアスIDが設定されている場合、アプリ側の挙動は次のようになります。

* **表示される施策:** 取得した候補のうち、**1件のみ**がユーザーに表示されます。選出ルールは「[配信ロジックについて](/experiment_edior/delivery_logic)」の「Conflict Resolution（優先度判定）」と同様で、主に次の順で決まります。
  1. 配信期間・対象ユーザー・イベント実績などの条件を満たすもの
  2. その中で **優先度（Priority）が最も高い** もの
  3. 優先度が同じ場合は、**配信開始日時が最も新しい** もの
* **大文字・小文字:** エイリアスIDは大文字・小文字を区別します（例: `HEADER` と `header` は別のIDとして扱われます）。

重複を許容した運用を行う場合は、意図した施策が適切に配信されるよう、優先度や配信期間・対象ユーザーの設定を慎重に行ってください。


# プロダクトツアー (Product Tour)

## プロダクトツアーとは

特定のエリアにハイライトをあてて、吹き出しを表示させる機能で、新規ユーザー向けのオンボーディングガイドなどに便利です。

## コード実装

* プロダクトツアーを利用する場合は、ハイライトをあてたいエリアにコード実装をする必要があります
* コードの実装方法は各SDKリファレンスを確認してください
  * iOS：[NubrickSDK](/reference/ios/nubricksdk)
  * Android：[NubrickSDK](/reference/android/nubricksdk)
  * Flutter： [NubrickAnchor](/reference/flutter/nubrickanchor)

## ユースケース

#### 1. 新規ユーザー向けのオンボーディング

* 新規ユーザー向けに初回ログイン時にアプリの使い方や必ず設定してほしい機能などの紹介などにおすすめです

#### 2. 新規機能のお知らせ

* 新しくできた機能やコンテンツなどをハイライトしてユーザーにより目立つように訴求ができます
* またハイライトに加えてテキストで機能のメリットやおすすめポイントなどを表示することで活用促進も可能です

#### 3. 埋もれてしまいがちな便利機能の訴求

* 画面上で埋もれてしまいがちな機能にハイライトすることでこれまであまりユーザーの目に入らなかった機能やコンテンツを目立たせ訴求することが可能です


# Remoteconfig（comingsoon）

Remoteconfig（comincomingsoon）


# 配信ロジックについて

Nubrick SDKにおけるエクスペリメントは「埋め込み（Embeddable Experiment）」と「オーバーレイ表示（In-App Messaging / Product Tour）」の2つのコンポーネント別に配信ロジックが異なるためそれぞれに付いて解説します

## 1. アプリ内埋め込み (Embeddable Experiment)

{% hint style="info" icon="lightbulb-exclamation-on" %}
アプリのネイティブレイアウト内に特定のUIを動的に挿入するコンポーネントです
{% endhint %}

#### 表示タイミング

* Viewの初期化時
  * 実装された `NubrickEmbedding` ウィジェット（Flutter等）やViewがレンダリングされるタイミングで評価・表示されます
* 暗黙的なトリガー
  * 特定のイベント発火を待つのではなく、その「場所（ID）」に到達したことが表示のトリガーとなります

#### トリガーの仕組み

* 埋め込みID (Embedding ID): コード内に埋め込まれた固有のIDをキーとして、管理画面上の設定と紐付けます
* トリガー設定の不要性: オーバーレイと異なり、明示的なイベント（アプリ起動等）の設定は不要です。特定の画面表示＝表示タイミングとなります

#### 配信プロセスの詳細

1. Context Resolution
   * SDKが保持している現在の `User Properties`（`setProperties`で注入された値）を読み込みます
2. Targeting Evaluation
   * 管理画面で定義された対象ユーザー条件とプロパティを照合します
   * 注意：埋め込みの場合、条件指定は `set_properties` による属性ベースのみとなります。
3. Conflict Resolution (優先度判定)
   * 同一の埋め込みIDに対して、条件を満たす複数のエクスペリメントが存在する場合、設定された 「優先度（Priority）」が最も高いもの を1つ選出します
4. Resource Fetch & Render
   * 選出されたエクスペリメントの構成JSONを取得し、ネイティブUIとして描写します

## 2. オーバーレイ表示 (In-App Messaging / Product Tour)

{% hint style="info" icon="lightbulb-exclamation-on" %}
特定のユーザーアクションや状態変化に応じて、オーバーレイで表示されるコンポーネントです
{% endhint %}

#### 表示タイミング

* イベントドリブン
  * アプリ起動、バックグラウンド復帰、または `NubrickDispatcher` によって明示的に送信されたカスタムイベント（例：`purchase_completed`）の発生直後に評価されます

#### トリガーの仕組み

* イベントトリガー
  * デフォルトイベント：アプリ起動、初回起動、バックグラウンド復帰
  * カスタムイベント：SDKを通じて任意に定義・発火させたイベント、SDKのAPIを経由して発火させたイベント
* 頻度制御 (Frequency Control)
  * 「毎回」「1回のみ」「1日1回」「n日に1回」といった表示回数制限を、端末内のローカルDB（履歴データ）を用いて判定します

#### 配信プロセスの詳細

1. Event Capture
   * `NubrickDispatcher` がイベントを検知し、当該イベントに紐づく全ての Modal/Tour の構成（Config）をロードします
2. Multilayer Filtering
   * 属性フィルタ: `setProperties` の値がターゲットセグメントに合致するか判定
   * スケジュールフィルタ: 現在のデバイス時刻が、配信期間（開始・終了）およびカスタムスケジュール（曜日・時間帯）内か判定
   * 頻度フィルタ: 過去のインプレッションログに基づき、頻度設定を逸脱していないか判定
3. Priority Evaluation
   * フィルタを通過した候補が複数ある場合、優先度が最も高いもの を選出します（Flutterの場合、ツールチップも同様のロジックで評価されます）
4. Execution
   * 条件に合致したJSONファイルを取得し、最前面のレイヤーに表示を実行します


# トリガー

エクスペリメント編集画面のトリガーについて説明します

{% hint style="danger" %}
設定内容は自動で保存されないため、必ず設定内容を変更、追加した場合には右下の青い保存ボタンを押してください
{% endhint %}

### トリガーとは

トリガー設定ではコンテンツを表示するタイミングを指定します。アプリ内メッセージとプロダクトツアーで利用する項目になります。

※アプリ内埋め込みでは埋め込み場所を指定するためトリガーの指定は不要です

### デフォルトで指定できるトリガー

* 頻度
  * 毎回/1回のみ/1日1回/n日に1回
* イベント
  * アプリの起動、アプリの起動（初回のみ）アプリの起動＋バックグラウンドからの復帰、バックグラウンドからの復帰
  * イベントはSDK実装時にカスタマイズすることでアプリ独自のイベントを連携することも可能です


# 対象ユーザー

エクスペリメント編集画面の対象ユーザーについて説明します

{% hint style="danger" %}
設定内容は自動で保存されないため、必ず設定内容を変更、追加した場合には右下の青い保存ボタンを押してください
{% endhint %}

### 対象ユーザーとは

特定のユーザー属性に対象を絞って、エクスペリメントを配信することができます。

### デフォルトで指定できるProperty

* デフォルトで定義されているPropertyはすべて端末識別子（UUID）に紐付く形で保存・管理されているデータです
  * User ID：端末固有のUUIDで生成しています
    * アプリのアンインストールや端末の変更を行わない限り、同一のIDが保持されます
  * Language Code
  * Country Code
  * Device Time (Unix)
  * First Boot Time (Unix)
  * Last Boot Time (Unix)
  * Retention Period (Unix)
  * Booting Time (Unix)
  * OS Name
  * OS Version
  * App Version
  * CFBundle Version (iOS)
  * Nubrick SDK Version

### 設定について

* when user propaty
  * 連携しているイベントデータを選択してください
* as
  * 連携しているデータ型を指定してください
  * dateを選ぶと日付けを指定できたり、型によって比較条件が表示内容が変わります
* is
  * 比較条件を指定してください（データ型によって表示される比較条件の表示内容が変わります）
    * equal to：等しい（完全一致）
    * not equal to：異なる
    * regex：正規表現で指定
    * after：xxより後
    * befor：xxより前
    * in：含む（部分一致）
    * not in：含まなない
    * between：xxの間
    * \>：xより大きい
    * \>=：x以上
    * <：xより小さい
    * <=：x以上


# 配信タイミングとスケジュール

エクスペリメント編集画面の配信タイミングと配信開始日/終了日について説明します

{% hint style="danger" %}
設定内容は自動で保存されないため、必ず設定内容を変更、追加した場合には右下の青い保存ボタンを押してください
{% endhint %}

### 配信タイミング

* "Everyday"と"Custom"から選択が可能です
  * デフォルトは"Everyday"が選択されています
* Customとした場合は曜日と日時を指定することが可能です
  * 特定の曜日にだけ表示するキャンペーンがある時、夜間等決まった時間の配信を除きたい場合、などにご利用ください
  * 祝日の設定は現状できません

### 配信開始日時

* "スケジュール"と"すぐに配信"から選択できます
  * デフォルトは"すぐに配信"が選択されています
* "スケジュール"を選択するとカレンダーが表示され、エクスペリメントの開始日と時間を自由に設定できます

### 配信終了日時

* "期限付き"と"無制限"から選択できます
  * デフォルトは"期限付き"が選択されていますが、日付を選択しないと無制限と同等の挙動となります
* "期限付き"を選択するとカレンダーが表示され、エクスペリメントの開始日と時間を自由に設定できます


# ゴールメトリクス

エクスペリメント編集画面のゴールメトリクスについて説明します

{% hint style="danger" %}
設定内容は自動で保存されないため、必ず設定内容を変更、追加した場合には右下の青い保存ボタンを押してください
{% endhint %}

### ゴールメトリクスとは

エクスペリメントのゴールとなる指標を設定する項目で、最大3つまで、カスタムイベントも設定可能です。

### デフォルトで設定できるゴール

* リテンション1日、リテンション2〜3日、リテンション4〜7日、リテンション8〜14日、リテンション15日以上

### カスタムイベントをゴールに指定する

* バナーやボタンなどのクリックをカスタムイベントとしてゴールに指定することも可能です
  * その場合、バリアントの編集画面で"Dispatch Event on click"の"Event"の"name"の設定を行ってください
  * "Dispatch Event on click"の"Event"で指定した"name"と同じイベント名をゴールメトリクスの"select or input"と記載のあるエリアに直接打ち込むと設定が可能です
    * この際、イベント名の入力を間違えるとゴールカウントされないためご注意ください
    * 一度施策が配信され、クリックイベントが発火するとゴールメトリクスの選択肢から選択することも可能です
      * テスト配信、クリック後に指定する方法もおすすめです


# iOS API移行ガイド（旧→新）

このページは、旧 iOS API（`NubrickClient` 系）から現行 API（`NubrickSDK` 系）への移行ポイントをまとめたものです。

## 対応表

| 旧API                                         | 新API                                           |
| -------------------------------------------- | ---------------------------------------------- |
| `NubrickClient(projectId: ...)`              | `NubrickSDK.initialize(projectId: ...)`        |
| `nubrick.experiment.dispatch(...)`           | `NubrickSDK.dispatch(...)`                     |
| `nubrick.experiment.embedding(...)`          | `NubrickSDK.embedding(...)`                    |
| `nubrick.experiment.embeddingUIView(...)`    | `NubrickSDK.embeddingUIView(...)`              |
| `nubrick.experiment.remoteConfig(...)`       | `NubrickSDK.remoteConfig(...)`                 |
| `nubrick.experiment.remoteConfigAsView(...)` | `NubrickSDK.remoteConfigAsView(...)`           |
| `nubrick.user.setProperties(...)`            | `NubrickSDK.setUserProperties(...)`            |
| `nubrick.user.id / getProperties()`          | `NubrickSDK.getUserId() / getUserProperties()` |
| `NubrickProvider(client: ...)`               | `NubrickProvider { ... }`                      |
| `AsyncEmbeddingPhase`                        | `SwiftUIEmbeddingPhase`                        |
| `EmbeddingPhase`                             | `UIKitEmbeddingPhase`                          |

## 主要な書き換え例

### 1) 初期化

```swift
// Before
let nubrick = NubrickClient(projectId: "<PROJECT_ID>")

// After
NubrickSDK.initialize(projectId: "<PROJECT_ID>")
```

### 2) SwiftUI での埋め込み

```swift
// Before
nubrick.experiment.embedding("TOP_COMPONENT")

// After
NubrickSDK.embedding("TOP_COMPONENT")
```

### 3) ユーザープロパティ

```swift
// Before
nubrick.user.setProperties(["plan": "gold"])

// After
NubrickSDK.setUserProperties(["plan": "gold"])
```

### 4) Provider

```swift
// Before
NubrickProvider(client: client) {
    ContentView()
}

// After
NubrickProvider {
    ContentView()
}
```

## 注意点

* 旧 `NubrickClient` / `NubrickExperiment` / `NubrickUser` を前提としたコードはそのままでは動きません。
* `ComponentEvent` から `destinationPageId` は削除されています。


# Android API移行ガイド（旧→新）

このページは、旧 Android API（`NubrickClient` 系）から現行 API（`NubrickSDK` 系）への移行ポイントをまとめたものです。

## 対応表

| 旧API                                    | 新API                                           |
| --------------------------------------- | ---------------------------------------------- |
| `NubrickClient(config, context)`        | `NubrickSDK.initialize(context, config)`       |
| `nubrick.experiment.dispatch(...)`      | `NubrickSDK.dispatch(...)`                     |
| `nubrick.experiment.Embedding(...)`     | `NubrickSDK.Embedding(...)`                    |
| `nubrick.experiment.RemoteConfig(...)`  | `NubrickSDK.RemoteConfig(...)`                 |
| `nubrick.experiment.remoteConfig(...)`  | `NubrickSDK.remoteConfig(...)`                 |
| `nubrick.user.setProperties(...)`       | `NubrickSDK.setUserProperties(...)`            |
| `nubrick.user.setProperty(...)`         | `NubrickSDK.setUserProperty(...)`              |
| `nubrick.user.getProperty(...)`         | `NubrickSDK.getUserProperty(...)`              |
| `nubrick.user.userId / getProperties()` | `NubrickSDK.getUserId() / getUserProperties()` |
| `NubrickProvider(client = ...)`         | `NubrickProvider { ... }`                      |
| `nubrick.close()`                       | （不要）                                           |

## 主要な書き換え例

### 1) 初期化

```kotlin
// Before
val nubrick = NubrickClient(
    config = Config(projectId = "<PROJECT_ID>"),
    context = applicationContext,
)

// After
NubrickSDK.initialize(
    context = applicationContext,
    config = Config(projectId = "<PROJECT_ID>"),
)
```

### 2) 埋め込み（Compose）

```kotlin
// Before
nubrick.experiment.Embedding("TOP_COMPONENT")

// After
NubrickSDK.Embedding("TOP_COMPONENT")
```

### 3) ユーザープロパティ

```kotlin
// Before
nubrick.user.setProperties(mapOf("plan" to "gold"))

// After
NubrickSDK.setUserProperties(mapOf("plan" to "gold"))
```

### 4) Provider

```kotlin
// Before
NubrickProvider(client = nubrick) {
    AppContent()
}

// After
NubrickProvider {
    AppContent()
}
```

## 注意点

* 旧 `NubrickClient` / `NubrickExperiment` を前提としたコードはそのままでは動きません。
* `NubrickSDK.initialize(...)` は、他の API を呼ぶ前に 1 回だけ実行してください。
* Compose でオーバーレイ配信を表示する場合は、`NubrickProvider` でルートを包んでください。


# 変数を利用する

component editorのいくつかの箇所では、変数を利用することができます。

変数は `{{ var }}` の記法で利用でき、アプリ上で展開されます。

<figure><img src="/files/EDCXO71sHD4EmUC4gcrK" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/UfrRpg3nb8VWuUSZiZV8" alt="" width="188"><figcaption></figcaption></figure>

### variables

以下の変数が利用できます。

#### user

ユーザー情報を参照できます。`setProperties` を利用してSDKで設定した任意の値を利用することができます。

* `user.id`
* `user.{key}`
  * e.g. `user.name`

ユーザープロパティの設定についてはSDKリファレンスを参照

* iOS: [NubrickSDK](/reference/ios/nubricksdk)
* Android: [NubrickSDK](/reference/android/nubricksdk)
* Flutter: [NubrickUser](/reference/flutter/nubrickuser)

#### props

ページに渡したpropsが参照できます。

* `props.{key}`

<figure><img src="/files/26WVYXUKWtSpb7D5wGSF" alt="" width="267"><figcaption></figcaption></figure>

#### data

ページ読み込み時に取得したdataが参照できます。

* `data.{key}`

<figure><img src="/files/8cJM4W6WUSanSdOxy8EO" alt="" width="274"><figcaption></figcaption></figure>

#### form

component内で入力されたformの値が参照できます。

* `form.{key}`

#### args

SDKで、Embedding ComponentやRemote ConfigのgetAsViewを呼び出す際に渡した引数を参照できます。

* `args.{key}`

#### experiment

* `experiment.id`
* `experiment.variantId`

#### project

* `project.id`

### format

`{{ var | format }}` の形式で、変数の展開時のformat形式を指定することができます。

#### letter case

英字を大文字・小文字に変換することができます

* `{{ var | upper }}`
* `{{ var | lower }}`

#### json

JSON stringifyして表示します。

* `{{ var | json }}`


# iOS

* [NubrickSDK](/reference/ios/nubricksdk)
* [NubrickProvider](/reference/ios/nubrickprovider)
* [RemoteConfigVariant](/reference/ios/remoteconfigvariant)
* [Phases](/reference/ios/phases)
* [Events](/reference/ios/events)


# NubrickSDK

`NubrickSDK` は iOS SDK のエントリポイントです。初期化、イベント送信、埋め込み、Remote Config、ユーザープロパティ更新を静的メソッドで扱います。

{% hint style="warning" %}
`NubrickSDK.initialize(...)` は、アプリ起動時に 1 回だけ実行してください。\
`embedding` / `overlay` / `remoteConfig` / `dispatch` などの API は、初期化完了後に利用してください。\
SwiftUI では、`@main` の `App` struct の `init()` で初期化する構成を推奨します。
{% endhint %}

### 定義

```swift
public enum NubrickSDK {
    @MainActor
    public static func initialize(
        projectId: String,
        onEvent: (@Sendable (_ event: ComponentEvent) -> Void)? = nil,
        httpRequestInterceptor: NubrickHttpRequestInterceptor? = nil,
        onDispatch: ((_ event: NubrickEvent) -> Void)? = nil,
        trackCrashes: Bool = true
    )

    public nonisolated static func dispatch(_ event: NubrickEvent)

    @MainActor public static func overlayViewController() -> UIViewController
    @MainActor public static func overlay() -> some View

    @MainActor
    public static func embedding(
        _ id: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        onSizeChange: ((_ width: NubrickSize, _ height: NubrickSize) -> Void)? = nil
    ) -> some View

    @MainActor
    public static func embedding<V: View>(
        _ id: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        @ViewBuilder content: @escaping (_ phase: SwiftUIEmbeddingPhase) -> V,
        onSizeChange: ((_ width: NubrickSize, _ height: NubrickSize) -> Void)? = nil
    ) -> some View

    @MainActor
    public static func embeddingUIView(
        _ id: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        onSizeChange: ((_ width: NubrickSize, _ height: NubrickSize) -> Void)? = nil
    ) -> UIView

    @MainActor
    public static func embeddingUIView(
        _ id: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        content: @escaping (_ phase: UIKitEmbeddingPhase) -> UIView,
        onSizeChange: ((_ width: NubrickSize, _ height: NubrickSize) -> Void)? = nil
    ) -> UIView

    public static func remoteConfig(
        _ id: String,
        phase: @escaping (@Sendable (_ phase: RemoteConfigPhase) -> Void)
    )

    @MainActor
    public static func remoteConfigAsView<V: View>(
        _ id: String,
        @ViewBuilder phase: @escaping ((_ phase: RemoteConfigPhase) -> V)
    ) -> some View

    @MainActor public static func setUserProperties(_ properties: [String: Any])
    @MainActor public static func setUserProperty(_ key: String, value: Any)
    @MainActor public static func setUserId(_ id: String)
    @MainActor public static func getUserProperty(_ key: String) -> String?
    @MainActor public static func getUserId() -> String?
    @MainActor public static func getUserProperties() -> [String: String]
}

public typealias NubrickArguments = [String: any Sendable]
public typealias NubrickHttpRequestInterceptor = @Sendable (_ request: URLRequest) -> URLRequest

@frozen
public enum NubrickSize: Sendable {
    case fixed(CGFloat)
    case fill
}
```

### 初期化

```swift
import Nubrick

@main
@MainActor
struct YourApp: App {
    init() {
        NubrickSDK.initialize(projectId: "<YOUR_PROJECT_ID>")
    }

    var body: some Scene {
        WindowGroup {
            NubrickProvider {
                ContentView()
            }
        }
    }
}
```

### イベント送信

```swift
NubrickSDK.dispatch(NubrickEvent("PURCHASE_COMPLETED"))
```

### 埋め込み（SwiftUI）

```swift
NubrickSDK.embedding("TOP_COMPONENT")
    .frame(height: 240)
```

フェーズを使う場合:

```swift
NubrickSDK.embedding("TOP_COMPONENT") { phase in
    switch phase {
    case .loading:
        ProgressView()
    case .notFound:
        Text("not found")
    case .failed:
        Text("error")
    case .completed(let view):
        view.frame(height: 240)
    }
}
```

### 埋め込み（UIKit）

```swift
let view = NubrickSDK.embeddingUIView("TOP_COMPONENT")
self.view.addSubview(view)
```

### 埋め込みサイズの取得

`onSizeChange` を使うと、埋め込みコンポーネントの実サイズを取得できます。\
このコールバックは、実際の埋め込みページが読み込まれたときだけ呼ばれます。`loading` / `notFound` / `failed` では呼ばれません。

```swift
NubrickSDK.embedding(
    "TOP_COMPONENT",
    onSizeChange: { width, height in
        print(width, height)
    }
)
```

`NubrickSize` の意味:

* `.fixed(value)` は、エディタで固定サイズが設定されていることを表します。
* `.fill` は、その軸に固定サイズがなく、ホスト側のレイアウトに従うことを表します。

### Remote Config

```swift
NubrickSDK.remoteConfig("FEATURE_FLAGS") { phase in
    switch phase {
    case .completed(let variant):
        print(variant.getAsBool("new_checkout") ?? false)
    default:
        break
    }
}
```

### ユーザープロパティ

{% hint style="warning" %}
この値は、エクスペリメントのデータを識別するためにNubrickサーバーに送信されます。そのため、氏名やメールアドレスなどの個人情報は、user\_id として使用しないでください。\
詳細はこちらのドキュメントもご覧ください。

[ユーザー属性情報（setProperties）について](/other/setproperties)
{% endhint %}

{% hint style="info" %}
このプロパティは、

* どのユーザーがエクスペリメントのターゲットとなるかをフィルタリングする
* エクスペリメント内のユーザー毎の動的な変数として表示する

ために使用されます。
{% endhint %}

```swift
NubrickSDK.setUserProperties([
    "plan": "gold",
    "isPremium": true,
    "age": 32
])

NubrickSDK.setUserId("<CUSTOM_USER_ID>")

let userId = NubrickSDK.getUserId()
let props = NubrickSDK.getUserProperties()
```

### ビルトインのユーザープロパティ

デフォルトで、以下のビルトインプロパティが設定されています：

| Key               | Description                                                              |
| ----------------- | ------------------------------------------------------------------------ |
| `userId`          | User id (uuid by default)                                                |
| `languageCode`    | language code (e.g. en for English, fr for French)                       |
| `regionCode`      | region code (e.g. US for United States, GB for United Kingdom)           |
| `sdkVersion`      | nubrick sdk version                                                      |
| `osName`          | os name (e.g. iOS, iPadOS)                                               |
| `osVersion`       | os version (e.g. 15.3.2)                                                 |
| `appId`           | your app bundle identifier                                               |
| `appVersion`      | your app version (e.g. `CFBundleShortVersionString` for Apple platforms) |
| `cfBundleVersion` | your apple app `CFBundleVersion`                                         |

### 補足

* `setUserProperties` / `setUserProperty` の値は `String`, `Bool`, `Int`, `Double`, `Date` などを渡せます。
* `getUserProperties()` は、アプリが設定したカスタム値と `userId` を取得できます。
* 失敗系の状態は [Phases](/reference/ios/phases) を参照してください。


# NubrickProvider

`NubrickProvider` は SwiftUI でオーバーレイ表示を有効化するためのラッパーです。

{% hint style="warning" %}
`NubrickProvider` を利用する前に `NubrickSDK.initialize(...)` を完了してください。\
推奨: `@main` の `init()` で 1 回だけ初期化する。
{% endhint %}

### 定義

```swift
@MainActor
public struct NubrickProvider<Content: View>: View {
    public init(@ViewBuilder content: () -> Content)
    public var body: some View
}
```

### 使い方

```swift
@main
@MainActor
struct YourApp: App {
    init() {
        NubrickSDK.initialize(projectId: "<YOUR_PROJECT_ID>")
    }

    var body: some Scene {
        WindowGroup {
            NubrickProvider {
                ContentView()
            }
        }
    }
}
```


# RemoteConfigVariant

### 定義

```swift
public final class RemoteConfigVariant {
    public let experimentId: String
    public let variantId: String

    public func get(_ key: String) -> String?
    public func getAsString(_ key: String) -> String?
    public func getAsBool(_ key: String) -> Bool?
    public func getAsInt(_ key: String) -> Int?
    public func getAsFloat(_ key: String) -> Float?
    public func getAsDouble(_ key: String) -> Double?
    public func getAsData(_ key: String) -> Data?

    @MainActor
    public func getAsView(
        _ key: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil
    ) -> some View

    @MainActor
    public func getAsView<V: View>(
        _ key: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        @ViewBuilder content: (@escaping (_ phase: SwiftUIEmbeddingPhase) -> V)
    ) -> some View

    @MainActor
    public func getAsUIView(
        _ key: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil
    ) -> UIView?

    @MainActor
    public func getAsUIView(
        _ key: String,
        arguments: NubrickArguments? = nil,
        onEvent: ((_ event: ComponentEvent) -> Void)? = nil,
        content: @escaping (_ phase: UIKitEmbeddingPhase) -> UIView
    ) -> UIView?
}
```

### 基本取得

```swift
let experimentId = configVariant.experimentId
let variantId = configVariant.variantId

let str = configVariant.getAsString("title")
let enabled = configVariant.getAsBool("is_enabled")
let count = configVariant.getAsInt("max_count")
```

### View として取得（SwiftUI）

```swift
configVariant.getAsView(
    "hero_component",
    arguments: ["item_id": itemId]
)
```

### UIView として取得（UIKit）

```swift
let view = configVariant.getAsUIView(
    "hero_component",
    arguments: ["item_id": itemId]
)
```


# Phases

### SwiftUIEmbeddingPhase

`SwiftUIEmbeddingPhase` は SwiftUI 埋め込み読み込み状態です。

```swift
public enum SwiftUIEmbeddingPhase {
    case loading
    case completed(AnyView)
    case notFound
    case failed(Error)
}
```

### UIKitEmbeddingPhase

`UIKitEmbeddingPhase` は UIKit 埋め込み読み込み状態です。

```swift
public enum UIKitEmbeddingPhase {
    case loading
    case completed(UIView)
    case notFound
    case failed(Error)
}
```

### RemoteConfigPhase

`RemoteConfigPhase` は Remote Config 読み込み状態です。

```swift
public enum RemoteConfigPhase {
    case loading
    case completed(RemoteConfigVariant)
    case notFound
    case failed(NubrickError)
}
```


# Events

### NubrickEvent

{% hint style="info" %}
送信された `NubrickEvent` は、Nubrickサーバーに送信されます。
{% endhint %}

`NubrickEvent` は、`NubrickSDK.dispatch(...)` が呼び出された際にディスパッチされるイベントです。このイベントがディスパッチされると、イベントに一致したポップアップ実験を表示します。

```swift
public struct NubrickEvent: Sendable {
    public let name: String
    public init(_ name: String)
}
```

```swift
NubrickSDK.dispatch(NubrickEvent("<TRIGGER_EVENT_NAME>"))
```

### ComponentEvent

`ComponentEvent` は、エクスペリメントにユーザーがアクションしたときにディスパッチされるイベントです。\
例えば、ユーザーがエクスペリメント内でボタンをタップした際、`ComponentEvent` がディスパッチされ、そのプロパティが定義されます。

```swift
public struct ComponentEvent: Sendable {
    public let name: String?
    public let deepLink: String?
    public let payload: [EventProperty]?
}

public struct EventProperty: Sendable {
    public let name: String
    public let value: String
    public let type: EventPropertyType
}

public enum EventPropertyType: Sendable {
    case INTEGER
    case STRING
    case TIMESTAMPZ
    case UNKNOWN
}
```

`ComponentEvent` は、`NubrickSDK.initialize(...)` または `NubrickSDK.embedding(...)` を呼び出す際に `onEvent` 引数を使ってリッスンできます。


# Android

Android SDK は Kotlin/Jetpack Compose と Java/Android View（XML）から利用できます。

* [NubrickSDK](/reference/android/nubricksdk)
* [NubrickProvider / NubrickOverlayView](/reference/android/nubrickprovider)
* [RemoteConfigVariant](/reference/android/remoteconfigvariant)
* [Phases](/reference/android/phases)
* [Events](/reference/android/events)


# NubrickSDK

`NubrickSDK` は Android SDK のエントリポイントです。Kotlin/Jetpack Compose と Java/XML のどちらからも、初期化、イベント送信、埋め込み、Remote Config、ユーザープロパティ更新を扱えます。

{% hint style="warning" %}
`NubrickSDK.initialize(...)` は、アプリ起動時に 1 回だけ実行してください。\
推奨: `Application` の `onCreate` で初期化してください。\
`Embedding` / `RemoteConfig` / `dispatch` などの API は、初期化完了後に利用してください。\
Compose でオーバーレイ配信を表示する場合は `NubrickProvider { ... }` でルートを包み、XML では `NubrickOverlayView` をアプリのコンテンツより上に配置してください。
{% endhint %}

### 定義

```kotlin
object NubrickSDK {
    fun initialize(
        context: Context,
        config: Config
    )

    fun createConfig(
        projectId: String,
        onEventListener: NubrickGlobalEventListener? = null,
        onDispatchListener: NubrickDispatchListener? = null,
        trackCrashes: Boolean = true
    ): Config

    fun dispatch(event: NubrickEvent)

    fun setUserId(id: String)
    fun getUserId(): String?

    fun setUserProperty(key: String, value: Any)
    fun getUserProperty(key: String): String?

    fun setUserProperties(props: Map<String, Any>)
    fun getUserProperties(): Map<String, String>

    @Composable
    fun Embedding(
        id: String,
        modifier: Modifier = Modifier,
        arguments: Any? = null,
        onEvent: ((event: Event) -> Unit)? = null,
        content: (@Composable (state: EmbeddingLoadingState) -> Unit)? = null,
        onSizeChange: ((width: NubrickSize, height: NubrickSize) -> Unit)? = null
    )

    @Composable
    fun RemoteConfig(
        id: String,
        content: @Composable (RemoteConfigLoadingState) -> Unit
    )

    fun remoteConfig(id: String): Result<app.nubrick.nubrick.remoteconfig.RemoteConfig>

    fun fetchRemoteConfig(
        id: String,
        listener: RemoteConfigListener
    )
}

data class Config(
    val projectId: String,
    val onEvent: ((event: Event) -> Unit)? = null,
    val onDispatch: ((event: NubrickEvent) -> Unit)? = null,
    val trackCrashes: Boolean = true,
)

sealed class NubrickSize {
    data class Fixed(val value: Int) : NubrickSize()
    data object Fill : NubrickSize()
}

fun interface NubrickSizeListener {
    fun onSizeChange(width: NubrickSize, height: NubrickSize)
}
```

### 初期化

#### Kotlin / Compose

```kotlin
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import app.nubrick.nubrick.Config
import app.nubrick.nubrick.NubrickProvider
import app.nubrick.nubrick.NubrickSDK

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        NubrickSDK.initialize(
            context = this,
            config = Config(projectId = "<YOUR_PROJECT_ID>")
        )
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            NubrickProvider {
                AppContent()
            }
        }
    }
}
```

#### Java / XML

`Application` の `onCreate` で `Config` を作成し、SDK を初期化します。

```java
import android.app.Application;

import app.nubrick.nubrick.Config;
import app.nubrick.nubrick.NubrickSDK;

public final class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        Config config = new Config("<YOUR_PROJECT_ID>");
        NubrickSDK.initialize(this, config);
    }
}
```

アプリ全体のイベントを受け取る場合は、`NubrickGlobalEventListener` と `NubrickDispatchListener` を設定できる `createConfig(...)` を利用します。

```java
Config config = NubrickSDK.createConfig(
    "<YOUR_PROJECT_ID>",
    event -> System.out.println("Event: " + event.getName()),
    event -> System.out.println("Dispatched: " + event.getName()),
    true
);
NubrickSDK.initialize(this, config);
```

`trackCrashes` だけを変更する場合は、`NubrickSDK.createConfig("<YOUR_PROJECT_ID>", false)` を利用できます。

### イベント送信

カスタムイベントを発火させる

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
import app.nubrick.nubrick.NubrickEvent
import app.nubrick.nubrick.NubrickSDK

NubrickSDK.dispatch(NubrickEvent("PURCHASE_COMPLETED"))
```

{% endtab %}

{% tab title="Java" %}

```java
import app.nubrick.nubrick.NubrickEvent;
import app.nubrick.nubrick.NubrickSDK;

NubrickSDK.dispatch(new NubrickEvent("PURCHASE_COMPLETED"));
```

{% endtab %}
{% endtabs %}

### 埋め込み（Compose）

```kotlin
NubrickSDK.Embedding("TOP_COMPONENT")
```

フェーズを使う場合：

```kotlin
import app.nubrick.nubrick.component.EmbeddingLoadingState

NubrickSDK.Embedding("TOP_COMPONENT") { state ->
    when (state) {
        is EmbeddingLoadingState.Loading -> CircularProgressIndicator()
        is EmbeddingLoadingState.Completed -> state.view()
        is EmbeddingLoadingState.NotFound -> Text("not found")
        is EmbeddingLoadingState.Failed -> Text("error")
    }
}
```

### 埋め込み（Java / XML）

XML に `NubrickEmbeddingView` を追加し、`nubrickExperimentId` にエクスペリメントIDまたはIDエイリアスを指定します。

```xml
<app.nubrick.nubrick.view.NubrickEmbeddingView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nubrick_embedding"
    android:layout_width="match_parent"
    android:layout_height="240dp"
    app:nubrickExperimentId="TOP_COMPONENT" />
```

エクスペリメントIDは Java から変更することもできます。

```java
import app.nubrick.nubrick.view.NubrickEmbeddingView;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setExperimentId("TOP_COMPONENT");
```

イベントと引数を設定する場合：

```java
import app.nubrick.nubrick.view.NubrickEmbeddingView;

import java.util.Collections;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setArguments(
    Collections.singletonMap("item_id", itemId)
);
embeddingView.setOnEventListener(event -> {
    System.out.println("Event: " + event.getName());
});
```

読み込み状態ごとのビューをカスタマイズする場合は、アプリモジュールで Kotlin/Jetpack Compose を有効にし、埋め込み部分だけを `NubrickSDK.Embedding(...)` で実装して、`ComposeView` を介して既存の XML レイアウトに組み込んでください。

### 埋め込みサイズ

#### Kotlin / Compose

`onSizeChange` を使うと、埋め込みコンポーネントの実サイズを取得できます。\
このコールバックは、実際の埋め込みページが読み込まれたときだけ呼ばれます。`Loading` / `NotFound` / `Failed` では呼ばれません。

```kotlin
NubrickSDK.Embedding(
    id = "TOP_COMPONENT",
    onSizeChange = { width, height ->
        println("width=$width, height=$height")
    }
)
```

`NubrickSize` の意味:

* `NubrickSize.Fixed(value)` は、エディタで固定サイズが設定されていることを表します。
* `NubrickSize.Fill` は、その軸に固定サイズがなく、ホスト側のレイアウトに従うことを表します。

#### Java / XML

`NubrickEmbeddingView` に `wrap_content` を指定した軸には、エディタ側の固定サイズが自動的に反映されます。エディタ側が `fill` の場合は、親ビューの制約に従います。

```xml
<app.nubrick.nubrick.view.NubrickEmbeddingView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:nubrickExperimentId="TOP_COMPONENT" />
```

`setOnSizeChangeListener(...)` を使うと、埋め込みコンポーネントの実サイズを受け取れます。このリスナーは、実際の埋め込みページが読み込まれたときだけ呼び出されます。`NubrickSize.Fixed` の値は `getValue()` で取得できます。

```java
import app.nubrick.nubrick.NubrickSize;
import app.nubrick.nubrick.view.NubrickEmbeddingView;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setOnSizeChangeListener((width, height) -> {
    if (width instanceof NubrickSize.Fixed) {
        int fixedWidth = ((NubrickSize.Fixed) width).getValue();
        System.out.println("width=" + fixedWidth);
    }
});
```

### Remote Config

#### Kotlin / Compose

```kotlin
import app.nubrick.nubrick.remoteconfig.RemoteConfigLoadingState

NubrickSDK.RemoteConfig("FEATURE_FLAGS") { state ->
    when (state) {
        is RemoteConfigLoadingState.Completed -> {
            val enabled = state.variant.getAsBoolean("new_checkout") ?: false
            Text("enabled=$enabled")
        }
        is RemoteConfigLoadingState.Loading -> CircularProgressIndicator()
        is RemoteConfigLoadingState.NotFound -> Text("not found")
        is RemoteConfigLoadingState.Failed -> Text("error")
    }
}
```

#### Java

Java では `fetchRemoteConfig(...)` で非同期に取得し、`RemoteConfigListener` で結果を受け取ります。このコールバックはメインスレッド上で呼び出されます。

```java
import app.nubrick.nubrick.remoteconfig.RemoteConfigVariant;

NubrickSDK.fetchRemoteConfig("FEATURE_FLAGS", result -> {
    if (!result.isSuccess()) {
        System.err.println(result.getError());
        return;
    }

    RemoteConfigVariant variant = result.getValue();
    if (variant == null) {
        return;
    }

    Boolean enabled = variant.getAsBoolean("new_checkout");
    System.out.println("enabled=" + enabled);
});
```

### ユーザープロパティ

{% hint style="warning" %}
この値は、エクスペリメントのデータを識別するためにNubrickサーバーに送信されます。そのため、氏名やメールアドレスなどの個人情報は、user\_id として使用しないでください。\
詳細はこちらのドキュメントもご覧ください。

[ユーザー属性情報（setProperties）について](/other/setproperties)
{% endhint %}

{% hint style="info" %}
このプロパティは、

* どのユーザーがエクスペリメントのターゲットとなるかをフィルタリングする
* エクスペリメント内のユーザー毎の動的な変数として表示する

ために使用されます。
{% endhint %}

#### Kotlin

```kotlin
NubrickSDK.setUserProperties(
    mapOf(
        "plan" to "gold",
        "isPremium" to true,
        "age" to 32
    )
)

NubrickSDK.setUserId("<CUSTOM_USER_ID>")

val userId = NubrickSDK.getUserId()
val props = NubrickSDK.getUserProperties()
```

#### Java

```java
import java.util.HashMap;
import java.util.Map;

Map<String, Object> properties = new HashMap<>();
properties.put("plan", "gold");
properties.put("isPremium", true);
properties.put("age", 32);
NubrickSDK.setUserProperties(properties);

NubrickSDK.setUserProperty("prefecture", "Tokyo");
String prefecture = NubrickSDK.getUserProperty("prefecture");

NubrickSDK.setUserId("<CUSTOM_USER_ID>");

String userId = NubrickSDK.getUserId();
Map<String, String> props = NubrickSDK.getUserProperties();
```

### ビルトインのユーザープロパティ

デフォルトで、以下のビルトインプロパティが設定されています：

| Key            | Description                                           |
| -------------- | ----------------------------------------------------- |
| `userId`       | User id (uuid by default)                             |
| `languageCode` | language code (e.g. ja for Japanese, en for English)  |
| `regionCode`   | region code (e.g. JP for Japan, US for United States) |
| `sdkVersion`   | nubrick sdk version                                   |
| `osName`       | os name (Android)                                     |
| `osVersion`    | Android API level                                     |
| `appId`        | your app package name                                 |
| `appVersion`   | your app version                                      |

### 補足

* `setUserProperties` / `setUserProperty` の値は `String`, `Boolean`, `Int`, `Double` などを渡せます。
* `getUserProperties()` は、アプリが設定したカスタム値と `userId` を取得できます。
* 失敗系の状態は [Phases](/reference/android/phases) を参照してください。


# NubrickProvider / NubrickOverlayView

`NubrickProvider` は Jetpack Compose でオーバーレイ配信を有効化するためのラッパーです。Java/XML では `NubrickOverlayView` を利用します。

{% hint style="warning" %}
`NubrickProvider` または `NubrickOverlayView` を利用する前に `NubrickSDK.initialize(...)` を完了してください。\
`Application` の `onCreate` で初期化してから、Compose ではルート Composable を `NubrickProvider { ... }` で包み、XML ではアプリのコンテンツより上に `NubrickOverlayView` を配置してください。
{% endhint %}

### Jetpack Compose

#### 定義

```kotlin
@Composable
fun NubrickProvider(
    content: @Composable () -> Unit
)
```

#### 使い方

```kotlin
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import app.nubrick.nubrick.Config
import app.nubrick.nubrick.NubrickProvider
import app.nubrick.nubrick.NubrickSDK

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        NubrickSDK.initialize(
            context = this,
            config = Config(projectId = "<YOUR_PROJECT_ID>")
        )
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            NubrickProvider {
                AppContent()
            }
        }
    }
}
```

### Java / XML

`NubrickOverlayView` は、ポップアップなどアプリ全体のオーバーレイ配信を表示します。Activity のレイアウトで通常の画面コンテンツより上に重ね、フルスクリーンで 1 つ配置してください。

```xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/app_content" />

    <app.nubrick.nubrick.view.NubrickOverlayView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
```


# RemoteConfigVariant

### 定義

```kotlin
class RemoteConfigVariant {
    val experimentId: String
    val id: String

    fun get(key: String): String?
    fun getAsString(key: String): String?
    fun getAsBoolean(key: String): Boolean?
    fun getAsInt(key: String): Int?
    fun getAsFloat(key: String): Float?
    fun getAsDouble(key: String): Double?

    @Composable
    fun GetAsEmbedding(
        key: String,
        arguments: Any? = null,
        onEvent: ((event: Event) -> Unit)? = null,
        content: (@Composable (state: EmbeddingLoadingState) -> Unit)? = null
    )
}

class RemoteConfig {
    suspend fun fetch(): Result<RemoteConfigVariant>
}

fun interface RemoteConfigListener {
    fun onResult(result: RemoteConfigResult)
}

class RemoteConfigResult {
    val value: RemoteConfigVariant?
    val error: Throwable?
    val isSuccess: Boolean
}
```

### 基本取得

#### Kotlin / Compose

```kotlin
NubrickSDK.RemoteConfig("FEATURE_FLAGS") { state ->
    when (state) {
        is RemoteConfigLoadingState.Completed -> {
            val variant = state.variant
            val experimentId = variant.experimentId
            val variantId = variant.id

            val title = variant.getAsString("title")
            val enabled = variant.getAsBoolean("is_enabled")
            val maxCount = variant.getAsInt("max_count")
        }
        else -> Unit
    }
}
```

#### Java

`fetchRemoteConfig(...)` は Remote Config を非同期で取得し、取得結果をメインスレッド上で `RemoteConfigListener` に通知します。

```java
import app.nubrick.nubrick.NubrickSDK;
import app.nubrick.nubrick.remoteconfig.RemoteConfigVariant;

NubrickSDK.fetchRemoteConfig("FEATURE_FLAGS", result -> {
    if (!result.isSuccess()) {
        Throwable error = result.getError();
        System.err.println(error);
        return;
    }

    RemoteConfigVariant variant = result.getValue();
    if (variant == null) {
        return;
    }

    String experimentId = variant.getExperimentId();
    String variantId = variant.getId();
    String title = variant.getAsString("title");
    Boolean enabled = variant.getAsBoolean("is_enabled");
    Integer maxCount = variant.getAsInt("max_count");
});
```

取得に成功した場合は `isSuccess()` が `true` になり、`getValue()` から `RemoteConfigVariant` を取得できます。失敗した場合は `getError()` から原因を取得できます。

### Embedding として取得（Compose）

```kotlin
NubrickSDK.RemoteConfig("FEATURE_FLAGS") { state ->
    when (state) {
        is RemoteConfigLoadingState.Completed -> {
            state.variant.GetAsEmbedding(
                key = "hero_component",
                arguments = mapOf("item_id" to itemId)
            )
        }
        else -> Unit
    }
}
```

`GetAsEmbedding(...)` は Jetpack Compose 専用の API です。Java/XML の画面で利用する場合は、アプリモジュールで Kotlin/Jetpack Compose を有効にし、この埋め込み部分だけを Compose で実装して、`ComposeView` を介して既存の XML レイアウトに組み込んでください。

### suspend API で取得（Kotlin）

```kotlin
lifecycleScope.launch {
    val remoteConfig = NubrickSDK.remoteConfig("FEATURE_FLAGS").getOrNull() ?: return@launch
    val variant = remoteConfig.fetch().getOrNull() ?: return@launch
    val message = variant.getAsString("message")
}
```


# Phases

このページで説明する読み込み状態は、Jetpack Compose の `NubrickSDK.Embedding(...)` と `NubrickSDK.RemoteConfig(...)` で利用します。

Java/XML の `NubrickEmbeddingView` は、読み込み状態を内部で処理します。読み込み状態ごとのビューをカスタマイズする場合は、アプリモジュールで Kotlin/Jetpack Compose を有効にし、埋め込み部分だけを Compose で実装して、`ComposeView` を介して既存の XML レイアウトに組み込んでください。

Java で Remote Config を取得する場合は、`RemoteConfigResult.isSuccess()`、`getValue()`、`getError()` を利用してください。

### EmbeddingLoadingState

`EmbeddingLoadingState` は埋め込み読み込み状態です。

```kotlin
sealed class EmbeddingLoadingState {
    class Loading : EmbeddingLoadingState()
    class Completed(var view: @Composable () -> Unit) : EmbeddingLoadingState()
    class NotFound : EmbeddingLoadingState()
    class Failed(e: Throwable) : EmbeddingLoadingState()
}
```

### RemoteConfigLoadingState

`RemoteConfigLoadingState` は Remote Config 読み込み状態です。

```kotlin
sealed class RemoteConfigLoadingState {
    class Loading : RemoteConfigLoadingState()
    class Completed(var variant: RemoteConfigVariant) : RemoteConfigLoadingState()
    class NotFound : RemoteConfigLoadingState()
    class Failed(e: Throwable) : RemoteConfigLoadingState()
}
```


# Events

### NubrickEvent

{% hint style="info" %}
送信された `NubrickEvent` は Nubrick サーバーへ送信されます。
{% endhint %}

`NubrickEvent` は `NubrickSDK.dispatch(...)` で送信するアプリイベントです。

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
NubrickSDK.dispatch(NubrickEvent("<TRIGGER_EVENT_NAME>"))
```

{% endtab %}

{% tab title="Java" %}

```java
NubrickSDK.dispatch(new NubrickEvent("<TRIGGER_EVENT_NAME>"));
```

{% endtab %}
{% endtabs %}

### Event

`Event` は、埋め込みコンポーネント内のアクション発生時に `onEvent` で受け取るイベントです。

```kotlin
data class Event(
    val name: String?,
    val deepLink: String?,
    val payload: List<EventProperty>?
)

data class EventProperty(
    val name: String,
    val value: String,
    val type: EventPropertyType
)

enum class EventPropertyType {
    INTEGER,
    STRING,
    TIMESTAMPZ,
    UNKNOWN
}
```

`onEvent` は `Config(onEvent = ...)`、`NubrickSDK.Embedding(...)`、`RemoteConfigVariant.GetAsEmbedding(...)` などで設定できます。

### Java のイベントリスナー

SDK 内のコンポーネントで発生した `Event` は `NubrickGlobalEventListener`、`NubrickSDK.dispatch(...)` で送信した `NubrickEvent` は `NubrickDispatchListener` で受け取れます。Java では、`Application` の `onCreate` で `NubrickSDK.createConfig(...)` を呼び出し、それぞれのリスナーを設定します。

```java
import app.nubrick.nubrick.Config;
import app.nubrick.nubrick.NubrickSDK;

Config config = NubrickSDK.createConfig(
    "<YOUR_PROJECT_ID>",
    event -> {
        String name = event.getName();
        String deepLink = event.getDeepLink();
        System.out.println("Event: " + name + ", deepLink: " + deepLink);
    },
    event -> System.out.println("Dispatched: " + event.getName()),
    true
);
NubrickSDK.initialize(this, config);
```

特定の `NubrickEmbeddingView` で発生したイベントだけを受け取る場合は、`setOnEventListener(...)` に `NubrickEventListener` を設定します。

```java
import app.nubrick.nubrick.view.NubrickEmbeddingView;

NubrickEmbeddingView embeddingView = findViewById(R.id.nubrick_embedding);
embeddingView.setOnEventListener(event -> {
    System.out.println("Embedding event: " + event.getName());
});
```

`Event` の各プロパティは `getName()`、`getDeepLink()`、`getPayload()` で取得できます。


# Flutter


# API名の変更一覧

Nativebrik SDK は **Nubrick SDK** にリネームされました。以下の表を参考に、コード内のAPI名を更新してください。

## パッケージ

| 変更前                 | 変更後               |
| ------------------- | ----------------- |
| `nativebrik_bridge` | `nubrick_flutter` |

### pubspec.yaml

```yaml
# 変更前
dependencies:
  nativebrik_bridge: ^x.x.x

# 変更後
dependencies:
  nubrick_flutter: ^0.16.0
```

### インストールコマンド

```bash
# 変更前
flutter pub add nativebrik_bridge

# 変更後
flutter pub add nubrick_flutter
```

## import文

| 変更前                                                         | 変更後                                                     |
| ----------------------------------------------------------- | ------------------------------------------------------- |
| `import 'package:nativebrik_bridge/nativebrik_bridge.dart'` | `import 'package:nubrick_flutter/nubrick_flutter.dart'` |
| `import 'package:nativebrik_bridge/provider.dart'`          | `import 'package:nubrick_flutter/provider.dart'`        |
| `import 'package:nativebrik_bridge/embedding.dart'`         | `import 'package:nubrick_flutter/embedding.dart'`       |
| `import 'package:nativebrik_bridge/dispatcher.dart'`        | `import 'package:nubrick_flutter/dispatcher.dart'`      |
| `import 'package:nativebrik_bridge/user.dart'`              | `import 'package:nubrick_flutter/user.dart'`            |
| `import 'package:nativebrik_bridge/anchor/anchor.dart'`     | `import 'package:nubrick_flutter/anchor/anchor.dart'`   |
| `import 'package:nativebrik_bridge/remote_config.dart'`     | `import 'package:nubrick_flutter/remote_config.dart'`   |

## クラス名・API名

| 変更前                             | 変更後                          | 説明                  |
| ------------------------------- | ---------------------------- | ------------------- |
| `NativebrikBridge`              | `Nubrick`                    | SDK初期化クラス           |
| `NativebrikProvider`            | `NubrickProvider`            | オーバーレイ表示用のルートWidget |
| `NativebrikEmbedding`           | `NubrickEmbedding`           | 埋め込みコンポーネントWidget   |
| `NativebrikRemoteConfig`        | `NubrickRemoteConfig`        | リモートコンフィグ取得         |
| `NativebrikRemoteConfigVariant` | `NubrickRemoteConfigVariant` | リモートコンフィグのバリアント     |
| `NativebrikDispatcher`          | `NubrickDispatcher`          | イベントディスパッチャー        |
| `NativebrikEvent`               | `NubrickEvent`               | ディスパッチ用イベント         |
| `NativebrikUser`                | `NubrickUser`                | ユーザー情報管理            |
| `NativebrikAnchor`              | `NubrickAnchor`              | プロダクトツアー用アンカー       |
| `NativebrikCachePolicy`         | 削除                           | キャッシュポリシー（廃止）       |

## コード例

### 変更前

```dart
import 'package:nativebrik_bridge/nativebrik_bridge.dart';
import 'package:nativebrik_bridge/provider.dart';
import 'package:nativebrik_bridge/user.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  NativebrikBridge("<PROJECT_ID>");
  runApp(const MyApp());
}
```

### 変更後

```dart
import 'package:nubrick_flutter/nubrick_flutter.dart';
import 'package:nubrick_flutter/provider.dart';
import 'package:nubrick_flutter/user.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Nubrick.initialize("<PROJECT_ID>");
  runApp(const MyApp());
}
```


# Nubrick

### Nubrick SDK を初期化する <a href="#intialize-nubrick-bridge-sdk-in-your-app" id="intialize-nubrick-bridge-sdk-in-your-app"></a>

Nubrickを利用するためには、アプリの起動時に`Nubrick.initialize`を呼び出す必要があります。

```dart
import 'package:nubrick_flutter/nubrick_flutter.dart';

// ...

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Nubrick.initialize("<YOUR_NUBRICK_PROJECT_ID>");
  runApp(const MyApp());
}
```


# NubrickDispatcher

### インターフェース

```dart
class NubrickDispatcher {
  Future<void> dispatch(NubrickEvent event)
}
```

### .dispatch <a href="#dispatch" id="dispatch"></a>

dispatch関数は、アプリ内のさまざまなイベントを定義するために使用できます。これにより、**イベントデータがNubrickサーバーに送信**され、Nubrickプラットフォームにおいて様々な用途で活用することができます。

この関数を使用することで、特定のエクスペリメントを表示させるトリガーを設定できたり、アプリ内でのユーザーのアクションやイベントをトラッキングし、アプリのパフォーマンスやユーザーの行動分析を行うことが可能になります。

{% hint style="success" %}
具体的なユースケース

* アプリ内でモーダルを表示させるトリガーとして使用。例えば、特定のボタンがクリックされた際や、特定のページを閲覧した際にモーダルを表示するなど。
* アプリ内でのKPIを評価するために使用。特定の機能がユーザーによってどれくらい利用されているかや、特定のUIをどれだけタップしているかを計測するなど。
  {% endhint %}

#### イベントを送信する際のコード例

```dart
import 'package:nubrick_flutter/dispatcher.dart';

await NubrickDispatcher().dispatch(NubrickEvent("<CUSTOM_EVENT_NAME>"))
```

### 詳細な使用例

#### アプリのXX機能を利用しているユーザーをトラッキング

```dart
import 'package:nubrick_flutter/dispatcher.dart';

Button(
  child: const Text('Press me!')
  onPressed: () {
    NubrickDispatcher().dispatch(NubrickEvent('PRESS_XX_FEATURE'))
  }
)
```

#### アプリ内でYYページを表示したときにXXイベントをトリガーまたは収集

```dart
import 'package:nubrick_flutter/dispatcher.dart';

class NubrickNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? result) {
    super.didPop(route, result);
    String name = route.settings.name ?? '';
    if (name.isNotEmpty) {
      NubrickDispatcher().dispatch(NubrickEvent('NAVIGATION_$name'));
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? result) {
    super.didPop(route, result);
    String name = route.settings.name ?? '';
    if (name.isNotEmpty) {
      NubrickDispatcher().dispatch(NubrickEvent('NAVIGATION_$name'));
    }
  }
}

// ...
MaterialApp(
  routes: {
    // ...
  },
  navigatorObservers: [
    NubrickNavigatorObserver(),
  ],
}

```


# NubrickProvider

Nubrickで作成したIn App Messageを表示するためには、NubrickProviderをウィジェットのルートに追加する必要があります。

#### 定義

```dart
class NubrickProvider extends StatelessWidget {}
```

#### サンプルコード <a href="#add-nubrickprovider-to-the-root-of-your-widget-tree" id="add-nubrickprovider-to-the-root-of-your-widget-tree"></a>

```dart
import 'package:nubrick_flutter/nubrick_flutter.dart';
import 'package:nubrick_flutter/provider.dart';

// ...

void main() {
  // Initialize Nubrick Bridge SDK
  WidgetsFlutterBinding.ensureInitialized();
  Nubrick.initialize("<YOUR_NUBRICK_PROJECT_ID>");
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // Add NubrickProvider to your root widget:
    return NubrickProvider(
      child: MaterialApp(
        // ...
      ),
    );
  }
}
```


# NubrickEmbedding

埋め込みコンポーネント（Embedded Component）は、挿入する箇所をウィジェット内で直接指定する必要があります。

### インターフェース

```dart
class NubrickEmbedding extends StatefulWidget {
  final String id;
  final double? width;
  final double? height;
  final dynamic arguments;
  final EventHandler? onEvent;
  final EmbeddingSizeHandler? onSizeChange;
  final EmbeddingBuilder? builder;
}

typedef EmbeddingSizeHandler = void Function(NubrickSize width, NubrickSize height);

sealed class NubrickSize {}
final class NubrickFixedSize extends NubrickSize { final double value; }
final class NubrickFillSize extends NubrickSize {}
```

### サンプルコード

`height` も指定することを推奨しています。

```dart
import 'package:flutter/material.dart';
import 'package:nubrick_flutter/embedding.dart';

Widget build(BuildContext context) {
  return Column(
    children: [
      NubrickEmbedding("<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>", height: 200),
    ],
  );
}
```

#### onEvent

イベントハンドラを渡すことも可能です。

```dart
import 'package:flutter/material.dart';
import 'package:nubrick_flutter/embedding.dart';

Widget build(BuildContext context) {
  return Column(
    children: [
      NubrickEmbedding(
        "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
        height: 200,
        onEvent: (event) {
          print("Nubrick Embedding Event: ${event.payload}");
        }
       ),
    ],
  );
}
```

#### onSizeChange

`onSizeChange` を使うと、埋め込みコンポーネントの実サイズを取得できます。 このコールバックは、実際の埋め込みページが読み込まれたときだけ呼ばれます。`loading` / `notFound` / `failed` では呼ばれません。

```dart
import 'package:flutter/material.dart';
import 'package:nubrick_flutter/embedding.dart';

Widget build(BuildContext context) {
  return Column(
    children: [
      NubrickEmbedding(
        "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
        onSizeChange: (width, height) {
          print("width=$width, height=$height");
        },
      ),
    ],
  );
}
```

`NubrickSize` の意味:

* `NubrickFixedSize(value)` は、エディタで固定サイズが設定されていることを表します。
* `NubrickFillSize()` は、その軸に固定サイズがなく、ホスト側のレイアウトに従うことを表します。

#### arguments

argumentsとしてパラメータを渡すと、Component内で展開される動的な変数として利用することができます。

```dart
import 'package:flutter/material.dart';
import 'package:nubrick_flutter/embedding.dart';

Widget build(BuildContext context) {
  return Column(
    children: [
      NubrickEmbedding(
        "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
        height: 200,
        arguments: {
          'item_id': itemId,
        },
      ),
    ],
  );
}
```

#### builder

loadingや、fallbackのハンドリングもカスタマイズすることができます。

```dart
import 'package:flutter/material.dart';
import 'package:nubrick_flutter/embedding.dart';

Widget build(BuildContext context) {
  return Column(
    children: [
      NubrickEmbedding(
        "<EXPERIMENT_ID> or <EXPERIMENT_ID_ALIAS>",
        builder: (context, phase, child) {
          case ExperimentPhase.loading:
            return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()));
          case ExperimentPhase.completed:
            return const SizedBox(height: 200, child: child);
          case ExperimentPhase.notFound:
            return const SizedBox(height: 200, child: Center(child: Text("Experiment not found.")));
          default:
            return const SizedBox.shrink();
        }
      ),
    ],
  );
}
```


# NubrickRemoteConfig

## Interface

```dart
class NubrickRemoteConfig {
  final String id;
  NubrickRemoteConfig(this.id);
  Future<NubrickRemoteConfigVariant> fetch()
}

class NubrickRemoteConfigVariant {
  Future<String?> get(String key)
  Future<int?> getAsInt(String key)
  Future<double?> getAsDouble(String key)
  Future<bool?> getAsBool(String key)
  Future<void> dispose()
}
```

## Usage

```dart
final config = NubrickRemoteConfig("<ID OR CUSTOM_ID>");
final variant = await config.fetch();
final phase = variant.phase;
final value = await variant.get("KEY");
await variant.dispose();
```


# NubrickUser

### インターフェース

```dart
class NubrickUser {
  Future<String?> getId()
  Future<void> setProperties(Map<String, dynamic> properties)
  Future<Map<String, String>?> getProperties()
}
```

### .getId <a href="#id" id="id"></a>

NubrickUser にはデフォルトでUUID形式のユーザーIDがプロパティとして設定されています。ユーザーIDは以下のように取得できます：

```dart
final user = NubrickUser();
final userId = await user.getId();
```

オプションで、カスタムユーザーIDを設定することも可能です：

```dart
await user.setProperties({'userId': '<CUSTOM_USER_ID>'});
```

{% hint style="warning" %}
この値は、エクスペリメントのデータを収集するためにNubrickサーバーに送信されます。そのため、ユーザーIDとしてプライバシーに関わるデータを設定することは推奨されません。
{% endhint %}

### .setProperties <a href="#set" id="set"></a>

{% hint style="info" %}
このプロパティは、

* どのユーザーがエクスペリメントのターゲットとなるかをフィルタリングする
* エクスペリメント内のユーザー毎の動的な変数として表示する

ために使用されます。
{% endhint %}

{% hint style="warning" %}
SDK v0.3.2未満では、カスタムのユーザープロパティはIn-memoryに保存される仕様となっています。アプリ起動時に、都度ユーザーのプロパティをsetしていただく実装が必要です。

SDK v0.3.2では、アプリ内のストレージに保存するよう修正しましたので、一度設定したユーザープロパティは、アプリの再起動後も永続化されます。
{% endhint %}

カスタムのユーザーのプロパティを設定することができます：

```dart
await user.setProperties({'<KEY>': '<VALUE>'});
```

また、 `<VALUE>` は `String`, `bool`, `int`, `double`, `DateTime` をサポートしています。 (SDK >= v0.9.0)

### .getProperties <a href="#comeback" id="comeback"></a>

ユーザーのプロパティを取得することができます：

```dart
final properties = await user.getProperties();
```


# NubrickAnchor

### インターフェース

Tooltipを紐づけるUI部品。表示対象となるWidgetを囲んで使用します。

```dart
class NubrickAnchor extends StatefulWidget {
  final String id;
  final Widget child;

  const NubrickAnchor(
    this.id, {
    super.key,
    required this.child,
  });
}
```

NubrickAnchorで囲んだWidgetに対して、ユーザーオンボーディングや機能ガイドをNubrickの管理画面から作成して、表示することができます。

### サンプルコード

対象のWidgetを `NubrickAnchor` でラップし、ID（例: `"MY_TOOLTIP_ID"`）を指定してください。

```dart
NubrickAnchor(
  "MY_TOOLTIP_ID",
  child: ElevatedButton(
    onPressed: () {
      print("MY_TOOLTIP anchor button pressed");
    },
    child: Text('MY_TOOLTIP anchor'),
  ),
)
```

ナビゲーションバーアイコンなどでも使用可能です：

```dart
BottomNavigationBarItem(
  icon: NubrickAnchor(
    "NAV_ITEM_A",
    child: Icon(Icons.business),
  ),
  label: 'Page A',
)
```


# トラブルシューティング


# Cocoapods error

* Error

```
[!] CocoaPods could not find compatible versions for pod "Nubrick":
  In Podfile:
    nubrick_flutter (from `.symlinks/plugins/nubrick_flutter/ios`) was resolved to 0.0.1, which depends on
      Nubrick (~> 0.10.1)

None of your spec sources contain a spec satisfying the dependency: `Nubrick (~> 0.10.1)`.

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.
```

* Solution

1. Update cocoapods spec repository cloned in your local disk.

```
$ pod repo update
```

2. Remove `Podfile.lock` if necessary

```
$ rm ./Podfile.lock
```

3. Install pod

```
$ pod install
```


# XCode Build error

* Error

```
Sandbox: rsync.samba(95629) deny(1) file-write-create ~/Library/Developer/Xcode/DerivedData/app-gtdoczjzruwrtcccpouxsqoffcng/Build/Products/Debug-iphonesimulator/calculator.app/Frameworks/Nubrick.framework/_CodeSignature/.CodeResources.EYIviv
```

* Solution

Set `User Script Sandboxing` to `No` under `Project Settings -> Build Settings -> Build Options`

```
Project Settings -> Build Settings -> Build Options -> User Script Sandboxing -> No
```


# イベント設計ガイド

## イベントの用途、メリット

Nubrickにおける「イベント」や「ユーザープロパティ」は、アプリ内施策（エクスペリメント）を適切なユーザー・タイミングで配信し、その効果を正確に測定するために不可欠なデータです。

適切に設計・実装することで、以下の3つのメリット・用途を実現できます。

1. **エクスペリメント配信時の対象ユーザー指定（ターゲティング）**
   * ユーザー属性や行動状態に応じて配信対象を絞り込む（例: 有料会員のみ、特定バージョンのユーザーのみなど）ことができます。
2. **モーダル施策（In-App Messaging）のトリガー指定**
   * ユーザーが特定の画面を開いた瞬間や、特定のアクションを起こしたタイミングでモーダルをリアルタイム表示できます。
3. **効果測定時の「ゴール（コンバージョン）」計測**
   * 施策（A/Bテスト等）を表示した結果、ユーザーが目的のアクション（購入完了、会員登録など）に至ったかをKPIとして評価・計測できます。

## デフォルトで指定できるイベントとユーザープロパティ

以下を参照してください

{% content-ref url="/pages/sfDI88CIvPPIXSDfoWbk" %}
[トリガー](/experiment_edior/trigger)
{% endcontent-ref %}

{% content-ref url="/pages/mGBQ8EVGYmbHtvSLGX0l" %}
[対象ユーザー](/experiment_edior/user)
{% endcontent-ref %}

## カスタムイベント・ユーザープロパティの3つの推奨設定

Nubrickの成果を最大化するために、以下**3つの区分での設定を推奨**しています。

#### 1. Viewイベント系（ページの閲覧をイベント化）

* **概要**
  * アプリ内の特定の画面（ページ）が表示されたタイミングで発火させるイベントです。
* **主な用途**
  * **モーダル施策のトリガー**: 特定の画面（例: カート画面、マイページなど）を開いた瞬間にクーポンや案内を表示する。
  * **ゴールの設定**: 施策を通して特定のページ（例: 注文完了画面、キャンペーン詳細画面）に到達したかを計測する。
* **実装・設計イメージ**
  * `VIEW_HOME`（ホーム画面表示）
  * `VIEW_CART`（カート画面表示）
  * `VIEW_THANK_YOU`（購入完了画面表示）

#### 2. その他イベント（ページ遷移を伴わないアクション）

* **概要**
  * ボタンタップ、機能の実行、状態の変化など、画面遷移を伴わないユーザー行動を追跡するイベントです。
* **主な用途**
  * **モーダル施策のトリガー**: 特定の操作（例: お気に入り登録、検索実行）をトリガーにして関連モーダルを即座に表示する。
  * **ゴールの設定**: 特定の機能利用やタップアクション（例: クーポン適用ボタンタップ、動画再生完了）を成果ゴールとして評価する。
* **実装・設計イメージ**
  * `TAP_FAVORITE_BUTTON`（お気に入りボタンのタップ）
  * `EXECUTE_SEARCH`（検索の実行）
  * `COMPLETE_PURCHASE`（購入アクションの完了）

#### 3. setProperties（ユーザー情報の設定）

* **概要**
  * イベント（点のアクション）ではなく、ユーザー個々の属性・状態（線の属性）をNubrickSDKに渡す設定です。
* **主な用途**
  * **配信ユーザーのセグメント（フィルタリング）：**「会員ランク」「課金有無」「登録日」などの条件を設定し、エクスペリメントの対象ユーザーを精密に絞り込むことができます。
  * **動的な変数表示：**&#x30E2;ーダルや埋め込み画面内で、ユーザー名や保有ポイント数などを動的にテキスト表示する際にも利用可能です。
* **実装・設計イメージ**
  * `setProperties({"user_type": "premium", "points": 1500})`
* 詳細リファレンス

{% content-ref url="/pages/g8D2PUVjC0sX5zBV9zoJ" %}
[ユーザー属性情報（setProperties）について](/other/setproperties)
{% endcontent-ref %}

## SDKでの実装について

以下各種リファレンスをご確認ください。

#### iOS

{% content-ref url="/pages/KoDSlChpdeCMjC1eTTgB" %}
[Events](/reference/ios/events)
{% endcontent-ref %}

{% content-ref url="/pages/MWjwHxmZyDjHWCoEPTrg" %}
[NubrickSDK](/reference/ios/nubricksdk)
{% endcontent-ref %}

#### Android

{% content-ref url="/pages/m8tZWgMTNTAJtpE62g8J" %}
[Events](/reference/android/events)
{% endcontent-ref %}

{% content-ref url="/pages/wEGc5WSWF6XTtdWSFi5e" %}
[NubrickSDK](/reference/android/nubricksdk)
{% endcontent-ref %}

#### Flutter

{% content-ref url="/pages/fN54DvJPOPI5cXeXTLlZ" %}
[NubrickDispatcher](/reference/flutter/nubrickdispatcher)
{% endcontent-ref %}

{% content-ref url="/pages/Y2mwHuEX6UfVu1bueF2n" %}
[NubrickUser](/reference/flutter/nubrickuser)
{% endcontent-ref %}

#### setProperties

{% content-ref url="/pages/g8D2PUVjC0sX5zBV9zoJ" %}
[ユーザー属性情報（setProperties）について](/other/setproperties)
{% endcontent-ref %}


# ユーザー属性情報（setProperties）について

### ユーザー属性設定（setProperties）の概要

Nubrickにおける`setProperties`とは、アプリを利用している**ユーザーの属性情報（プロパティ）をNubrick側に連携する機能**です 。

通常、アプリ側で保持している”会員ランク”、”性別”、”年齢”、”契約プラン”などの会員情報をNubrickに連携することで、管理画面から特定のセグメント条件に合致するユーザーにだけ施策を配信することが可能になります 。

### 個人情報に関する連携について

* 現在のNubrickの仕様では、`setProperties` で設定された値のうち`userId`のみをユーザーの識別のためにサーバーに送信しています
  * そのため、`userId` には**氏名やメールアドレスなどの個人情報は使用しないでください**。
    * 連番など推測されやすい値を使用する場合は、ハッシュ化などによって推測困難な値に変換してから利用してください。IDは第三者から推測困難な値であることを推奨します。
    * ユーザーIDを意味する値をユーザータグで送信する場合は、必ず`userId`という名称で、システム上でユニークなID（1人のユーザーに対して与えられ、システム上で重複しない）を文字列形式で送信してください。
  * `userId` 以外の値はサーバーに連携されていませんが、単体で個人を特定できるような個人情報は設定しないことを推奨しています

### setPropertiesの仕様

プロパティとして設定できるデータの形式や、あらかじめ用意されている自動取得項目について説明します。

#### 1. サポートされているデータ型

以下の5種類のデータ型をプロパティの値として設定できます 。

* **String**（文字列）: 例 "Gold", "Tokyo"
* **Bool**（真偽値）: 例 true, false
* **Int**（整数）: 例 25, 100
* **Double**（浮動小数点数）: 例 4.5
* **Date**（日付）

※ `Date` は iOS でサポートされます。

#### 2. ビルトイン・プロパティ（自動取得項目）

SDKを導入すると、以下の項目はデフォルトで自動的に設定~~収集~~されています。これらを別途手動で設定する必要はありません 。

| **キー名**                | **内容**                                              |
| ---------------------- | --------------------------------------------------- |
| `userId`               | ユーザーID（デフォルトはUUID形式）                                |
| `languageCode`         | 言語設定（例: ja, en）                                     |
| `regionCode`           | 地域設定（例: JP, US）                                     |
| `sdkVersion`           | Nubrick SDK のバージョン                                  |
| `osName` / `osVersion` | OS名およびOSバージョン                                       |
| `appId`                | アプリID（iOS: Bundle Identifier、Android: Package Name） |
| `appVersion`           | アプリのバージョン                                           |
| `cfBundleVersion`      | iOS の `CFBundleVersion`                             |

### 実装例

{% tabs %}
{% tab title="iOS" %}

```swift
NubrickSDK.setUserProperties([
    "plan": "gold",
    "prefecture": "Tokyo"
])

NubrickSDK.setUserId("<CUSTOM_USER_ID>")

let userId = NubrickSDK.getUserId()
let properties = NubrickSDK.getUserProperties()
print(userId ?? "")
print(properties)
```

{% endtab %}

{% tab title="Android (Kotlin)" %}

```kotlin
NubrickSDK.setUserProperties(
    mapOf(
        "plan" to "gold",
        "prefecture" to "Tokyo"
    )
)

NubrickSDK.setUserId("<CUSTOM_USER_ID>")

val userId = NubrickSDK.getUserId()
val properties = NubrickSDK.getUserProperties()
println(userId)
println(properties)
```

{% endtab %}

{% tab title="Android (Java)" %}

```java
import java.util.HashMap;
import java.util.Map;

Map<String, Object> properties = new HashMap<>();
properties.put("plan", "gold");
properties.put("prefecture", "Tokyo");
NubrickSDK.setUserProperties(properties);

NubrickSDK.setUserId("<CUSTOM_USER_ID>");

String userId = NubrickSDK.getUserId();
Map<String, String> currentProperties = NubrickSDK.getUserProperties();
System.out.println(userId);
System.out.println(currentProperties);
```

{% endtab %}

{% tab title="Flutter" %}

```dart
final user = NubrickUser();
await user.setProperties({
  'plan': 'gold',
  'prefecture': 'Tokyo',
  'userId': '<CUSTOM_USER_ID>',
});

final userId = await user.getId();
final properties = await user.getProperties();
print(userId);
print(properties);
```

{% endtab %}
{% endtabs %}

### 実装時の注意事項

エンジニアによる実装および運用にあたって、以下の点に注意してください。

* **プライバシーへの配慮**
  * 設定された`userId`は上記記載の通りユーザー識別のためにサーバーへ送信されます。そのため、ユーザーIDとして**個人を特定できる直接的な情報や、プライバシーに関わる機密データ**を設定することは推奨されません 。
* **データ連携のタイミング**
  * `setProperties`で設定された値は、即座にそのユーザーの属性として更新されます。ユーザーの状態が変化したタイミング（例：ログイン後、プロフィール更新後）で呼び出すように実装してください 。
* **デバッグ機能の活用**
  * 実装したプロパティが正しく反映されているかは、`NubrickSDK.getUserProperties()`メソッドを呼び出すことで確認できます 。

### 主なユースケース

`setProperties`を活用することで、以下のような高度なマーケティング施策が実現できます。

#### 1. ユーザーセグメントによる配信ターゲットの絞り込み

特定の属性を持つユーザーをフィルタリングして、キャンペーンやA/Bテストを表示できます 。

* **例**: 「ゴールド会員」のユーザーだけに、先行セール案内をアプリ内メッセージで表示する。
* **例**: 「最終購入日から30日以上経過している」ユーザーだけに、再訪問クーポンを配布する。

#### 2. コンテンツ内での動的な変数表示

連携したプロパティを、配信するUI（バナーやメッセージ）内の変数として利用できます 。

* **例**: メッセージ内に「現在契約中のプランは○○です」といった、ユーザーごとの情報を動的に差し込む。

#### 3. パーソナライズされたレコメンドの提供

ユーザーの行動特性や属性に基づいた体験を提供し、エンゲージメントを高めます 。

* **例**: 「興味カテゴリー：キャンプ」と設定されているユーザーのホーム画面に、アウトドア関連の特集バナーを優先的に表示する。


# アカウントの招待方法

自分のプロジェクトにユーザーを招待する方法を紹介します

## Step1：招待したいユーザーにSignupしてもらう

プロジェクトに招待したいユーザーがまだNubrickのアカウントを持っていない場合は、先にSignupからアカウントの作成をお願いします。

<https://dashboard.nubrick.app/signup>

## Step2：プロジェクト設定からアカウントを追加する

* 上部メニューバーにある"設定"をクリック
* 右側メニューからMembersを選択し、画面左上にある"メンバーを追加"をクリック
  * 表示されたモーダル上でSignupした際と同じメールアドレスを追加、もしくは招待URLをコピーし招待したいユーザーに送付してください

## Step3：メンバー追加

* プロジェクトでメールアドレスを追加した場合は、招待されたユーザーはログイン後の画面にログイン可能なプロジェクト一覧が表示されます
* 招待URLを送られた場合は、招待URLをクリックするとログイン後にプロジェクト一覧が表示されます


