iOS SDK - データプライバシー

データプライバシー法の遵守

GDPR、CCPA、その他の消費者プライバシー規制におけるユーザーの同意の選択を Singular に通知することで、プライバシーに準拠したデータ収集を実装します。

ユーザーが第三者との情報共有に同意または拒否した場合、Singular のプライバシーメソッドを使用してその選択を伝達します。これにより、 California Consumer Privacy Act (CCPA) などの規制を遵守し、パートナーがユーザーのプライバシー設定を尊重できるようになります。

詳しく見る: Singular がプライバシー同意をどのように処理するかの詳細については、 ユーザープライバシーとデータ共有の制限 を参照してください。


データ共有の制限

第三者へのデータ共有の制御

ユーザーが第三者パートナーと個人データを共有することに同意したかどうかを、 limitDataSharing メソッドを使用して Singular に通知します。

メソッドシグネチャ:

+ (void)limitDataSharing:(BOOL)shouldLimitDataSharing;

パラメーター:

  • NO (false): ユーザーがオプトインし、データの共有に同意した
  • YES (true): ユーザーがオプトアウトし、データの共有に同意しなかった

重要: このメソッドは任意ですが、アトリビューションデータの共有に影響します。一部のパートナーは、ユーザーがオプトインしたことが明示的に通知された場合にのみ、完全なアトリビューション情報を共有します。

使用例

Swift Objective-C
// User has opted in to share their data
Singular.limitDataSharing(false)

// User has opted out and declined to share their data
Singular.limitDataSharing(true)

// Example: Set based on user preference
func handlePrivacyConsent(userConsented: Bool) {
    // Pass inverse: false = opted in, true = opted out
    Singular.limitDataSharing(!userConsented)

    print("Data sharing: \(userConsented ? "Enabled" : "Limited")")
}

動作の仕組み:

Singular はこの設定を ユーザープライバシーポストバック で使用し、規制遵守のためにこれを必要とするパートナーに渡します。


イベント単位のデータ共有制限

単一イベントのデータ共有を上書き

他のイベント引数とともに ATTRIBUTE_SNG_LIMIT_DATA_SHARING 属性を渡すことで、単一のイベントまたはカスタム収益呼び出しに対して、グローバルな limitDataSharing 設定を上書きできます。これは、ユーザーがアクションと同時に同意を更新し、後続のイベントに対する SDK 全体の設定を変更することなく、その特定のイベントに新しい選択を即座に反映させたい場合に役立ちます。

許容値:

  • NO (false): このイベントに限ってユーザーがオプトイン
  • YES (true): このイベントに限ってユーザーがオプトアウト

重要: この属性はブール値である必要があります (Objective-C では BOOL 、Swift では Bool )。ブール値以外の入力は無視され、リクエストはグローバルな limitDataSharing 設定にフォールバックします。いずれの場合でも、この属性はリクエストが送信される前にイベントの引数から削除されるため、イベントペイロードには表示されません。

使用例

Swift Objective-C
// Example 1: Standard event, opt out only for this event
var dic: [AnyHashable: Any] = [:]
dic[ATTRIBUTE_SNG_LIMIT_DATA_SHARING] = true
dic["order_id"] = "12345"

Singular.event("checkout_completed", withArgs: dic)

// Example 2: Custom revenue, opt in only for this event
var attributes: [AnyHashable: Any] = [:]
attributes[ATTRIBUTE_SNG_LIMIT_DATA_SHARING] = false
attributes["sku"] = "premium_monthly"

Singular.customRevenue("premium_purchase",
                      currency: "USD",
                      amount: 9.99,
                      withAttributes: attributes)

動作の仕組み:

有効なブール値が指定されると、SDK は該当属性をイベント引数から削除し、リクエストの data_sharing_options.limit_data_sharing フィールドに書き込みます — これにより、その単一リクエストに限ってグローバルな limitDataSharing 設定が上書きされます。グローバル設定と getLimitDataSharing の結果は変更されないため、属性を指定しない後続のイベントは引き続きグローバルな選択を使用します。


GDPR 準拠メソッド

GDPR (一般データ保護規則) およびその他のプライバシー規制を遵守するために、ユーザートラッキング同意を管理し SDK 機能を制御します。

トラッキング同意管理

trackingOptIn

GDPR オプトインイベントを Singular サーバーに送信して、ユーザーのトラッキング同意を明示的に記録します。

Info.plist の前提条件: アプリが Apple の App Tracking Transparency (iOS 14.5+) — 同意したユーザーの IDFA にアクセスするために必要 — を使用する場合、ATT プロンプトを表示したり +trackingOptIn を呼び出す前に、 Info.plist NSUserTrackingUsageDescription を明確なユーザー向け説明とともに宣言してください。このキーなしにトラッキングを要求するアプリは App Review で却下されます。

メソッドシグネチャ:

+ (void)trackingOptIn;

