Skip to content


Braze iOS SDK 統合ガイド

このオプションの iOS 統合ガイドでは、最初に iOS SDK とそのコアコンポーネントをアプリケーションに統合するときに、セットアップのベストプラクティスについて段階的に説明します。このガイドは、BrazeManager.swift ヘルパーファイルを作成する際に役立ちます。このヘルパーファイルは、Braze iOS SDK への依存関係をプロダクションコードの残りの部分から切り離し、アプリケーション全体で 1 つの import AppboyUI を生成します。このアプローチでは、過剰な SDK インポートから発生する問題が制限されるため、コードの追跡、デバッグ、および変更が容易になります。

統合の概要

以下の手順は、プロダクション・コードが呼び出す BrazeManager ヘルパー・ファイルの作成に役立ちます。このヘルパーファイルは、リストされている以下の統合トピックのさまざまな拡張機能を追加することで、Braze 関連のすべての依存関係を処理します。各トピックには、Swift と Objective-C の両方の水平タブステップとコードスニペットが含まれます。アプリケーションでこれらのチャネルを使用する予定がない場合、統合にはコンテンツカードとアプリ内メッセージの手順は必要ありません。

BrazeManager.swift の作成

BrazeManager.swift の作成

BrazeManager.swift ファイルを作成するには、BrazeManager という名前の新しい Swift ファイルを作成し、目的の場所のプロジェクトに追加します。次に、import Foundation を SPM の import AppboyUI に置き換えてから (CocoaPods の場合は import Appboy_iOS_SDK)、BrazeManager クラスを作成します。これは、すべての Braze 関連のメソッドと変数をホストするために使用されます。Appboy_iOS_SDK

  1. BrazeManagerクラスを初期化する shared という名前の静的変数を追加します。これは、一度だけ遅延開始されることが保証されています。
  2. 次に、apiKey という名前のプライベート定数変数を追加し、Braze ダッシュボードのワークスペースから API キー値として設定します。
  3. appboyOptions という名前のプライベート計算変数を追加します。これにより SDK の構成値が格納されます。今のところ空です。

```swift class BrazeManager:NSObject { // 1 static let shared = BrazeManager()

// 2 private let apikey = “YOUR-API-KEY”

// 3 private var appboyOptions: [String:Any] { return [:] } } ```

```objc @implementation BrazeManager

// 1

  • (instancetype)shared { static BrazeManager *shared = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shared = [[BrazeManager alloc] init]; // Do any other initialisation stuff here }); return shared; }

// 2 - (NSString *)apiKey { return @”YOUR-API-KEY”; }

// 3 - (NSDictionary *)appboyOptions { return [NSDictionary dictionary]; } ```

SDK の初期化

BrazeManager.swift から SDK を初期化します

次に、SDK を初期化する必要があります。このガイドでは、すでに SDK を Xcode プロジェクトに追加していることを前提としています。また、ワークスペース SDK エンドポイント および LogLevelInfo.plist ファイルまたは appboyOptions に設定する必要があります。

didFinishLaunchingWithOptions メソッドを AppDelegate.swift ファイルから BrazeManager.swift ファイルに戻りタイプなしで追加します。BrazeManager.swift ファイルに同様のメソッドを作成すると、import AppboyUI ステートメントは AppDelegate.swift ファイルにはありません。

次に、新しく宣言した apiKey および appboyOptions 変数を使用して SDK を初期化します。

1
2
3
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
  Appboy.start(withApiKey: apikey, in: application, withLaunchOptions: launchOptions, withAppboyOptions: appboyOptions)
}
1
2
3
- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [Appboy startWithApiKey:[self apiKey] inApplication:application withLaunchOptions:launchOptions withAppboyOptions:[self appboyOptions]];
}
AppDelegate.swift での Appboy の初期化の処理

