モバイル SDKアプリ内イベント
iOS
AdStage アプリ内イベント統合ガイド (iOS)
目次
概要
AdStage のアプリ内イベントは、ユーザーの行動とアプリのイベントをトラッキングし、マーケティング分析と最適化を支援します。
主な機能
- グローバルコンテキスト管理:ユーザー/デバイス情報を一度設定すれば自動で付与
- シンプルな API:イベント名とパラメータだけで手軽に送信
- 自動セッショントラッキング:セッション ID を自動で生成・管理
- 非同期処理:ネットワーク通信が UI をブロックしない
- オフライン対応:ネットワーク復旧時に自動で再送信
基本設定
CocoaPods の設定
Podfile
platform :ios, '15.0'
target 'YourApp' do
use_frameworks!
# AdStage SDK
pod 'AdapterAdStage', '3.0.11'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
end
end
endインストール:
pod install2. SDK の初期化
import AdapterAdStage
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// AdStage の初期化
AdStageManager.shared.initialize(
apiKey: "your-api-key-here",
serverUrl: "https://api.adstage.app"
)
print("✅ AdStage SDK 初期化完了")
return true
}
}3. Info.plist の設定
<!-- ネットワーク使用の権限 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
</dict>型安全なイベント送信
1. 最もシンプルな方法
import AdapterAdStage
// パラメータなしのイベント
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())
// ログインイベント
AdStageManager.shared.trackEvent(
AdStageEvent.Login(method: .email)
)2. 購入イベント(検証の例)
// ✅ GOOD: value と currency を一緒に指定
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: 29.99,
currency: "USD",
transactionId: "TXN_123456"
)
)
// ❌ BAD: value のみ指定するとコンパイルエラー!
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: 29.99 // ❌ エラー: currency は必須!
)
)
// ✅ GOOD: currency なしで transactionId のみ
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
transactionId: "TXN_123456"
)
)3. 商品の閲覧
// パラメータあり
AdStageManager.shared.trackEvent(
AdStageEvent.ProductDetailsView(
itemId: "PROD_123",
itemName: "Wireless Earbuds"
)
)
// パラメータなし
AdStageManager.shared.trackEvent(AdStageEvent.ProductListView())4. カスタムイベント(event_name の自動昇格)
標準イベント以外にアプリ独自のイベントを送信するときは、AdStageEvent.Custom を使用します。
パラメータに event_name キーを含めると、その値が実際のイベント名に自動で昇格され、ダッシュボードに保存されます。
// 例: 'promotion_click' というカスタムイベントを送信
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"event_name": "promotion_click",
"promotion_id": "summer_sale_2025",
"screen": "home_banner"
]
)
)
// ダッシュボードには "promotion_click" イベントとして収集される
// event_name なしの一般的なカスタムイベント
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"action": "button_click",
"button_id": "promo_banner",
"screen": "home",
"timestamp": Date().timeIntervalSince1970
]
)
)
// ダッシュボードには "custom" イベントとして収集される
// Click、View も自由なパラメータに対応
AdStageManager.shared.trackEvent(
AdStageEvent.Click(
params: [
"campaign_id": "SUMMER2025",
"ad_group": "electronics"
]
)
)標準イベントカタログ
AdStage SDK は 46 個の標準イベントを提供します。
📌 広告トラッキング(4 個)
// 1. 広告クリック
AdStageManager.shared.trackEvent(
AdStageEvent.Click(
params: ["campaign_id": "CAMP_123"]
)
)
// 2. 広告インプレッション
AdStageManager.shared.trackEvent(
AdStageEvent.View(
params: ["impression_id": "IMP_456"]
)
)
// 3. アプリのインストール
AdStageManager.shared.trackEvent(AdStageEvent.Install())
// 4. カスタムイベント(event_name でイベント名を指定)
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"event_name": "promotion_click",
"promotion_id": "summer_sale_2025"
]
)
)👤 ユーザーライフサイクル(5 個)
// SignUpMethod は SDK が提供する enum です(自分で定義しないでください)
// 使用できる値: .email, .google, .apple, .facebook, .kakao, .naver
// 1. 会員登録完了
AdStageManager.shared.trackEvent(
AdStageEvent.SignUp(method: .google)
)
// 2. 会員登録開始
AdStageManager.shared.trackEvent(AdStageEvent.SignUpStart())
// 3. ログイン
AdStageManager.shared.trackEvent(
AdStageEvent.Login(method: .email)
)
// 4. ログアウト
AdStageManager.shared.trackEvent(AdStageEvent.Logout())
// 5. アプリの初回起動
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())📄 コンテンツの閲覧(6 個)
// 1. ホーム画面
AdStageManager.shared.trackEvent(AdStageEvent.HomeView())
// 2. 商品一覧
AdStageManager.shared.trackEvent(
AdStageEvent.ProductListView(itemCategory: "electronics")
)
// 3. 検索結果
AdStageManager.shared.trackEvent(
AdStageEvent.SearchResultView(searchTerm: "wireless headphones")
)
// 4. 商品詳細
AdStageManager.shared.trackEvent(
AdStageEvent.ProductDetailsView(
itemId: "PROD_123",
itemName: "Wireless Earbuds"
)
)
// 5. ページの閲覧(ウェブ)
AdStageManager.shared.trackEvent(
AdStageEvent.PageView(
pageUrl: "https://example.com/products",
pageTitle: "Products"
)
)
// 6. 画面の閲覧(アプリ)
AdStageManager.shared.trackEvent(
AdStageEvent.ScreenView(
screenName: "product_detail",
screenClass: "ProductDetailViewController"
)
)🛒 E コマース(8 個)
// 1. カートに追加
AdStageManager.shared.trackEvent(
AdStageEvent.AddToCart(
value: 99000.0,
currency: "KRW",
items: [
EcommerceItem(
itemId: "PROD_123",
itemName: "Wireless Earbuds",
price: 99000.0,
quantity: 1
)
]
)
)
// 2. カートから削除
AdStageManager.shared.trackEvent(
AdStageEvent.RemoveFromCart(
value: 50000.0,
currency: "KRW"
)
)
// 3. ウィッシュリストに追加
AdStageManager.shared.trackEvent(
AdStageEvent.AddToWishlist(
itemId: "PROD_456",
itemName: "Smart Watch"
)
)
// 4. 決済情報の入力
AdStageManager.shared.trackEvent(
AdStageEvent.AddPaymentInfo(paymentType: "credit_card")
)
// 5. 決済開始
AdStageManager.shared.trackEvent(
AdStageEvent.BeginCheckout(
value: 150000.0,
currency: "KRW"
)
)
// 6. 購入完了 ⭐⭐⭐
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: 129000.0,
currency: "KRW",
transactionId: "ORDER_20250105_001",
tax: 12900.0,
shipping: 3000.0,
coupon: "SUMMER2025",
items: [
EcommerceItem(
itemId: "PROD_123",
itemName: "Wireless Earbuds",
price: 126000.0,
quantity: 1
)
]
)
)
// 7. 返金
AdStageManager.shared.trackEvent(
AdStageEvent.Refund(
transactionId: "ORDER_20250105_001",
value: 129000.0,
currency: "KRW"
)
)🎮 進行/達成(4 個)
// 1. チュートリアル開始
AdStageManager.shared.trackEvent(
AdStageEvent.TutorialBegin(
params: ["tutorial_id": "intro"]
)
)
// 2. チュートリアル完了
AdStageManager.shared.trackEvent(
AdStageEvent.TutorialComplete(
params: ["duration_seconds": 120]
)
)
// 3. レベルアップ
AdStageManager.shared.trackEvent(
AdStageEvent.LevelUp(
level: 25,
character: "warrior"
)
)
// 4. 実績の達成
AdStageManager.shared.trackEvent(
AdStageEvent.Achievement(achievementId: "first_win")
)💬 インタラクション(3 個)
// 1. 検索
AdStageManager.shared.trackEvent(
AdStageEvent.Search(searchTerm: "gaming laptop")
)
// 2. 共有
AdStageManager.shared.trackEvent(
AdStageEvent.Share(
contentType: "product",
method: "kakao"
)
)
// 3. アプリ内広告のクリック
AdStageManager.shared.trackEvent(
AdStageEvent.AdClick(
adPlatform: "admob",
adFormat: "rewarded_video",
adUnitName: "AD_12345"
)
)🎮 ゲーム特化(4 個)
// 1. ゲームプレイ
AdStageManager.shared.trackEvent(
AdStageEvent.GamePlay(
level: 10,
levelName: "Dragon's Lair",
character: "mage",
contentType: "dungeon"
)
)
// 2. ボーナスの獲得
AdStageManager.shared.trackEvent(
AdStageEvent.AcquireBonus(
contentType: "reward",
itemId: "ITEM_123",
itemName: "Gold Chest",
quantity: 1
)
)
// 3. ゲームサーバーの選択
AdStageManager.shared.trackEvent(
AdStageEvent.SelectGameServer(
contentId: "SERVER_01",
contentType: "pvp",
itemName: "Asia Server"
)
)
// 4. パッチ完了
AdStageManager.shared.trackEvent(
AdStageEvent.CompletePatch(
contentId: "PATCH_2.1.0",
contentType: "update"
)
)📅 サブスクリプション/トライアル(3 個)
// 1. 無料トライアル開始
AdStageManager.shared.trackEvent(
AdStageEvent.StartTrial(
value: 9900.0,
currency: "KRW",
trialDays: 14
)
)
// 2. サブスクリプション開始
AdStageManager.shared.trackEvent(
AdStageEvent.Subscribe(
value: 9900.0,
currency: "KRW",
subscriptionId: "premium_monthly"
)
)
// 3. サブスクリプションのキャンセル
AdStageManager.shared.trackEvent(
AdStageEvent.Unsubscribe(subscriptionId: "premium_monthly")
)💰 仮想通貨(2 個)
// 1. 仮想通貨(クレジット)の獲得 - AcquireBonus を使用
AdStageManager.shared.trackEvent(
AdStageEvent.AcquireBonus(
contentType: "currency",
itemName: "gold",
quantity: 500
)
)
// 2. 仮想通貨(クレジット)の使用 - SpendCredits を使用
AdStageManager.shared.trackEvent(
AdStageEvent.SpendCredits(
value: 100.0,
itemName: "health_potion"
)
)🎯 その他(7 個)
// 1. スケジュール登録
AdStageManager.shared.trackEvent(
AdStageEvent.Schedule(
params: ["event_type": "appointment"]
)
)
// 2. クレジットの使用
AdStageManager.shared.trackEvent(
AdStageEvent.SpendCredits(
value: 10.0,
itemName: "premium_feature"
)
)
// 3. プロモーションの閲覧(Custom イベントで送信)
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"event_name": "view_promotion",
"promotion_id": "PROMO_SUMMER",
"promotion_name": "Summer Sale 2025",
"creative_slot": "home_banner_1"
]
)
)
// 4. プロモーションの選択(Custom イベントで送信)
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"event_name": "select_promotion",
"promotion_id": "PROMO_SUMMER",
"promotion_name": "Summer Sale 2025"
]
)
)イベントタイプ別の例
1. アプリのライフサイクル
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// SDK の初期化
AdStageManager.shared.initialize(
apiKey: "your-api-key",
serverUrl: "https://api.adstage.app"
)
// 初回起動イベントは SDK が自動で送信
print("✅ アプリ起動")
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("📱 アプリがバックグラウンドに移行")
}
func applicationWillEnterForeground(_ application: UIApplication) {
print("📱 アプリがフォアグラウンドに移行")
}
}2. ユーザー認証
class AuthManager {
// 会員登録
func onSignUpComplete(method: String) {
let signUpMethod: SignUpMethod
switch method {
case "email": signUpMethod = .email
case "google": signUpMethod = .google
case "apple": signUpMethod = .apple
case "kakao": signUpMethod = .kakao
case "naver": signUpMethod = .naver
default: signUpMethod = .email
}
AdStageManager.shared.trackEvent(
AdStageEvent.SignUp(method: signUpMethod)
)
print("✅ 会員登録完了: \(method)")
}
// ログイン
func onLoginSuccess(userId: String, method: String) {
let loginMethod: SignUpMethod = method == "google" ? .google : .email
AdStageManager.shared.trackEvent(
AdStageEvent.Login(method: loginMethod)
)
print("✅ ログイン: \(userId)")
}
// ログアウト
func onLogout() {
AdStageManager.shared.trackEvent(AdStageEvent.Logout())
print("🚪 ログアウト")
}
}3. 画面トラッキング(BaseViewController パターン)
class BaseViewController: UIViewController {
// サブクラスでオーバーライド
var screenName: String {
return String(describing: type(of: self))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
trackScreenView()
}
private func trackScreenView() {
AdStageManager.shared.trackEvent(
AdStageEvent.ScreenView(
screenName: screenName,
screenClass: String(describing: type(of: self))
)
)
print("📺 \(screenName)")
}
}
// 使用例
class HomeViewController: BaseViewController {
override var screenName: String { "home" }
}
class ProductDetailViewController: BaseViewController {
override var screenName: String { "product_detail" }
var productId: String?
func loadProduct(_ productId: String) {
self.productId = productId
// データを読み込み中...
// 商品詳細の閲覧イベント
AdStageManager.shared.trackEvent(
AdStageEvent.ProductDetailsView(
itemId: productId,
itemName: product.name
)
)
}
}4. E コマースの全体フロー
class EcommerceManager {
// 1. 商品一覧の閲覧
func trackProductList(category: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.ProductListView(itemCategory: category)
)
}
// 2. 検索
func trackSearch(query: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.Search(searchTerm: query)
)
}
// 3. 検索結果の閲覧
func trackSearchResults(query: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.SearchResultView(searchTerm: query)
)
}
// 4. 商品詳細の閲覧
func trackProductView(product: Product) {
AdStageManager.shared.trackEvent(
AdStageEvent.ProductDetailsView(
itemId: product.id,
itemName: product.name
)
)
}
// 5. カートに追加
func trackAddToCart(product: Product, quantity: Int) {
let item = EcommerceItem(
itemId: product.id,
itemName: product.name,
price: product.price,
quantity: quantity
)
AdStageManager.shared.trackEvent(
AdStageEvent.AddToCart(
value: product.price * Double(quantity),
currency: "KRW",
items: [item]
)
)
}
// 6. ウィッシュリストに追加
func trackAddToWishlist(product: Product) {
AdStageManager.shared.trackEvent(
AdStageEvent.AddToWishlist(
itemId: product.id,
itemName: product.name
)
)
}
// 7. 決済開始
func trackBeginCheckout(cart: Cart) {
let items = cart.items.map { cartItem in
EcommerceItem(
itemId: cartItem.product.id,
itemName: cartItem.product.name,
price: cartItem.product.price,
quantity: cartItem.quantity
)
}
AdStageManager.shared.trackEvent(
AdStageEvent.BeginCheckout(
value: cart.totalAmount,
currency: "KRW",
items: items
)
)
}
// 8. 決済情報の入力
func trackAddPaymentInfo(paymentMethod: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.AddPaymentInfo(paymentType: paymentMethod)
)
}
// 9. 購入完了 ⭐⭐⭐
func trackPurchase(order: Order) {
let items = order.items.map { orderItem in
EcommerceItem(
itemId: orderItem.product.id,
itemName: orderItem.product.name,
price: orderItem.product.price,
quantity: orderItem.quantity
)
}
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: order.totalAmount,
currency: "KRW",
transactionId: order.id,
tax: order.tax,
shipping: order.shippingFee,
coupon: order.couponCode,
items: items
)
)
print("✅ 購入完了: \(order.id), \(order.totalAmount)ウォン")
}
// 10. 返金
func trackRefund(order: Order) {
AdStageManager.shared.trackEvent(
AdStageEvent.Refund(
transactionId: order.id,
value: order.totalAmount,
currency: "KRW"
)
)
}
// 11. 共有
func trackShare(product: Product, method: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.Share(
contentType: "product",
method: method
)
)
}
}5. ゲームイベント
class GameEventManager {
// チュートリアル
func trackTutorialBegin(tutorialId: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.TutorialBegin(
params: ["tutorial_id": tutorialId]
)
)
}
func trackTutorialComplete(tutorialId: String, duration: TimeInterval) {
AdStageManager.shared.trackEvent(
AdStageEvent.TutorialComplete(
params: [
"tutorial_id": tutorialId,
"duration_seconds": Int(duration)
]
)
)
}
// レベル
func trackLevelUp(level: Int, character: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.LevelUp(
level: level,
character: character
)
)
}
// 実績
func trackAchievement(achievementId: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.Achievement(achievementId: achievementId)
)
}
// ゲームプレイ
func trackGameStart(level: Int, levelName: String, character: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.GamePlay(
level: level,
levelName: levelName,
character: character,
contentType: "pvp"
)
)
}
// ボーナスの獲得
func trackBonusAcquired(itemId: String, itemName: String, quantity: Int) {
AdStageManager.shared.trackEvent(
AdStageEvent.AcquireBonus(
contentType: "reward",
itemId: itemId,
itemName: itemName,
quantity: quantity
)
)
}
// 仮想通貨(クレジット)の獲得 - AcquireBonus を使用
func trackEarnCurrency(currencyName: String, amount: Int) {
AdStageManager.shared.trackEvent(
AdStageEvent.AcquireBonus(
contentType: "currency",
itemName: currencyName,
quantity: amount
)
)
}
// 仮想通貨(クレジット)の使用 - SpendCredits を使用
func trackSpendCurrency(currencyName: String, amount: Double, itemName: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.SpendCredits(
value: amount,
itemName: itemName
)
)
}
}ベストプラクティス
1. Extension の活用
// UIViewController+AdStage.swift
extension UIViewController {
func trackScreen() {
let screenName = String(describing: type(of: self))
.replacingOccurrences(of: "ViewController", with: "")
.lowercased()
AdStageManager.shared.trackEvent(
AdStageEvent.ScreenView(
screenName: screenName,
screenClass: String(describing: type(of: self))
)
)
}
}
// 使用
class ProfileViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
trackScreen() // ✅ シンプル!
}
}2. ViewModel でのイベントトラッキング
class ProductViewModel: ObservableObject {
@Published var product: Product?
func loadProduct(productId: String) {
Task {
do {
let product = try await repository.getProduct(productId)
self.product = product
// 商品閲覧イベント
AdStageManager.shared.trackEvent(
AdStageEvent.ProductDetailsView(
itemId: product.id,
itemName: product.name
)
)
} catch {
print("Failed to load product: \(error)")
}
}
}
func addToCart(product: Product, quantity: Int) {
Task {
do {
try await repository.addToCart(product, quantity: quantity)
let item = EcommerceItem(
itemId: product.id,
itemName: product.name,
price: product.price,
quantity: quantity
)
AdStageManager.shared.trackEvent(
AdStageEvent.AddToCart(
value: product.price * Double(quantity),
currency: "KRW",
items: [item]
)
)
} catch {
print("Failed to add to cart: \(error)")
}
}
}
}3. SwiftUI での使用
import SwiftUI
import AdapterAdStage
struct ProductDetailView: View {
let productId: String
@StateObject private var viewModel = ProductViewModel()
var body: some View {
VStack {
// UI...
Button("カートに追加") {
viewModel.addToCart(viewModel.product, quantity: 1)
// ボタンクリックイベント
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"action": "add_to_cart_button",
"product_id": productId
]
)
)
}
}
.onAppear {
viewModel.loadProduct(productId: productId)
// 画面閲覧イベント
AdStageManager.shared.trackEvent(
AdStageEvent.ScreenView(
screenName: "product_detail",
screenClass: "ProductDetailView"
)
)
}
}
}4. イベントラッパークラス
class AnalyticsManager {
static let shared = AnalyticsManager()
private init() {}
func trackScreen(_ screenName: String, screenClass: String? = nil) {
AdStageManager.shared.trackEvent(
AdStageEvent.ScreenView(
screenName: screenName,
screenClass: screenClass
)
)
print("📺 Screen: \(screenName)")
}
func trackPurchase(_ order: Order) {
let items = order.items.map {
EcommerceItem(
itemId: $0.product.id,
itemName: $0.product.name,
price: $0.product.price,
quantity: $0.quantity
)
}
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: order.totalAmount,
currency: "KRW",
transactionId: order.id,
items: items
)
)
print("💰 Purchase: \(order.id)")
}
func trackError(_ error: Error, context: String) {
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(
params: [
"event_type": "error",
"error_message": error.localizedDescription,
"context": context
]
)
)
print("❌ Error: \(context) - \(error)")
}
}5. パフォーマンス最適化:Throttling
class ThrottledEventTracker {
private var lastTrackTimes: [String: TimeInterval] = [:]
private let throttleInterval: TimeInterval = 2.0 // 2 秒
func trackEvent(_ event: AdStageEventProtocol) {
let eventKey = event.eventName
let now = Date().timeIntervalSince1970
let lastTime = lastTrackTimes[eventKey] ?? 0
if now - lastTime >= throttleInterval {
AdStageManager.shared.trackEvent(event)
lastTrackTimes[eventKey] = now
} else {
print("⏱️ Throttled: \(eventKey)")
}
}
}
// 使用(スクロールイベントなど)
let throttledTracker = ThrottledEventTracker()
func scrollViewDidScroll(_ scrollView: UIScrollView) {
throttledTracker.trackEvent(
AdStageEvent.Custom(
params: [
"action": "scroll",
"offset_y": scrollView.contentOffset.y
]
)
)
}変換の例
// 1. 基本イベント
// OLD: EventTrackingManager.shared.trackEvent(...)
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())
// 2. ログイン
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.Login(method: .email))
// 3. 画面の閲覧
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.ScreenView(screenName: "home"))
// 4. カスタム
// NEW:
AdStageManager.shared.trackEvent(
AdStageEvent.Custom(params: ["action": "click"])
)トラブルシューティング
1. コンパイルエラー:「currency パラメータは必須」
問題:
// ❌ エラー
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(value: 9900.0)
)解決方法:
// ✅ currency を追加(ISO 4217、3 文字)
AdStageManager.shared.trackEvent(
AdStageEvent.Purchase(
value: 9900.0,
currency: "KRW"
)
)2. Xcode の自動補完が機能しない
解決方法:
- Clean Build Folder:
Product → Clean Build Folder (⇧⌘K) - Derived Data を削除:
~/Library/Developer/Xcode/DerivedData - Pod を再インストール:
pod deintegrate
pod install3. 通貨コードの検証エラー
// ❌ 2 文字のコード
AdStageEvent.Purchase(value: 100.0, currency: "KR")
// ValidationException: "Currency must be 3-letter ISO 4217 code"
// ✅ 3 文字の ISO 4217 コード
AdStageEvent.Purchase(value: 100.0, currency: "KRW") // 韓国ウォン
AdStageEvent.Purchase(value: 100.0, currency: "USD") // 米ドル
AdStageEvent.Purchase(value: 100.0, currency: "JPY") // 日本円4. SwiftUI Preview での競合
問題: Preview で AdStageManager の初期化エラーが発生する
解決方法:
#if DEBUG
struct ProductDetailView_Previews: PreviewProvider {
static var previews: some View {
ProductDetailView(productId: "PROD_123")
.onAppear {
// Preview では初期化しない
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == nil {
AdStageManager.shared.initialize(
apiKey: "test-key",
serverUrl: "https://api.adstage.app"
)
}
}
}
}
#endif5. デバッグログの確認
SDK は、初期化とイベント送信の過程のログをコンソールに自動で出力します。 別途デバッグモードを設定しなくても、Xcode のコンソールですぐに確認できます。
コンソールフィルター:
# Xcode Console
filter: AdStage (または ADSTAGE)参考資料
標準リファレンス
FAQ
Q: カスタムイベントはどのように送信しますか?
A: AdStageEvent.Custom(params: [...]) を使用します。
Q: Android SDK と互換性はありますか?
A: はい。v3.0 は Android SDK と 100% 同じ 46 個のイベントに対応しています。
Q: SwiftUI で使用できますか?
A: はい。ObservableObject パターンで完全に対応しています。
サポート
連絡先:
- メールアドレス:support@nbase.io
© 2025 NBase. All rights reserved.