使用するタイミング:

  • GDPR 準拠: GDPR 規制地域でユーザーがトラッキングに明示的に同意したときに呼び出す
  • 同意の記録: Singular のシステム内で、ユーザーが GDPR 同意を提供したものとしてマーク
  • デフォルトの動作: この呼び出しがなくても SDK はトラッキングを継続するが、同意を特定して記録することはない
Swift Objective-C
// User accepted tracking consent
Singular.trackingOptIn()

// Example: Call after consent dialog
func onUserAcceptedTracking() {
    Singular.trackingOptIn()
    print("User opted in to tracking")
}

トラッキング制御メソッド

stopAllTracking

このデバイスの現在のユーザーに対する SDK のすべてのトラッキング活動を完全に無効化します。

メソッドシグネチャ:

+ (void)stopAllTracking;

重要な警告: このメソッドは resumeAllTracking が呼び出されるまで SDK を恒久的に無効化します。無効化された状態はアプリの再起動後も維持され、プログラムによってのみ元に戻すことができます。

動作:

  • 即時適用: すべてのトラッキング、イベント報告、データ収集を即座に停止
  • 永続的な状態: アプリを閉じて再度開いた後も無効化された状態が継続
  • 自動リセットなし: 再度有効にするには resumeAllTracking を明示的に呼び出す必要がある
Swift Objective-C
// User declined all tracking
Singular.stopAllTracking()

// Example: Handle user opt-out
func onUserDeclinedTracking() {
    Singular.stopAllTracking()
    print("All tracking stopped")

    // Optionally store preference
    saveUserTrackingPreference(false)
}

resumeAllTracking

stopAllTracking で停止されたトラッキングを再度有効にします。

メソッドシグネチャ:

+ (void)resumeAllTracking;

使用ケース:

  • 同意の変更: ユーザーがプライバシー設定を変更し、トラッキングに再度オプトインした
  • プライバシー設定: ユーザーがアプリの設定メニューで同意を更新した
  • 地域コンプライアンス: ユーザーが規制対象外の地域に移動した場合にトラッキングを再有効化
Swift Objective-C
// User opted back in to tracking
Singular.resumeAllTracking()

// Example: Handle consent update
func onUserResumedTracking() {
    Singular.resumeAllTracking()
    print("Tracking resumed")

    // Optionally update stored preference
    saveUserTrackingPreference(true)
}

isAllTrackingStopped

現在のユーザーに対してトラッキングが無効化されているかどうかを確認します。

メソッドシグネチャ:

+ (BOOL)isAllTrackingStopped;

戻り値:

  • YES (true): stopAllTracking によってトラッキングが現在停止されている
  • NO (false): トラッキングがアクティブ (停止されていないか、再開された状態)

SDK が初期化されていない場合、それ以前のトラッキング状態に関係なく NO を返します。この値を信頼する前に、 +start: が完了したことを必ず確認し、 NO を「アクティブにトラッキング中」ではなく「停止されていない、またはまだ初期化されていない」と解釈してください。

Swift Objective-C
// Check current tracking status
let isTrackingStopped = Singular.isAllTrackingStopped()

// Example: Display privacy status in settings
func getPrivacyStatusText() -> String {
    return Singular.isAllTrackingStopped() ? "Tracking: Disabled" : "Tracking: Enabled"
}

// Example: Sync UI with tracking state
func updatePrivacyToggle() {
    let isStopped = Singular.isAllTrackingStopped()
    privacyToggle.isOn = !isStopped
    print("Current tracking state: \(isStopped ? "Stopped" : "Active")")
}

児童プライバシー保護

trackingUnder13

COPPA (児童オンラインプライバシー保護法) およびその他の児童プライバシー規制を遵守するために、ユーザーが 13 歳未満であることを Singular に通知します。

メソッドシグネチャ:

+ (void)trackingUnder13;

コンプライアンス要件:

  • COPPA 準拠: 米国で 13 歳未満の児童からデータを収集するアプリで必須
  • 年齢制限コンテンツ: 登録または年齢確認時にユーザーが 13 歳未満として識別された場合に使用
  • トラッキングの制限: 児童プライバシー保護法を遵守するためにデータ収集を制限
Swift Objective-C
// User identified as under 13
Singular.trackingUnder13()

// Example: Call after age verification
func onAgeVerified(userAge: Int) {
    if userAge < 13 {
        Singular.trackingUnder13()
        print("COPPA mode enabled for user under 13")
    }
}

重要: ユーザーが 13 歳未満であると判明したら、できるだけ早くこのメソッドを呼び出してください。理想的にはアプリの初期化時、または年齢確認の直後が望ましいです。これにより、それ以降のすべてのトラッキングが児童プライバシー規制を遵守するようになります。


limitAdvertisingIdentifiers

混合オーディエンスアプリの場合、SDK 初期化時に広告識別子 (iOS の IDFA) の収集と使用を制限します。

構成プロパティ:

