Unity SDK - Data Privacy

Complying with Data Privacy Laws

Implement privacy-compliant data collection by notifying Singular of user consent choices for GDPR, CCPA, and other consumer privacy regulations.

When users consent or decline to share their information with third parties, use Singular's privacy methods to communicate their choice. This ensures compliance with regulations like California Consumer Privacy Act (CCPA) and enables partners to respect user privacy preferences.

Learn More: See User Privacy and Limit Data Sharing for detailed information on how Singular processes privacy consent.


Limit Data Sharing

Control Third-Party Data Sharing

Notify Singular whether users have consented to share their personal data with third-party partners using the LimitDataSharing method.

Method Signature:

SingularSDK.LimitDataSharing(bool shouldLimitDataSharing)

Parameters:

  • false: User has opted in and consented to share their data
  • true: User has opted out and does not consent to share their data

Important: While optional, this method affects attribution data sharing. Some partners only share complete attribution information when explicitly notified that users have opted in.

Usage Examples

C#
using UnityEngine;
using Singular;

public class PrivacyManager : MonoBehaviour
{
    // User has opted in to share their data
    public void OnUserOptedInToDataSharing()
    {
        SingularSDK.LimitDataSharing(false);
        Debug.Log("Data sharing enabled");
    }

    // User has opted out and declined to share their data
    public void OnUserOptedOutOfDataSharing()
    {
        SingularSDK.LimitDataSharing(true);
        Debug.Log("Data sharing limited");
    }

    // Example: Set based on user preference
    public void HandlePrivacyConsent(bool userConsented)
    {
        // Pass inverse: false = opted in, true = opted out
        SingularSDK.LimitDataSharing(!userConsented);

        Debug.Log($"Data sharing: {(userConsented ? "Enabled" : "Limited")}");
    }
}

How It Works:

Singular uses this setting in User Privacy Postbacks and passes it to partners who require it for regulatory compliance.


GDPR Compliance Methods

Manage user tracking consent and control SDK functionality to comply with GDPR (General Data Protection Regulation) and other privacy regulations.

Tracking Consent Management

TrackingOptIn

Record explicit user consent for tracking by sending a GDPR opt-in event to Singular servers.

Method Signature:

SingularSDK.TrackingOptIn()

When to Use:

  • GDPR Compliance: Call when users explicitly consent to tracking in GDPR-regulated regions
  • Consent Recording: Marks users as having provided GDPR consent in Singular's systems
  • Default Behavior: Without this call, SDK continues tracking but doesn't specifically record consent
C#
using UnityEngine;
using Singular;

public class GDPRManager : MonoBehaviour
{
    // User accepted tracking consent
    public void OnUserAcceptedTracking()
    {
        SingularSDK.TrackingOptIn();
        Debug.Log("User opted in to tracking");
    }

    // Example: Call after consent dialog
    public void ShowGDPRConsentDialog()
    {
        // Your consent dialog UI logic here
        // ...

        // If user accepts:
        OnUserAcceptedTracking();
    }
}

Tracking Control Methods

StopAllTracking

Completely disable all SDK tracking activities for the current user on this device.

Method Signature:

SingularSDK.StopAllTracking()

Critical Warning: This method permanently disables the SDK until ResumeAllTracking() is called. The disabled state persists across app restarts and can only be reversed programmatically.

Behavior:

  • Immediate Effect: Stops all tracking, event reporting, and data collection instantly
  • Persistent State: Remains disabled even after app closes and reopens
  • No Automatic Reset: Must explicitly call ResumeAllTracking() to re-enable
C#
using UnityEngine;
using Singular;

public class TrackingController : MonoBehaviour
{
    // User declined all tracking
    public void OnUserDeclinedTracking()
    {
        SingularSDK.StopAllTracking();
        Debug.Log("All tracking stopped");

        // Optionally store preference
        PlayerPrefs.SetInt("tracking_enabled", 0);
        PlayerPrefs.Save();
    }

    // Example: Handle user opt-out from settings menu
    public void HandlePrivacySettingsChange(bool trackingEnabled)
    {
        if (!trackingEnabled)
        {
            SingularSDK.StopAllTracking();
            Debug.Log("Privacy settings: Tracking disabled");
        }
    }
}

ResumeAllTracking

Re-enable tracking after it was stopped with StopAllTracking().

Method Signature:

SingularSDK.ResumeAllTracking()

Use Cases:

  • Consent Change: User changes privacy preferences and opts back into tracking
  • Privacy Settings: User updates consent through app settings menu
  • Regional Compliance: Re-enable tracking when user moves to non-regulated regions
C#
using UnityEngine;
using Singular;

public class TrackingController : MonoBehaviour
{
    // User opted back in to tracking
    public void OnUserResumedTracking()
    {
        SingularSDK.ResumeAllTracking();
        Debug.Log("Tracking resumed");

        // Optionally update stored preference
        PlayerPrefs.SetInt("tracking_enabled", 1);
        PlayerPrefs.Save();
    }

    // Example: Handle consent update from settings
    public void HandlePrivacySettingsChange(bool trackingEnabled)
    {
        if (trackingEnabled)
        {
            SingularSDK.ResumeAllTracking();
            Debug.Log("Privacy settings: Tracking enabled");
        }
    }
}

