データプライバシー法の遵守
GDPR、CCPA、その他の消費者プライバシー規制におけるユーザーの同意の選択を Singular に通知することで、プライバシーに準拠したデータ収集を実装します。
ユーザーが第三者との情報共有に同意または拒否した場合、Singular のプライバシーメソッドを使用してその選択を伝達します。これにより、 California Consumer Privacy Act (CCPA) などの規制を遵守し、パートナーがユーザーのプライバシー設定を尊重できるようになります。
詳しく見る: Singular がプライバシー同意をどのように処理するかの詳細については、 ユーザープライバシーとデータ共有の制限 を参照してください。
データ共有の制限
第三者へのデータ共有の制御
ユーザーが第三者パートナーと個人データを共有することに同意したかどうかを、
limitDataSharing
メソッドを使用して Singular に通知します。
メソッドシグネチャ:
+ (void)limitDataSharing:(BOOL)shouldLimitDataSharing;
パラメーター:
- NO (false): ユーザーがオプトインし、データの共有に同意した
- YES (true): ユーザーがオプトアウトし、データの共有に同意しなかった
重要: このメソッドは任意ですが、アトリビューションデータの共有に影響します。一部のパートナーは、ユーザーがオプトインしたことが明示的に通知された場合にのみ、完全なアトリビューション情報を共有します。
使用例
// 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")")
}
// User has opted in to share their data
[Singular limitDataSharing:NO];
// User has opted out and declined to share their data
[Singular limitDataSharing:YES];
// Example: Set based on user preference
- (void)handlePrivacyConsent:(BOOL)userConsented {
// Pass inverse: NO = opted in, YES = opted out
[Singular limitDataSharing:!userConsented];
NSLog(@"Data sharing: %@", userConsented ? @"Enabled" : @"Limited");
}
動作の仕組み:
Singular はこの設定を ユーザープライバシーポストバック で使用し、規制遵守のためにこれを必要とするパートナーに渡します。
イベント単位のデータ共有制限
単一イベントのデータ共有を上書き
他のイベント引数とともに
ATTRIBUTE_SNG_LIMIT_DATA_SHARING
属性を渡すことで、単一のイベントまたはカスタム収益呼び出しに対して、グローバルな
limitDataSharing
設定を上書きできます。これは、ユーザーがアクションと同時に同意を更新し、後続のイベントに対する SDK 全体の設定を変更することなく、その特定のイベントに新しい選択を即座に反映させたい場合に役立ちます。
許容値:
- NO (false): このイベントに限ってユーザーがオプトイン
- YES (true): このイベントに限ってユーザーがオプトアウト
重要:
この属性はブール値である必要があります (Objective-C では
BOOL
、Swift では
Bool
)。ブール値以外の入力は無視され、リクエストはグローバルな
limitDataSharing
設定にフォールバックします。いずれの場合でも、この属性はリクエストが送信される前にイベントの引数から削除されるため、イベントペイロードには表示されません。
使用例
// 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)
// Example 1: Standard event, opt out only for this event
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@YES forKey:ATTRIBUTE_SNG_LIMIT_DATA_SHARING];
[dic setValue:@"12345" forKey:@"order_id"];
[Singular event:@"checkout_completed" withArgs:dic];
// Example 2: Custom revenue, opt in only for this event
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
[attributes setValue:@NO forKey:ATTRIBUTE_SNG_LIMIT_DATA_SHARING];
[attributes setValue:@"premium_monthly" forKey:@"sku"];
[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 はトラッキングを継続するが、同意を特定して記録することはない
// User accepted tracking consent
Singular.trackingOptIn()
// Example: Call after consent dialog
func onUserAcceptedTracking() {
Singular.trackingOptIn()
print("User opted in to tracking")
}
// User accepted tracking consent
[Singular trackingOptIn];
// Example: Call after consent dialog
- (void)onUserAcceptedTracking {
[Singular trackingOptIn];
NSLog(@"User opted in to tracking");
}
トラッキング制御メソッド
stopAllTracking
このデバイスの現在のユーザーに対する SDK のすべてのトラッキング活動を完全に無効化します。
メソッドシグネチャ:
+ (void)stopAllTracking;
重要な警告:
このメソッドは
resumeAllTracking
が呼び出されるまで SDK を恒久的に無効化します。無効化された状態はアプリの再起動後も維持され、プログラムによってのみ元に戻すことができます。
動作:
- 即時適用: すべてのトラッキング、イベント報告、データ収集を即座に停止
- 永続的な状態: アプリを閉じて再度開いた後も無効化された状態が継続
-
自動リセットなし:
再度有効にするには
resumeAllTrackingを明示的に呼び出す必要がある
// User declined all tracking
Singular.stopAllTracking()
// Example: Handle user opt-out
func onUserDeclinedTracking() {
Singular.stopAllTracking()
print("All tracking stopped")
// Optionally store preference
saveUserTrackingPreference(false)
}
// User declined all tracking
[Singular stopAllTracking];
// Example: Handle user opt-out
- (void)onUserDeclinedTracking {
[Singular stopAllTracking];
NSLog(@"All tracking stopped");
// Optionally store preference
[self saveUserTrackingPreference:NO];
}
resumeAllTracking
stopAllTracking
で停止されたトラッキングを再度有効にします。
メソッドシグネチャ:
+ (void)resumeAllTracking;
使用ケース:
- 同意の変更: ユーザーがプライバシー設定を変更し、トラッキングに再度オプトインした
- プライバシー設定: ユーザーがアプリの設定メニューで同意を更新した
- 地域コンプライアンス: ユーザーが規制対象外の地域に移動した場合にトラッキングを再有効化
// 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)
}
// User opted back in to tracking
[Singular resumeAllTracking];
// Example: Handle consent update
- (void)onUserResumedTracking {
[Singular resumeAllTracking];
NSLog(@"Tracking resumed");
// Optionally update stored preference
[self saveUserTrackingPreference:YES];
}
isAllTrackingStopped
現在のユーザーに対してトラッキングが無効化されているかどうかを確認します。
メソッドシグネチャ:
+ (BOOL)isAllTrackingStopped;
戻り値:
-
YES (true):
stopAllTrackingによってトラッキングが現在停止されている - NO (false): トラッキングがアクティブ (停止されていないか、再開された状態)
SDK が初期化されていない場合、それ以前のトラッキング状態に関係なく
NO
を返します。この値を信頼する前に、
+start:
が完了したことを必ず確認し、
NO
を「アクティブにトラッキング中」ではなく「停止されていない、またはまだ初期化されていない」と解釈してください。
// 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")")
}
// Check current tracking status
BOOL isTrackingStopped = [Singular isAllTrackingStopped];
// Example: Display privacy status in settings
- (NSString *)getPrivacyStatusText {
return [Singular isAllTrackingStopped] ? @"Tracking: Disabled" : @"Tracking: Enabled";
}
// Example: Sync UI with tracking state
- (void)updatePrivacyToggle {
BOOL isStopped = [Singular isAllTrackingStopped];
self.privacyToggle.on = !isStopped;
NSLog(@"Current tracking state: %@", isStopped ? @"Stopped" : @"Active");
}
児童プライバシー保護
trackingUnder13
COPPA (児童オンラインプライバシー保護法) およびその他の児童プライバシー規制を遵守するために、ユーザーが 13 歳未満であることを Singular に通知します。
メソッドシグネチャ:
+ (void)trackingUnder13;
コンプライアンス要件:
- COPPA 準拠: 米国で 13 歳未満の児童からデータを収集するアプリで必須
- 年齢制限コンテンツ: 登録または年齢確認時にユーザーが 13 歳未満として識別された場合に使用
- トラッキングの制限: 児童プライバシー保護法を遵守するためにデータ収集を制限
// 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")
}
}
// User identified as under 13
[Singular trackingUnder13];
// Example: Call after age verification
- (void)onAgeVerified:(int)userAge {
if (userAge < 13) {
[Singular trackingUnder13];
NSLog(@"COPPA mode enabled for user under 13");
}
}
重要: ユーザーが 13 歳未満であると判明したら、できるだけ早くこのメソッドを呼び出してください。理想的にはアプリの初期化時、または年齢確認の直後が望ましいです。これにより、それ以降のすべてのトラッキングが児童プライバシー規制を遵守するようになります。
limitAdvertisingIdentifiers
混合オーディエンスアプリの場合、SDK 初期化時に広告識別子 (iOS の IDFA) の収集と使用を制限します。
構成プロパティ:
@property (assign) BOOL limitAdvertisingIdentifiers;
使用ケース:
- 混合オーディエンスアプリ: アプリ起動前に年齢が決定される、成人と児童の両方を対象とするアプリ
- 既知の COPPA ユーザー: 初期化時点でユーザーが 13 歳未満であることが分かっている場合
- プライバシーファーストのアプローチ: 最初の SDK セッションから広告識別子の制限を適用
構成メソッド
プライバシー要件を事前に把握しているアプリの場合、SDK 初期化時に広告識別子の制限を設定します。
// Limit advertising identifiers at initialization
let config = SingularConfig(apiKey: "SDK_KEY", andSecret: "SDK_SECRET")
config?.limitAdvertisingIdentifiers = true
Singular.start(config)
// Limit advertising identifiers at initialization
SingularConfig *config = [[SingularConfig alloc]
initWithApiKey:@"SDK_KEY"
andSecret:@"SDK_SECRET"];
config.limitAdvertisingIdentifiers = YES;
[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;
// Apply identifier limit after the user enters kids mode
func onKidsModeSwitched(isKidsMode: Bool) {
Singular.setLimitAdvertisingIdentifiers(isKidsMode)
}
// Apply identifier limit after the user enters kids mode
- (void)onKidsModeSwitched:(BOOL)isKidsMode {
[Singular setLimitAdvertisingIdentifiers:isKidsMode];
}
ランタイムメソッドにも
BOOL
引数が必要です —
+setLimitAdvertisingIdentifiers
を引数なしで呼び出すとコンパイルされません。構成時プロパティと同様に、このメソッドは Kids SDK ビルドでは使用できません。
ベストプラクティス:
包括的な COPPA 準拠を実現するには、初期化時に
limitAdvertisingIdentifiers
を使用し、ユーザーの年齢が確認された時点で
trackingUnder13()
を呼び出してください。これにより、最初のセッションから完全な保護が確保されます。
実装のベストプラクティス
完全なプライバシー管理の例
ユーザーの選好を尊重し、規制を遵守する包括的なプライバシー制御を実装します。
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)
}
}
#import <Foundation/Foundation.h>
#import <Singular/Singular.h>
@interface PrivacyManager : NSObject
- (void)initializePrivacy;
- (void)userAcceptedTracking;
- (void)userDeclinedTracking;
- (void)setDataSharingEnabled:(BOOL)enabled;
- (BOOL)isTrackingEnabled;
@end
@implementation PrivacyManager
static NSString *const kConsentKey = @"user_consent";
static NSString *const kDataSharingKey = @"data_sharing";
// Initialize privacy settings on app start
- (void)initializePrivacy {
BOOL hasUserConsent = [self getUserConsent];
BOOL allowDataSharing = [self getDataSharingPreference];
// Apply stored preferences
if (hasUserConsent) {
[Singular trackingOptIn];
[Singular resumeAllTracking];
} else {
[Singular stopAllTracking];
}
// Set data sharing preference
[Singular limitDataSharing:!allowDataSharing];
NSLog(@"Privacy initialized: consent=%d, sharing=%d", hasUserConsent, allowDataSharing);
}
// User accepts tracking via consent dialog
- (void)userAcceptedTracking {
[self saveUserConsent:YES];
[Singular trackingOptIn];
[Singular resumeAllTracking];
NSLog(@"User accepted tracking");
}
// User declines tracking
- (void)userDeclinedTracking {
[self saveUserConsent:NO];
[Singular stopAllTracking];
NSLog(@"User declined tracking");
}
// User updates data sharing preference
- (void)setDataSharingEnabled:(BOOL)enabled {
[self saveDataSharingPreference:enabled];
// Note: limitDataSharing uses inverse logic
[Singular limitDataSharing:!enabled];
NSLog(@"Data sharing: %@", enabled ? @"Enabled" : @"Limited");
}
// Get current tracking status
- (BOOL)isTrackingEnabled {
return ![Singular isAllTrackingStopped];
}
// Private helper methods
- (BOOL)getUserConsent {
return [[NSUserDefaults standardUserDefaults] boolForKey:kConsentKey];
}
- (void)saveUserConsent:(BOOL)consent {
[[NSUserDefaults standardUserDefaults] setBool:consent forKey:kConsentKey];
}
- (BOOL)getDataSharingPreference {
return [[NSUserDefaults standardUserDefaults] boolForKey:kDataSharingKey];
}
- (void)saveDataSharingPreference:(BOOL)enabled {
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kDataSharingKey];
}
@end
ベストプラクティス:
- 永続的なストレージ: ユーザー設定を UserDefaults またはセキュアなストレージに保存
- 早期の初期化: 可能であれば SDK 初期化前にプライバシー設定を適用
-
UI 同期:
isAllTrackingStoppedを使用して設定 UI と実際の SDK 状態を同期 - 明確なコミュニケーション: アプリ設定で明確でアクセスしやすいプライバシー制御を提供
- コンプライアンス文書: 規制監査に向けたプライバシー実装の明確な記録を維持