データプライバシー法の遵守
GDPR、CCPA、その他の消費者プライバシー規制におけるユーザーの同意の選択を Singular に通知することで、プライバシーに準拠したデータ収集を実装します。
ユーザーが第三者との情報共有に同意または拒否した場合、Singular のプライバシーメソッドを使用してその選択を伝達します。これにより、 California Consumer Privacy Act (CCPA) などの規制を遵守し、パートナーがユーザーのプライバシー設定を尊重できるようになります。
詳しく見る: Singular がプライバシー同意をどのように処理するかの詳細については、 ユーザープライバシーとデータ共有の制限 を参照してください。
データ共有の制限
第三者へのデータ共有の制御
ユーザーが第三者パートナーと個人データを共有することに同意したかどうかを、
limitDataSharing
メソッドを使用して Singular に通知します。
メソッドシグネチャ:
public static void limitDataSharing(boolean shouldLimitDataSharing);
パラメーター:
- false: ユーザーがオプトインし、データの共有に同意した
- 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
fun handlePrivacyConsent(userConsented: Boolean) {
// Pass inverse: false = opted in, true = opted out
Singular.limitDataSharing(!userConsented)
Log.d("Privacy", "Data sharing: ${if (userConsented) "Enabled" else "Limited"}")
}
// 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
public void handlePrivacyConsent(boolean userConsented) {
// Pass inverse: false = opted in, true = opted out
Singular.limitDataSharing(!userConsented);
Log.d("Privacy", "Data sharing: " + (userConsented ? "Enabled" : "Limited"));
}
動作の仕組み:
Singular はこの設定を ユーザープライバシーポストバック で使用し、規制遵守のためにこれを必要とするパートナーに渡します。
イベント単位のデータ共有制限
単一イベントのデータ共有を上書き
他のイベント引数とともに
Attributes.sngAttrLimitDataSharing
属性を渡すことで、単一のイベントまたはカスタム収益呼び出しに対して、グローバルな
limitDataSharing
設定を上書きできます。これは、ユーザーがアクションと同時に同意を更新し、後続のイベントに対する SDK 全体の設定を変更することなく、その特定のイベントに新しい選択を即座に反映させたい場合に役立ちます。
許容値:
- false: このイベントに限ってユーザーがオプトイン
- true: このイベントに限ってユーザーがオプトアウト
重要:
この属性は
Boolean
である必要があります。ブール値以外の入力は無視され、リクエストはグローバルな
limitDataSharing
設定にフォールバックします。いずれの場合でも、この属性はリクエストが送信される前にイベントの引数から削除されるため、イベントペイロードには表示されません。
使用例
// Example 1: Standard event, opt out only for this event
val args = JSONObject()
.put(Attributes.sngAttrLimitDataSharing.toString(), true)
.put("order_id", "12345")
Singular.event("checkout_completed", args.toString())
// Example 2: Custom revenue, opt in only for this event
val attributes = mutableMapOf<String, Any>().apply {
put(Attributes.sngAttrLimitDataSharing.toString(), false)
put("sku", "premium_monthly")
}
Singular.customRevenue("premium_purchase", "USD", 9.99, attributes)
// Example 1: Standard event, opt out only for this event
JSONObject args = new JSONObject();
args.put(Attributes.sngAttrLimitDataSharing.toString(), true);
args.put("order_id", "12345");
Singular.event("checkout_completed", args.toString());
// Example 2: Custom revenue, opt in only for this event
Map<String, Object> attributes = new HashMap<>();
attributes.put(Attributes.sngAttrLimitDataSharing.toString(), false);
attributes.put("sku", "premium_monthly");
Singular.customRevenue("premium_purchase", "USD", 9.99, attributes);
動作の仕組み:
有効なブール値が指定されると、SDK は該当属性をイベント引数から削除し、リクエストの
data_sharing_options.limit_data_sharing
フィールドに書き込みます — これにより、その単一リクエストに限ってグローバルな
limitDataSharing
設定が上書きされます。グローバル設定と
getLimitDataSharing
の結果は変更されないため、属性を指定しない後続のイベントは引き続きグローバルな選択を使用します。
GDPR 準拠メソッド
GDPR (一般データ保護規則) およびその他のプライバシー規制を遵守するために、ユーザートラッキング同意を管理し SDK 機能を制御します。
トラッキング同意管理
trackingOptIn
GDPR オプトインイベントを Singular サーバーに送信して、ユーザーのトラッキング同意を明示的に記録します。
メソッドシグネチャ:
Singular.trackingOptIn()
使用するタイミング:
- GDPR 準拠: GDPR 規制地域でユーザーがトラッキングに明示的に同意したときに呼び出す
- 同意の記録: Singular のシステム内で、ユーザーが GDPR 同意を提供したものとしてマーク
- デフォルトの動作: この呼び出しがなくても SDK はトラッキングを継続するが、同意を特定して記録することはない
// User accepted tracking consent
Singular.trackingOptIn()
// Example: Call after consent dialog
fun onUserAcceptedTracking() {
Singular.trackingOptIn()
Log.d("GDPR", "User opted in to tracking")
}
// User accepted tracking consent
Singular.trackingOptIn();
// Example: Call after consent dialog
public void onUserAcceptedTracking() {
Singular.trackingOptIn();
Log.d("GDPR", "User opted in to tracking");
}
トラッキング制御メソッド
stopAllTracking
このデバイスの現在のユーザーに対する SDK のすべてのトラッキング活動を完全に無効化します。
メソッドシグネチャ:
Singular.stopAllTracking()
重要な警告:
このメソッドは
resumeAllTracking()
が呼び出されるまで SDK を恒久的に無効化します。無効化された状態はアプリの再起動後も維持され、プログラムによってのみ元に戻すことができます。
動作:
- 即時適用: すべてのトラッキング、イベント報告、データ収集を即座に停止
- 永続的な状態: アプリを閉じて再度開いた後も無効化された状態が継続
-
自動リセットなし:
再度有効にするには
resumeAllTracking()を明示的に呼び出す必要がある
// User declined all tracking
Singular.stopAllTracking()
// Example: Handle user opt-out
fun onUserDeclinedTracking() {
Singular.stopAllTracking()
Log.d("Privacy", "All tracking stopped")
// Optionally store preference
saveUserTrackingPreference(false)
}
// User declined all tracking
Singular.stopAllTracking();
// Example: Handle user opt-out
public void onUserDeclinedTracking() {
Singular.stopAllTracking();
Log.d("Privacy", "All tracking stopped");
// Optionally store preference
saveUserTrackingPreference(false);
}
resumeAllTracking
stopAllTracking()
で停止されたトラッキングを再度有効にします。
メソッドシグネチャ:
Singular.resumeAllTracking()
使用ケース:
- 同意の変更: ユーザーがプライバシー設定を変更し、トラッキングに再度オプトインした
- プライバシー設定: ユーザーがアプリの設定メニューで同意を更新した
- 地域コンプライアンス: ユーザーが規制対象外の地域に移動した場合にトラッキングを再有効化
// User opted back in to tracking
Singular.resumeAllTracking()
// Example: Handle consent update
fun onUserResumedTracking() {
Singular.resumeAllTracking()
Log.d("Privacy", "Tracking resumed")
// Optionally update stored preference
saveUserTrackingPreference(true)
}
// User opted back in to tracking
Singular.resumeAllTracking();
// Example: Handle consent update
public void onUserResumedTracking() {
Singular.resumeAllTracking();
Log.d("Privacy", "Tracking resumed");
// Optionally update stored preference
saveUserTrackingPreference(true);
}
isAllTrackingStopped
現在のユーザーに対してトラッキングが無効化されているかどうかを確認します。
メソッドシグネチャ:
public static boolean isAllTrackingStopped();
戻り値:
-
true:
stopAllTracking()によってトラッキングが現在停止されている - false: トラッキングがアクティブ (停止されていないか、再開された状態)
SDK が初期化されていない場合、それ以前のトラッキング状態に関係なく
false
を返します。この値を信頼する前に、
Singular.init()
が完了したことを必ず確認し、
false
を「アクティブにトラッキング中」ではなく「停止されていない、またはまだ初期化されていない」と解釈してください。
// Check current tracking status
val isTrackingStopped = Singular.isAllTrackingStopped()
// Example: Display privacy status in settings
fun getPrivacyStatusText(): String {
return if (Singular.isAllTrackingStopped()) {
"Tracking: Disabled"
} else {
"Tracking: Enabled"
}
}
// Example: Sync UI with tracking state
fun updatePrivacyToggle() {
val isStopped = Singular.isAllTrackingStopped()
privacyToggle.isChecked = !isStopped
Log.d("Privacy", "Current tracking state: ${if (isStopped) "Stopped" else "Active"}")
}
// Check current tracking status
boolean isTrackingStopped = Singular.isAllTrackingStopped();
// Example: Display privacy status in settings
public String getPrivacyStatusText() {
if (Singular.isAllTrackingStopped()) {
return "Tracking: Disabled";
} else {
return "Tracking: Enabled";
}
}
// Example: Sync UI with tracking state
public void updatePrivacyToggle() {
boolean isStopped = Singular.isAllTrackingStopped();
privacyToggle.setChecked(!isStopped);
Log.d("Privacy", "Current tracking state: " + (isStopped ? "Stopped" : "Active"));
}
児童プライバシー保護
trackingUnder13
COPPA (児童オンラインプライバシー保護法) およびその他の児童プライバシー規制を遵守するために、ユーザーが 13 歳未満であることを Singular に通知します。
メソッドシグネチャ:
Singular.trackingUnder13()
コンプライアンス要件:
- COPPA 準拠: 米国で 13 歳未満の児童からデータを収集するアプリで必須
- 年齢制限コンテンツ: 登録または年齢確認時にユーザーが 13 歳未満として識別された場合に使用
- トラッキングの制限: 児童プライバシー保護法を遵守するためにデータ収集を制限
// User identified as under 13
Singular.trackingUnder13()
// Example: Call after age verification
fun onAgeVerified(userAge: Int) {
if (userAge < 13) {
Singular.trackingUnder13()
Log.d("Privacy", "COPPA mode enabled for user under 13")
}
}
// User identified as under 13
Singular.trackingUnder13();
// Example: Call after age verification
public void onAgeVerified(int userAge) {
if (userAge < 13) {
Singular.trackingUnder13();
Log.d("Privacy", "COPPA mode enabled for user under 13");
}
}
重要: ユーザーが 13 歳未満であると判明したら、できるだけ早くこのメソッドを呼び出してください。理想的にはアプリの初期化時、または年齢確認の直後が望ましいです。これにより、それ以降のすべてのトラッキングが児童プライバシー規制を遵守するようになります。
setLimitAdvertisingIdentifiers
混合オーディエンスアプリの場合、SDK 初期化後に広告識別子 (Android の GAID) の収集と使用を制限します。
メソッドシグネチャ:
public static void setLimitAdvertisingIdentifiers(boolean enabled);
パラメーター:
-
enabled:
広告識別子の収集を制限するには
trueを渡し、通常の収集に戻すにはfalseを渡します。
構成時のバリアントと混同しないでください。
ランタイムメソッド
Singular.setLimitAdvertisingIdentifiers(boolean)
はブール引数を必要とするのに対し、構成時メソッド
SingularConfig.withLimitAdvertisingIdentifiers()
は引数を取らず、無条件に制限を有効にします。ランタイムメソッドを引数なしで呼び出すとコンパイルされません。
使用ケース:
- 混合オーディエンスアプリ: アプリ起動後に年齢が決定される、成人と児童の両方を対象とするアプリ
- 動的プライバシー制御: ユーザーの行動やアクセスするコンテンツに応じてトラッキングを調整
- ランタイム制限: 初期 SDK 設定後に広告識別子の制限を適用
// Limit advertising identifiers after initialization
Singular.setLimitAdvertisingIdentifiers(true)
// Example: Mixed audience app with age gate
fun onKidsModeSwitched(isKidsMode: Boolean) {
if (isKidsMode) {
Singular.setLimitAdvertisingIdentifiers(true)
Log.d("Privacy", "Advertising identifiers limited for kids mode")
}
}
// Example: Content-based restrictions
fun onViewingChildrensContent() {
Singular.setLimitAdvertisingIdentifiers(true)
Log.d("Privacy", "Ad identifiers restricted for children's content")
}
// Limit advertising identifiers after initialization
Singular.setLimitAdvertisingIdentifiers(true);
// Example: Mixed audience app with age gate
public void onKidsModeSwitched(boolean isKidsMode) {
if (isKidsMode) {
Singular.setLimitAdvertisingIdentifiers(true);
Log.d("Privacy", "Advertising identifiers limited for kids mode");
}
}
// Example: Content-based restrictions
public void onViewingChildrensContent() {
Singular.setLimitAdvertisingIdentifiers(true);
Log.d("Privacy", "Ad identifiers restricted for children's content");
}
構成での代替手段:
SDK 起動前にプライバシー要件を把握している場合は、
SingularConfig.withLimitAdvertisingIdentifiers()
を使用して SDK 初期化時に広告識別子を制限することもできます。
構成メソッド
プライバシー要件を事前に把握しているアプリの場合、SDK 初期化時に広告識別子の制限を設定します。
// Limit advertising identifiers at initialization
val config = SingularConfig("SDK_KEY", "SDK_SECRET")
.withLimitAdvertisingIdentifiers()
Singular.init(applicationContext, config)
// Limit advertising identifiers at initialization
SingularConfig config = new SingularConfig("SDK_KEY", "SDK_SECRET")
.withLimitAdvertisingIdentifiers();
Singular.init(getApplicationContext(), config);
実装のベストプラクティス
完全なプライバシー管理の例
ユーザーの選好を尊重し、規制を遵守する包括的なプライバシー制御を実装します。
class PrivacyManager(private val context: Context) {
private val prefs = context.getSharedPreferences("privacy_prefs", Context.MODE_PRIVATE)
// Initialize privacy settings on app start
fun initializePrivacy() {
val hasUserConsent = getUserConsent()
val allowDataSharing = getDataSharingPreference()
val userAge = getUserAge()
// Apply stored preferences
if (hasUserConsent) {
Singular.trackingOptIn()
Singular.resumeAllTracking()
} else {
Singular.stopAllTracking()
}
// Set data sharing preference
Singular.limitDataSharing(!allowDataSharing)
// Handle children's privacy
if (userAge > 0 && userAge < 13) {
Singular.trackingUnder13()
Singular.setLimitAdvertisingIdentifiers(true)
}
Log.d("Privacy", "Initialized: consent=$hasUserConsent, sharing=$allowDataSharing, age=$userAge")
}
// User accepts tracking via consent dialog
fun userAcceptedTracking() {
saveUserConsent(true)
Singular.trackingOptIn()
Singular.resumeAllTracking()
Log.d("Privacy", "User accepted tracking")
}
// User declines tracking
fun userDeclinedTracking() {
saveUserConsent(false)
Singular.stopAllTracking()
Log.d("Privacy", "User declined tracking")
}
// User updates data sharing preference
fun setDataSharingEnabled(enabled: Boolean) {
saveDataSharingPreference(enabled)
// Note: limitDataSharing uses inverse logic
Singular.limitDataSharing(!enabled)
Log.d("Privacy", "Data sharing: ${if (enabled) "Enabled" else "Limited"}")
}
// Handle age verification result
fun onAgeVerified(age: Int) {
saveUserAge(age)
if (age < 13) {
Singular.trackingUnder13()
Singular.setLimitAdvertisingIdentifiers(true)
Log.d("Privacy", "COPPA restrictions applied for user under 13")
}
}
// Get current tracking status
fun isTrackingEnabled(): Boolean {
return !Singular.isAllTrackingStopped()
}
// Private helper methods
private fun getUserConsent(): Boolean {
return prefs.getBoolean("user_consent", false)
}
private fun saveUserConsent(consent: Boolean) {
prefs.edit().putBoolean("user_consent", consent).apply()
}
private fun getDataSharingPreference(): Boolean {
return prefs.getBoolean("data_sharing", false)
}
private fun saveDataSharingPreference(enabled: Boolean) {
prefs.edit().putBoolean("data_sharing", enabled).apply()
}
private fun getUserAge(): Int {
return prefs.getInt("user_age", 0)
}
private fun saveUserAge(age: Int) {
prefs.edit().putInt("user_age", age).apply()
}
}
public class PrivacyManager {
private Context context;
private SharedPreferences prefs;
public PrivacyManager(Context context) {
this.context = context;
this.prefs = context.getSharedPreferences("privacy_prefs", Context.MODE_PRIVATE);
}
// Initialize privacy settings on app start
public void initializePrivacy() {
boolean hasUserConsent = getUserConsent();
boolean allowDataSharing = getDataSharingPreference();
int userAge = getUserAge();
// Apply stored preferences
if (hasUserConsent) {
Singular.trackingOptIn();
Singular.resumeAllTracking();
} else {
Singular.stopAllTracking();
}
// Set data sharing preference
Singular.limitDataSharing(!allowDataSharing);
// Handle children's privacy
if (userAge > 0 && userAge < 13) {
Singular.trackingUnder13();
Singular.setLimitAdvertisingIdentifiers(true);
}
Log.d("Privacy", "Initialized: consent=" + hasUserConsent + ", sharing=" + allowDataSharing + ", age=" + userAge);
}
// User accepts tracking via consent dialog
public void userAcceptedTracking() {
saveUserConsent(true);
Singular.trackingOptIn();
Singular.resumeAllTracking();
Log.d("Privacy", "User accepted tracking");
}
// User declines tracking
public void userDeclinedTracking() {
saveUserConsent(false);
Singular.stopAllTracking();
Log.d("Privacy", "User declined tracking");
}
// User updates data sharing preference
public void setDataSharingEnabled(boolean enabled) {
saveDataSharingPreference(enabled);
// Note: limitDataSharing uses inverse logic
Singular.limitDataSharing(!enabled);
Log.d("Privacy", "Data sharing: " + (enabled ? "Enabled" : "Limited"));
}
// Handle age verification result
public void onAgeVerified(int age) {
saveUserAge(age);
if (age < 13) {
Singular.trackingUnder13();
Singular.setLimitAdvertisingIdentifiers(true);
Log.d("Privacy", "COPPA restrictions applied for user under 13");
}
}
// Get current tracking status
public boolean isTrackingEnabled() {
return !Singular.isAllTrackingStopped();
}
// Private helper methods
private boolean getUserConsent() {
return prefs.getBoolean("user_consent", false);
}
private void saveUserConsent(boolean consent) {
prefs.edit().putBoolean("user_consent", consent).apply();
}
private boolean getDataSharingPreference() {
return prefs.getBoolean("data_sharing", false);
}
private void saveDataSharingPreference(boolean enabled) {
prefs.edit().putBoolean("data_sharing", enabled).apply();
}
private int getUserAge() {
return prefs.getInt("user_age", 0);
}
private void saveUserAge(int age) {
prefs.edit().putInt("user_age", age).apply();
}
}
ベストプラクティス:
- 永続的なストレージ: ユーザー設定を SharedPreferences またはセキュアなストレージに保存
- 早期の初期化: 可能であれば SDK 初期化前にプライバシー設定を適用
-
UI 同期:
isAllTrackingStopped()を使用して設定 UI と実際の SDK 状態を同期 - 明確なコミュニケーション: アプリ設定で明確でアクセスしやすいプライバシー制御を提供
- 年齢確認: 児童を対象とするアプリには堅牢な年齢確認を実装
-
併用する制御:
13 歳未満のユーザーには
trackingUnder13()とsetLimitAdvertisingIdentifiers(true)の両方を適用