IsAllTrackingStopped

Check whether tracking has been disabled for the current user.

Method Signature:

bool SingularSDK.IsAllTrackingStopped()

Returns:

  • true: Tracking is currently stopped via StopAllTracking()
  • false: Tracking is active (either never stopped or resumed)
C#
using UnityEngine;
using UnityEngine.UI;
using Singular;

public class PrivacySettingsUI : MonoBehaviour
{
    public Toggle trackingToggle;
    public Text statusText;

    void Start()
    {
        // Check current tracking status on startup
        UpdatePrivacyUI();
    }

    // Check current tracking status
    public bool IsTrackingEnabled()
    {
        return !SingularSDK.IsAllTrackingStopped();
    }

    // Example: Display privacy status in settings
    public string GetPrivacyStatusText()
    {
        if (SingularSDK.IsAllTrackingStopped())
        {
            return "Tracking: Disabled";
        }
        else
        {
            return "Tracking: Enabled";
        }
    }

    // Example: Sync UI with tracking state
    public void UpdatePrivacyUI()
    {
        bool isStopped = SingularSDK.IsAllTrackingStopped();

        if (trackingToggle != null)
        {
            trackingToggle.isOn = !isStopped;
        }

        if (statusText != null)
        {
            statusText.text = GetPrivacyStatusText();
        }

        Debug.Log($"Current tracking state: {(isStopped ? "Stopped" : "Active")}");
    }

    // Handle toggle change from UI
    public void OnTrackingToggleChanged(bool enabled)
    {
        if (enabled)
        {
            SingularSDK.ResumeAllTracking();
        }
        else
        {
            SingularSDK.StopAllTracking();
        }

        UpdatePrivacyUI();
    }
}

Children's Privacy Protection

TrackingUnder13