次に、AppDelegate.swift ファイルに戻り、AppDelegate の didFinishLaunchingWithOptions メソッドに以下のコードスニペットを追加して、BrazeManager.swift ヘルパーファイルから Appboy の初期化を処理します。AppDelegate.swiftimport AppboyUI ステートメントを追加する必要はありません。

```swift func application( _ application:UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey:Any]? ) -> Bool { // アプリケーション起動後のカスタマイズ用のオーバーライドポイント

BrazeManager.shared.application(application, didFinishLaunchingWithOptions: launchOptions)

return true } ```

```objc - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // アプリケーション起動後のカスタマイズ用のオーバーライドポイント

[[BrazeManager shared] application:application didFinishLaunchingWithOptions:launchOptions];

return YES; } ```

プッシュ通知

プッシュ証明書の追加

Braze ダッシュボードで既存のワークスペースに移動します。プッシュ通知設定 ngs で、プッシュ証明書ファイルを Braze ダッシュボードにアップロードして保存します。

![](/docs/ja/assets/img/ios_sdk/ios_sdk2.png?5aa81433727ecfa43c76bc0762a8c1de){: style=”max-width:60%;”}

プッシュ通知の登録

次に、プッシュ通知を登録します。このガイドでは、Apple 開発者ポータルおよび Xcode プロジェクトでプッシュ認証情報を正しく設定していることを前提としています。

プッシュ通知を登録するコードは、BrazeManager.swift ファイルの didFinishLaunching... メソッドに追加されます。初期化コードは最終的に次のようになります。

  1. ユーザと対話する権限を要求するためのコンテンツを設定します。これらのオプションは例としてリストされています。
  2. ユーザにプッシュ通知を送信する権限を要求します。プッシュ通知を許可または拒否するユーザの応答は、granted 変数で追跡されます。
  3. ユーザが通知プロンプトを操作した後、プッシュ承認の結果を Braze に転送します。
  4. APN で登録プロセスを開始します。これはメインスレッドで行う必要があります。登録が成功すると、アプリは AppDelegate オブジェクトの didRegisterForRemoteNotificationsWithDeviceToken メソッドを呼び出します。

```swift func application(_ application:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey:Any]?) { Appboy.start(withAPIKey: apikey, in: application, withLaunchOptions: launchOptions, withAppboyOptions: appboyOptions) // 1 let options: UNAuthorizationOptions = [.alert, .sound, .badge] // 2 UNUserNotificationCenter.current().requestAuthorization(option: options) { (granted, error) in // 3 Appboy.sharedInstance()?.pushAuthorization(fromUserNotificationCenter: granted) }

// 4 UIApplications.shared.registerForRemoteNotificiations() } ```

```objc - (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [Appboy startWithApiKey:[self apiKey] inApplication:application withLaunchOptions:launchOptions withAppboyOptions:[self appboyOptions]];

// 1 UNAuthorizationOptions options = (UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);

// 2 [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) { // 3 [[Appboy sharedInstance] pushAuthorizationFromUserNotificationCenter:granted]; }];

// 4 [[UIApplication sharedApplication] registerForRemoteNotifications]; } ```

プッシュ通知メソッドの転送

次に、システムのプッシュ通知メソッドを AppDelegate.swift から BrazeManager.swift に転送し、Braze iOS SDK で処理されるようにします。

ステップ1:プッシュ通知コードの拡張子を作成する

BrazeManager.swift ファイルにプッシュ通知コードの拡張子を作成し、ヘルパーファイルで提供されている目的について、より組織的な方法で読み取るようにします。以下に例を示します。

  1. import AppboyUI ステートメントを AppDelegate に含めないパターンに従って、BrazeManager.swift ファイルのプッシュ通知メソッドを処理します。ユーザのデバイストークンは、didRegisterForRemote... メソッドから Braze に渡される必要があります。このメソッドは、サイレントプッシュ通知を実装するために必要です。次に、BrazeManager クラスの AppDelegate から同じメソッドを追加します。
  2. 以下の行をメソッド内に追加して、デバイストークンを Braze に登録します。これは、Braze がトークンを現在のデバイスに関連付けるために必要です。