@property (assign) BOOL limitAdvertisingIdentifiers;

使用ケース:

  • 混合オーディエンスアプリ: アプリ起動前に年齢が決定される、成人と児童の両方を対象とするアプリ
  • 既知の COPPA ユーザー: 初期化時点でユーザーが 13 歳未満であることが分かっている場合
  • プライバシーファーストのアプローチ: 最初の SDK セッションから広告識別子の制限を適用

構成メソッド

プライバシー要件を事前に把握しているアプリの場合、SDK 初期化時に広告識別子の制限を設定します。

Swift Objective-C
// Limit advertising identifiers at initialization
let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET")
config?.limitAdvertisingIdentifiers = true

Singular.start(config)

Kids SDK ビルド: limitAdvertisingIdentifiers は Singular Kids SDK ビルドではコンパイルから除外されています ( #ifndef SINGULAR_KIDS で保護)。 Singular-Kids-SDK を組み込んでいる場合、このプロパティは使用できません — Kids SDK は自動的により厳格な識別子処理を実施します。ランタイムでの COPPA フラグ付けには trackingUnder13 を使用してください。

ランタイムメソッド

+start: 呼び出し後、いつでも広告識別子の収集を切り替えることができます。年齢ゲート、同意プロンプト、コンテンツ選択が SDK 起動後に行われる混合オーディエンスアプリに役立ちます。

+ (void)setLimitAdvertisingIdentifiers:(BOOL)enabled;
Swift Objective-C
// Apply identifier limit after the user enters kids mode
func onKidsModeSwitched(isKidsMode: Bool) {
    Singular.setLimitAdvertisingIdentifiers(isKidsMode)
}

ランタイムメソッドにも BOOL 引数が必要です — +setLimitAdvertisingIdentifiers を引数なしで呼び出すとコンパイルされません。構成時プロパティと同様に、このメソッドは Kids SDK ビルドでは使用できません。

ベストプラクティス: 包括的な COPPA 準拠を実現するには、初期化時に limitAdvertisingIdentifiers を使用し、ユーザーの年齢が確認された時点で trackingUnder13() を呼び出してください。これにより、最初のセッションから完全な保護が確保されます。


実装のベストプラクティス

完全なプライバシー管理の例

ユーザーの選好を尊重し、規制を遵守する包括的なプライバシー制御を実装します。

Swift Objective-C
import Foundation

class PrivacyManager {

    private let userDefaults = UserDefaults.standard
    private let consentKey = "user_consent"
    private let dataSharingKey = "data_sharing"

    // Initialize privacy settings on app start
    func initializePrivacy() {
        let hasUserConsent = getUserConsent()
        let allowDataSharing = getDataSharingPreference()

        // Apply stored preferences
        if hasUserConsent {
            Singular.trackingOptIn()
            Singular.resumeAllTracking()
        } else {
            Singular.stopAllTracking()
        }

        // Set data sharing preference
        Singular.limitDataSharing(!allowDataSharing)

        print("Privacy initialized: consent=\(hasUserConsent), sharing=\(allowDataSharing)")
    }

    // User accepts tracking via consent dialog
    func userAcceptedTracking() {
        saveUserConsent(true)
        Singular.trackingOptIn()
        Singular.resumeAllTracking()
        print("User accepted tracking")
    }

    // User declines tracking
    func userDeclinedTracking() {
        saveUserConsent(false)
        Singular.stopAllTracking()
        print("User declined tracking")
    }

    // User updates data sharing preference
    func setDataSharingEnabled(_ enabled: Bool) {
        saveDataSharingPreference(enabled)
        // Note: limitDataSharing uses inverse logic
        Singular.limitDataSharing(!enabled)
        print("Data sharing: \(enabled ? "Enabled" : "Limited")")
    }

    // Get current tracking status
    func isTrackingEnabled() -> Bool {
        return !Singular.isAllTrackingStopped()
    }

    // Private helper methods
    private func getUserConsent() -> Bool {
        return userDefaults.bool(forKey: consentKey)
    }

    private func saveUserConsent(_ consent: Bool) {
        userDefaults.set(consent, forKey: consentKey)
    }

    private func getDataSharingPreference() -> Bool {
        return userDefaults.bool(forKey: dataSharingKey)
    }

    private func saveDataSharingPreference(_ enabled: Bool) {
        userDefaults.set(enabled, forKey: dataSharingKey)
    }
}

ベストプラクティス:

  • 永続的なストレージ: ユーザー設定を UserDefaults またはセキュアなストレージに保存
  • 早期の初期化: 可能であれば SDK 初期化前にプライバシー設定を適用
  • UI 同期: isAllTrackingStopped を使用して設定 UI と実際の SDK 状態を同期
  • 明確なコミュニケーション: アプリ設定で明確でアクセスしやすいプライバシー制御を提供
  • コンプライアンス文書: 規制監査に向けたプライバシー実装の明確な記録を維持