Notify Singular that the user is under 13 years old to comply with COPPA (Children's Online Privacy Protection Act) and other child privacy regulations.

Method Signature:

SingularSDK.TrackingUnder13()

Compliance Requirements:

  • COPPA Compliance: Required for apps that collect data from children under 13 in the United States
  • Age-Gated Content: Use when users identify themselves as under 13 during registration or age verification
  • Restricted Tracking: Limits data collection to comply with children's privacy protection laws
C#
using UnityEngine;
using Singular;

public class COPPAManager : MonoBehaviour
{
    // User identified as under 13
    public void OnUserUnder13()
    {
        SingularSDK.TrackingUnder13();
        Debug.Log("COPPA mode enabled for user under 13");
    }
    
    // Example: Call after age verification
    public void OnAgeVerified(int userAge)
    {
        if (userAge < 13)
        {
            SingularSDK.TrackingUnder13();
            Debug.Log("COPPA restrictions applied");
            
            // Also limit advertising identifiers
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
        }
    }
}

Important: Call this method as early as possible after determining the user is under 13, ideally during app initialization or immediately after age verification. This ensures all subsequent tracking respects children's privacy regulations.


SetLimitAdvertisingIdentifiers

Restrict the collection and use of advertising identifiers (GAID on Android, IDFA on iOS) after SDK initialization for mixed audience apps.

Method Signature:

SingularSDK.SetLimitAdvertisingIdentifiers(bool isEnabled)

Parameters:

  • true: Enable limited advertising identifiers mode (restrict collection)
  • false: Disable limited advertising identifiers mode (normal collection)

Use Cases:

  • Mixed Audience Apps: Apps that serve both adults and children where age is determined after app launch
  • Dynamic Privacy Controls: Adjust tracking based on user actions or content being accessed
  • Runtime Restrictions: Apply advertising identifier limitations after initial SDK setup
C#
using UnityEngine;
using Singular;

public class AdvertisingIdentifierManager : MonoBehaviour
{
    // Limit advertising identifiers after initialization
    public void EnableLimitedMode()
    {
        SingularSDK.SetLimitAdvertisingIdentifiers(true);
        Debug.Log("Advertising identifiers limited");
    }
    
    // Example: Mixed audience app with age gate
    public void OnKidsModeSwitched(bool isKidsMode)
    {
        if (isKidsMode)
        {
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
            Debug.Log("Advertising identifiers limited for kids mode");
        }
        else
        {
            SingularSDK.SetLimitAdvertisingIdentifiers(false);
            Debug.Log("Advertising identifiers unrestricted for adult mode");
        }
    }
    
    // Example: Content-based restrictions
    public void OnViewingChildrensContent()
    {
        SingularSDK.SetLimitAdvertisingIdentifiers(true);
        Debug.Log("Ad identifiers restricted for children's content");
    }
    
    // Example: Combined with TrackingUnder13
    public void OnAgeVerified(int age)
    {
        if (age < 13)
        {
            SingularSDK.TrackingUnder13();
            SingularSDK.SetLimitAdvertisingIdentifiers(true);
            Debug.Log("Full COPPA restrictions applied");
        }
    }
}

Configuration Alternative: You can also limit advertising identifiers during SDK initialization by setting the limitAdvertisingIdentifiers property in the Singular SDK configuration if you know privacy requirements before the SDK starts.

Configuration Property

Set advertising identifier limitations during SDK initialization for apps that know privacy requirements upfront.

C#
using UnityEngine;
using Singular;

public class SDKInitializer : MonoBehaviour
{
    void Start()
    {
        // Get reference to SingularSDK component
        var singularSDK = GetComponent<SingularSDK>();
        
        // Limit advertising identifiers at initialization
        singularSDK.limitAdvertisingIdentifiers = true;
        
        // Initialize SDK
        if (!singularSDK.InitializeOnAwake)
        {
            SingularSDK.InitializeSingularSDK();
        }
    }
}

Implementation Best Practices

Complete Privacy Management Example

Implement comprehensive privacy controls that respect user preferences and comply with regulations.

C#
using UnityEngine;
using Singular;

public class ComprehensivePrivacyManager : MonoBehaviour
{
    private const string PREF_USER_CONSENT = "privacy_user_consent";
    private const string PREF_DATA_SHARING = "privacy_data_sharing";

    void Start()
    {
        // Initialize privacy settings on app start
        InitializePrivacySettings();
    }

    /// <summary>
    /// Initialize privacy settings on app startup based on stored preferences
    /// </summary>
    public void InitializePrivacySettings()
    {
        bool hasUserConsent = GetUserConsent();
        bool allowDataSharing = GetDataSharingPreference();

        // Apply stored tracking preference
        if (hasUserConsent)
        {
            SingularSDK.TrackingOptIn();
            SingularSDK.ResumeAllTracking();
            Debug.Log("Privacy initialized: Tracking enabled with consent");
        }
        else
        {
            SingularSDK.StopAllTracking();
            Debug.Log("Privacy initialized: Tracking disabled");
        }

        // Set data sharing preference (inverse logic)
        SingularSDK.LimitDataSharing(!allowDataSharing);

        Debug.Log($"Privacy initialized: consent={hasUserConsent}, sharing={allowDataSharing}");
    }

    /// <summary>
    /// User accepts tracking via consent dialog
    /// </summary>
    public void OnUserAcceptedTracking()
    {
        SaveUserConsent(true);

        SingularSDK.TrackingOptIn();
        SingularSDK.ResumeAllTracking();

        Debug.Log("User accepted tracking");
    }

    /// <summary>
    /// User declines tracking
    /// </summary>
    public void OnUserDeclinedTracking()
    {
        SaveUserConsent(false);

        SingularSDK.StopAllTracking();

        Debug.Log("User declined tracking");
    }

    /// <summary>
    /// User updates data sharing preference
    /// </summary>
    /// <param name="enabled">True to enable data sharing, false to limit it</param>
    public void SetDataSharingEnabled(bool enabled)
    {
        SaveDataSharingPreference(enabled);

        // Note: LimitDataSharing uses inverse logic
        // false = data sharing enabled, true = data sharing limited
        SingularSDK.LimitDataSharing(!enabled);

        Debug.Log($"Data sharing: {(enabled ? "Enabled" : "Limited")}");
    }

    /// <summary>
    /// Check if tracking is currently enabled
    /// </summary>
    /// <returns>True if tracking is active, false if stopped</returns>
    public bool IsTrackingEnabled()
    {
        return !SingularSDK.IsAllTrackingStopped();
    }

    /// <summary>
    /// Get current privacy status as readable text
    /// </summary>
    /// <returns>Human-readable tracking status</returns>
    public string GetPrivacyStatus()
    {
        bool isEnabled = !SingularSDK.IsAllTrackingStopped();
        bool dataSharingEnabled = GetDataSharingPreference();

        return $"Tracking: {(isEnabled ? "Enabled" : "Disabled")}\n" +
               $"Data Sharing: {(dataSharingEnabled ? "Enabled" : "Limited")}";
    }

    // Private helper methods for PlayerPrefs storage

    private bool GetUserConsent()
    {
        return PlayerPrefs.GetInt(PREF_USER_CONSENT, 0) == 1;
    }

    private void SaveUserConsent(bool consent)
    {
        PlayerPrefs.SetInt(PREF_USER_CONSENT, consent ? 1 : 0);
        PlayerPrefs.Save();
    }

    private bool GetDataSharingPreference()
    {
        return PlayerPrefs.GetInt(PREF_DATA_SHARING, 0) == 1;
    }

    private void SaveDataSharingPreference(bool enabled)
    {
        PlayerPrefs.SetInt(PREF_DATA_SHARING, enabled ? 1 : 0);
        PlayerPrefs.Save();
    }
}

Best Practices:

  • Persistent Storage: Save user preferences using PlayerPrefs or a secure storage solution
  • Early Initialization: Apply privacy settings before SDK initialization when possible
  • UI Sync: Keep settings UI synchronized with actual SDK state using IsAllTrackingStopped()
  • Clear Communication: Provide clear, accessible privacy controls in app settings
  • Inverse Logic: Remember that LimitDataSharing(false) means data sharing is enabled, while true means it's limited
  • Compliance Documentation: Maintain records of when and how users provide or revoke consent