1
2
3
4
5
6
7
8
9
10
11
// MARK - Push Notifications
extension BrazeManager {
  // 1 
  func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    // 2 
    Appboy.sharedInstance().?registerDeviceToken(deviceToken)
  }
}
1
2
3
4
5
6
// MARK - Push Notifications
// 1
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  // 2
  [[Appboy sharedInstance] registerDeviceToken:deviceToken];
}
ステップ2:リモート通知のサポート

[署名および機能] タブで、[バックグラウンドモード] サポートを追加し、[リモート通知] を選択して、Braze から発信されるリモートプッシュ通知のサポートを開始します。

Signing & Capabilities

ステップ3:リモート通知処理

Braze SDK は、Braze から発信されるリモートプッシュ通知を処理できます。Braze にリモート通知を転送します。SDK は Braze から発信されたものではないプッシュ通知を自動的に無視します。プッシュ通知拡張子で、BrazeManager.swift ファイルに次のメソッドを追加します。

1
2
3
4
5
6
7
8
9
10
11
func application(
  _ application: UIApplication, 
  didReceiveRemoteNotification userInfo: [AnyHashable : Any], 
  fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
  Appboy.sharedInstance()?.register(
    application, 
    didReceiveRemoteNotification: userInfo, 
    fetchCompletionHandler: completionHandler
  )
}
1
2
3
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [[Appboy sharedInstance] registerApplication:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
ステップ4:通知応答の転送

Braze SDK は、Braze から発信されるプッシュ通知の応答を処理できます。通知の応答を Braze に転送します。SDK は、Braze から発信されていないプッシュ通知からの応答を自動的に無視します。以下のメソッドを BrazeManager.swift ファイルに追加します。

1
2
3
4
5
6
7
8
9
10
11
func userNotificationCenter(
  _ center: UNUserNotificationCenter, 
  didReceive response: UNNotificationResponse, 
  withCompletionHandler completionHandler: @escaping () -> Void
) {
  Appboy.sharedInstance()?.userNotificationCenter(
    center, 
    didReceive: response, 
    withCompletionHandler: completionHandler
  )
}
1
2
3
4
5
6
7
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response 
         withCompletionHandler:(void (^)(void))completionHandler {
  [[Appboy sharedInstance] userNotificationCenter:center 
                   didReceiveNotificationResponse:response 
                            withCompletionHandler:completionHandler];
}

ユーザー変数とメソッドへのアクセス

ユーザー変数とメソッドの作成

次に、ABKUser の変数とメソッドに簡単にアクセスできるようにします。BrazeManager.swift ファイルでユーザコードの拡張子を作成し、ヘルパーファイルで提供されている目的について、以下のように整理された方法で読み込むようにします。

  1. ABKUser オブジェクトは、iOS アプリケーションの既知または匿名ユーザを表します。計算変数を追加して ABKUser を取得します。この変数は、ユーザーに関する変数を取得するために再利用されます。
  2. userId に簡単にアクセスするには、ユーザー変数をクエリします。他の変数の中で、ABKUser オブジェクトは (firstNamelastNamephonehomeCity など) の原因となります。
  3. 対応する userIdchangeUser() を呼び出してユーザーを設定します。

```swift // MARK: - User extension BrazeManager { // 1 var user:ABKUser? { return Appboy.sharedInstance()?.user }

// 2 var userId:String? { return user?.userID }

// 3 func changeUser(_ userId:String) { Appboy.sharedInstance()?.changeUser(userId) } } ```

```objc // MARK: - User // 1 - (ABKUser *)user { return [[Appboy sharedInstance] user]; }

// 2 - (NSString *)userId { return [self user].userID; }

// 3 - (void)changeUser:(NSString *)userId { [[Appboy sharedInstance] changeUser:userId]; } ```

ログ分析

カスタムイベント記録メソッドの作成

以下の Braze SDK logCustomEvent メソッドに基づいて、一致するメソッドを作成します。

Braze logCustomEvent 参照メソッド
Braze iOS SDK のメソッドに直接アクセスできるのは BrazeManager.swift ファイルだけなので、これは仕様です。したがって、マッチングメソッドを作成することで、結果は同じになり、プロダクションコード内の Braze iOS SDK に直接依存することなく実行されます。

1
open func logCustomEvent(_ eventName: String, withProperties properties: [AnyHashable : Any]?)

マッチングメソッド
Appboy オブジェクトから Braze にカスタムイベントを記録します。Properties はオプションのパラメータで、デフォルト値は nil です。カスタムイベントにはプロパティは必要ありませんが、名前を付ける必要があります。

1
2
3
func logCustomEvent(_ eventName: String, withProperties properties: [AnyHashable: Any]? = nil) {
  Appboy.sharedInstance()?.logCustomEvent(eventName, withProperties: properties)
}
1
2
3
- (void)logCustomEvent:(NSString *)eventName withProperties:(nullable NSDictionary *)properties {
  [[Appboy sharedInstance] logCustomEvent:eventName withProperties:properties];
}
カスタム属性記録メソッドの作成

SDK は、カスタム属性として多数のタイプをログに記録できます。設定可能な値タイプごとにヘルパーメソッドを作成する必要はありません。代わりに、適切な値に絞り込むことができる1つのメソッドのみを公開します。

1
2
3
4
5
- (BOOL)setCustomAttributeWithKey:(NSString *)key andBOOLValue:(BOOL)value; 
- (BOOL)setCustomAttributeWithKey:(NSString *)key andIntegerValue:(NSIntenger)value; 
- (BOOL)setCustomAttributeWithKey:(NSString *)key andDoubleValue:(double)value; 
- (BOOL)setCustomAttributeWithKey:(NSString *)key andStringValue:(NSString *)value; 
- (BOOL)setCustomAttributeWithKey:(NSString *)key andDateValue:(NSDate *)value;

カスタム属性は、ABKUser オブジェクトからログに記録されます。

属性に設定可能なすべての使用可能なタイプを包含できる1つのメソッドを作成します。分析拡張の BrazeManager.swift ファイルにこのメソッドを追加します。これは、有効なカスタム属性タイプをフィルタリングして、一致するタイプに関連付けられたメソッドを呼び出すことによって行うことができます。

  • パラメーター value は、Equatable プロトコルに準拠する汎用型です。これは明示的に行われます。そのため、タイプが Braze iOS SDK が期待するものでない場合、コンパイル時エラーが発生します。
  • パラメータ key および value はオプションのパラメータで、メソッドで条件付きでアンラップされます。これは、Nil 以外の値が Braze iOS SDK に渡されるようにする1つの方法です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func setCustomAttributeWithKey<T: Equatable>(_ key: String?, andValue value: T?) {
  guard let key = key, let value = value else { return }
  switch value.self {
  case let value as Date:
    user?.setCustomAttributeWithKey(key, andDateValue: value)
  case let value as Bool:
    user?.setCustomAttributeWithKey(key, andBOOLValue: value)
  case let value as String:
    user?.setCustomAttributeWithKey(key, andStringValue: value)
  case let value as Double:
    user?.setCustomAttributeWithKey(key, andDoubleValue: value)
  case let value as Int:
    user?.setCustomAttributeWithKey(key, andIntegerValue: value)
  default:
   return
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)setCustomAttributeWith:(NSString *)key andValue:(id)value {
  if ([value isKindOfClass:[NSDate class]]) {
    [[self user] setCustomAttributeWithKey:key andDateValue:value];
  } else if ([value isKindOfClass:[NSString class]]) {
    [[self user] setCustomAttributeWithKey:key andStringValue:value];
  } else if ([value isKindOfClass:[NSNumber class]]) {
    if (strcmp([value objCType], @encode(double)) == 0) {
      [[self user] setCustomAttributeWithKey:key andDoubleValue:[value doubleValue]];
    } else if (strcmp([value objCType], @encode(int)) == 0) {
      [[self user] setCustomAttributeWithKey:key andIntegerValue:[value integerValue]];
    } else if ([value boolValue]) {
      [[self user] setCustomAttributeWithKey:key andBOOLValue:[value boolValue]];
    }
  }
}
購入記録メソッドの作成

次に、以下の Braze SDK logPurchase メソッドに基づいて、マッチングメソッドを作成します。

Braze logPurchase 参照メソッド
Braze iOS SDK のメソッドに直接アクセスできるのは BrazeManager.swift ファイルだけなので、これは仕様です。したがって、マッチングメソッドを作成することで、結果は同じになり、プロダクションコード内の Braze iOS SDK に直接依存することなく実行されます。

1
open func logPurchase(_ productIdentifier: String, inCurrency currency: String, atPrice price: NSDecimalNumber, withoutQuantity quantity: UInt)

マッチングメソッド
Appboy オブジェクトからの購入を Braze に記録します。SDK には、購入を記録するための複数の方法があり、これは 1 つの例にすぎません。このメソッドは、NSDecimal およびUInt オブジェクトの作成も処理します。その部分をどのように処理するかはあなた次第ですが、以下はほんの一例に過ぎません。

```swift func logPurchase(_ productIdentifier:String, inCurrency currency:String, atPrice price: String, withQuantity quantity:Int) {

Appboy.sharedInstance()?.logPurchase(productIdentifier, inCurrency: currency, atPrice:NSDecimalNumber(string: price), withQuantity:UInt(quantity))

} ```

```objc - (void)logPurchase:(NSString *)productIdentifier inCurrency:(nonnull NSString *)currencyCode atPrice:(nonnull NSDecimalNumber *)price withQuantity:(NSUInteger)quantity { [[Appboy sharedInstance] logPurchase:productIdentifier inCurrency:currencyCode atPrice:price withQuantity:quantity]; } ```

アプリ内メッセージ

ABKInAppMessageUIDelegate に準拠する

次に、BrazeManager.swift ファイルコードを有効にして、ABKInAppMessageUIDelegate に準拠し、関連付けられたメソッドを直接処理します。

デリゲートに準拠するコードは、BrazeManager.swift ファイルの didFinishLaunching... メソッドに追加されます。初期化コードは最終的に次のようになります。

```swift func application(_ application:UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey:Any]?) { Appboy.start(withApiKey: apiKey, in: application, withLaunchOptions: launchOptions, withAppboyOptions: appboyOptions)

let options:UNAuthorizationOptions = [.alert, .sound, .badge] UNUserNotificationCenter.current().requestAuthorization(options: options) { (granted, error) in Appboy.sharedInstance()?.pushAuthorization(fromUserNotificationCenter: granted) } UIApplication.shared.registerForRemoteNotifications()

Appboy.sharedInstance()?.inAppMessageController.inAppMessageUIController?.setInAppMessageUIDelegate?(self) } ```

```objc - (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [Appboy startWithApiKey:[self apiKey] inApplication:application withLaunchOptions:launchOptions withAppboyOptions:[self appboyOptions]];

UNAuthorizationOptions options = (UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge); [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) { [[Appboy sharedInstance] pushAuthorizationFromUserNotificationCenter:granted]; }]; [[UIApplication sharedApplication] registerForRemoteNotifications];

[[Appboy sharedInstance].inAppMessageController.inAppMessageUIController setInAppMessageUIDelegate:self]; } ```

デリゲートメソッドの追加

次に、ABKInAppMessageUIDelegate に準拠する拡張子を作成します。

次のスニペットを分析セクションに追加します。BrazeManager.swift オブジェクトがデリゲートとして設定されていることに注意してください。これは、BrazeManager.swift ファイルがすべての ABKInAppMessageUIDelegate メソッドを処理する場所です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// MARK: - ABKInAppMessage UI Delegate
extension AppboyManager: ABKInAppMessageUIDelegate{
  func inAppMessageViewControllerWith(_ inAppMessage: ABKInAppMessage) -> ABKInAppMessageViewController {
    switch inAppMessage {
    case is ABKInAppMessageSlideup:
      return ABKInAppMessageSlideupViewController(inAppMessage: inAppMessage)
    case is ABKInAppMessageModal:
      return ABKInAppMessageModalViewController(inAppMessage: inAppMessage)
    case is ABKInAppMessageFull:
      return ABKInAppMessageFullViewController(inAppMessage: inAppMessage)
    case is ABKInAppMessageHTML:
      return ABKInAppMessageHTMLViewController(inAppMessage: inAppMessage)
    default:
      return ABKInAppMessageViewController(inAppMessage: inAppMessage)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// MARK: - ABKInAppMessage UI Delegate
- (ABKInAppMessageViewController *)inAppMessageViewControllerWithInAppMessage:(ABKInAppMessage *)inAppMessage {
  if ([inAppMessage isKindOfClass:[ABKInAppMessageSlideup class]]) {
    return [[ABKInAppMessageSlideupViewController alloc] initWithInAppMessage:inAppMessage];
  } else if ([inAppMessage isKindOfClass:[ABKInAppMessageModal class]]) {
    return [[ABKInAppMessageModalViewController alloc] initWithInAppMessage:inAppMessage];
  } else if ([inAppMessage isKindOfClass:[ABKInAppMessageFull class]]) {
    return [[ABKInAppMessageFullViewController alloc] initWithInAppMessage:inAppMessage];
  } else if ([inAppMessage isKindOfClass:[ABKInAppMessageHTML class]]) {
    return [[ABKInAppMessageHTMLViewController alloc] initWithInAppMessage:inAppMessage];
  }
  return nil;
}

コンテンツカード

コンテンツカードの変数とメソッドの作成

不要な import AppboyUI ステートメントを必要とせずに、コンテンツカードビューコントローラを表示するようにプロダクションコードを有効にします。

BrazeManager.swift ファイルにコンテンツカードコードの拡張子を作成します。ヘルパーファイルで提供されている目的について、以下のように整理された方法で読み込むようにします。

  1. ABKContentCardsTableViewController を表示します。オプションの navigationController は、ビューコントローラーを表示またはプッシュするために必要な唯一のパラメーターです。
  2. ABKContentCardsTableViewController オブジェクトを初期化し、オプションでタイトルを変更します。初期化されたビューコントローラーをナビゲーションスタックに追加する必要もあります。

```swift // MARK: -コンテンツカード extension BrazeManager {

// 1 func displayContentCards(navigationController:UINavigationController?) {

1
2
3
4
// 2 
let contentCardsVc = ABKContentCardsTableViewController()
contentCardsVc.title = "Content Cards"
navigationController?.pushViewController(contentCardsVc, animated: true)   } } ```

```objc // MARK: - Content Cards // 1 - (void)displayContentCards:(UINavigationController *)navigationController { // 2 ABKContentCardsTableViewController *contentCardsVc = [[ABKContentCardsTableViewController alloc] init]; contentCardsVc.title = @”Content Cards”; [navigationController pushViewController:contentCardsVc animated:YES]; } ```

次のステップ

おめでとうございます!このベストプラクティス統合ガイドを完了しました!BrazeManager ヘルパーファイルの例は、GitHub にあります。

これで、Braze iOS SDK への依存関係をプロダクションコードの残りの部分から切り離したので、オプションの高度な実装ガイドをいくつかご覧ください。

「このページはどの程度役に立ちましたか?」
New Stuff!