Privacy: Scripting

This section provides a guide to work with the Privacy module scripting API.

App Tracking Transparency

To show the ATT popup on iOS 14 or newer, simply call the RequestTrackingAuthorization method as shown in the following example. Once the popup has been shown and the user has responded, a callback will be invoked with a status indicating whether user authorized or denied the access to their privacy data.

On iOS older than 14, no popup will be shown and the callback will be invoked immediately with a result ATTrackingManagerAuthorizationStatusAuthorized because IDFA access is always available on those systems as if authorized by the user.

On Android and other non-supported platforms, no popup will be shown and the callback will be invoked immediately with the result ATTrackingManagerAuthorizationStatusNotDetermined.

using UnityEngine;
using EasyMobile;

// Show the ATT popup on iOS 14 or newer.
public void ShowRequestTrackingAuthorizationPopup()
{
    Privacy.AppTrackingManager.RequestTrackingAuthorization(status =>
    {
        NativeUI.Alert("Request Tracking Completed", "Tracking authorization request completed with result: " + status.ToString());
    });
}

You can also query the tracking authorization status later via the TrackingAuthorizationStatus property.

using UnityEngine;
using EasyMobile;

// Get the current tracking authorization status.
public AppTrackingAuthorizationStatus GetTrackingAuthorizationStatus()
{
    return Privacy.AppTrackingManager.TrackingAuthorizationStatus;
}

EEA Region Checking

Easy Mobile provides a built-in validator to detect whether the current device is in the European Economic Area (EEA) region, where the GDPR governs. This validator performs the region check using the methods defined in the EEARegionValidationMethods enum (see Introduction chapter for a detailed explanation of these methods): GoogleService, Telephony, Timezone or Locale. It will return one of the following results: InEEA, NotInEEA or Unknown.

The validator can use any subset of the available methods, in any order. To instruct it to use a certain collection of methods in a specific order, simply prepare a List object containing the methods-to-use in the desired order. The validator will perform validating using the provided methods in their order in the containing list. If a method fails to return an explicit result (either InEEA or NotInEEA), the next one in the list will be used until a clear result is found. If all methods fail, the validator will return Unknown as the result.

Validating Using Default Method List

The default EEA region validating method list is defined as the DefaultMethods variable of the EEARegionValidator class. It employs all the available methods in the following order:

  1. GoogleService
  2. Telephony
  3. Timezone
  4. Locale

To perform EEA region validation using the default method list, call the IsInEEARegion method of the Privacy class. This method is actually a wrapper of the ValidateEEARegionStatus method of the EEARegionValidator class so you can also use that method directly.

using UnityEngine;
using EasyMobile;

public static class ExampleEEARegionDetector
{
    // Checks if we're in EEA region.
    public static void Check()
    {
        // You can use the method of the Privacy class.
        Privacy.IsInEEARegion(CheckEEARegionCallback);

        // You can also do this.
        // EEARegionValidator.ValidateEEARegionStatus(CheckEEARegionCallback);
    }

    // Callback to be invoked when the validation completes.
    static void CheckEEARegionCallback(EEARegionStatus result)
    {
        if (result == EEARegionStatus.InEEA)
            Debug.Log("We're in EEA region!");
        else if (result == EEARegionStatus.NotInEEA)
            Debug.Log("We're not in EEA region!");
        else
            Debug.Log("Result is Unknown: couldn't determine if we're in EEA region or not.");
    }
}

Validating Using Custom Method List

You can instruct the validator to use a custom list of desired methods in the desired order. To do so use the ValidateEEARegionStatus method of the EEARegionValidator class but provide it your custom method list.

using UnityEngine;
using EasyMobile;
using System.Collections.Generic;

public static class ExampleEEARegionDetector
{
    // Checks if we're in EEA region using custom method list.
    public static void CheckWithCustomMethodList()
    {
        // First create a custom list of methods in the preferred order.
        var methodList = new List<EEARegionValidationMethods>()
            {
                EEARegionValidationMethods.Telephony,
                EEARegionValidationMethods.GoogleService,
                EEARegionValidationMethods.Locale,
                EEARegionValidationMethods.Timezone
            };

        // Validates using the custom method list.
        EEARegionValidator.ValidateEEARegionStatus(CheckEEARegionCallback, methodList);
    }

    // Callback to be invoked when the validation completes.
    static void CheckEEARegionCallback(EEARegionStatus result)
    {
        if (result == EEARegionStatus.InEEA)
            Debug.Log("We're in EEA region!");
        else if (result == EEARegionStatus.NotInEEA)
            Debug.Log("We're not in EEA region!");
        else
            Debug.Log("Result is Unknown: couldn't determine if we're in EEA region or not.");
    }
}

You can get the default consent dialog that was composed using the built-in composer (see Consent Dialog Composer) using the GetDefaultConsentDialog method of the Privacy class.

ConsentDialog dialog = Privacy.GetDefaultConsentDialog();

You can localize the main content of the consent dialog by grabbing its Content property and replace the placeholder texts with the appropriate localized texts.

// Replace placeholder texts in main content with localized texts. 
// You may need to repeat this multiple times to replace all placeholders.
ddialog.Content = dialog.Content.Replace("PLACEHOLDER_TEXT", "LOCALIZED_TEXT");

To localize toggles in the dialog you can iterate through the Toggles property and localize the title and the description texts of each toggle.

// Iterate through all toggles in the dialog and localize them.
foreach (ConsentDialog.Toggle toggle in dialog.Toggles)
{
    // Localize the toggle title.
    toggle.Title = toggle.Title.Replace("PLACEHOLDER_TOGGLE_TITLE", "LOCALIZED_TOGGLE_TITLE");

    // Localize the toggle on description.
    toggle.OnDescription = toggle.OnDescription.Replace("PLACEHOLDER_ON_DESCRIPTION", "LOCALIZED_ON_DESCRIPTION");

    // Localize the toggle off description if needed.
    toggle.OffDescription = toggle.OffDescription.Replace("PLACEHOLDER_OFF_DESCRIPTION", "LOCALIZED_OFF_DESCRIPTION");
}

To localize buttons in the dialog you can iterate through the ActionButtons property and localize each button title.

// Iterate through all buttons in the dialog and localize them.
foreach (ConsentDialog.Button button in dialog.ActionButtons)
{
    // Localize the button text.
    button.Title = button.Title.Replace("PLACEHOLDER_BUTTON_TITLE", "LOCALIZED_BUTTON_TITLE");
}

For the sake of simplicity, we use sample strings in the above example snippets. In a practical app you may use a dedicated localization tool, as well as checking toggle or button ID, to pick the correct translation for each placeholder text.

To show a consent dialog simply call its Show method. This method has an optional 'dismissible' parameter. You can set it to 'true' to allow the user to dismiss the dialog using a cancel button that is added to the dialog automatically. Otherwise the dialog can only be closed by one of the buttons in its content.

// Shows the dialog and don't allow the user to dismiss it (must provide explicit consent).
dialog.Show(false);

Only one consent dialog can be shown at a time. Attempts to show a consent dialog when another is being shown will be ignored. You can check if there's any consent dialog being shown using the IsShowingAnyDialog method.

// Checks if any consent dialog is being shown.
bool isShowingAnotherDialog = ConsentDialog.IsShowingAnyDialog();

A consent dialog has following events:

Event Description
ToggleStateUpdated This event is raised when the value of a toggle in the (being shown) consent dialog has been updated. You may subscribe to this event if you want to update the dialog according to the values of its toggles.
Dismissed This event is raised when the dialog is dismissed (closed by the cancel button)
Completed This event is raised when the dialog is completed (close by one of the action buttons). The handler of this event will be called with the ID of the selected button and the values of the toggles in the dialog at the time it is closed.

Updating Toggles in Runtime

You can update the toggle value of a being-shown consent dialog using the SetToggleIsOn method on the dialog.

dialog.SetToggleIsOn("TOGGLE_ID", true); // turn the toggle on

You can also change the interactability of a toggle while the dialog is being shown using the SetToggleInteractable method.

dialog.SetToggleInteractable("TOGGLE_ID", false);   // make the toggle un-clickable

Updating Buttons in Runtime

In some cases, you may want to update the interactability of a button on a being-shown consent dialog, e.g. only make the button clickable if a certain toggle is on. For that purpose you can use the SetButtonInteractable method.

dialog.SetButtonInteractable("BUTTON_ID", true);    // make the button clickable

A Complete Example

The following script gives an example on how to grab the default consent dialog, localize and show it, as well as handle its events.

using UnityEngine;
using EasyMobile;
using System.Collections.Generic;

public static class ExampleConsentDialogDisplayer
{
    static bool hasSubscribedEvents = false;

    // Grabs the default consent dialog, localizes and then shows it.
    public static void ShowDefaultConsentDialog()
    {
        // Grab the default consent dialog that was built with the composer.
        ConsentDialog dialog = Privacy.GetDefaultConsentDialog();

        // Replace placeholder texts in main content with localized texts. 
        // You may need to repeat this multiple times to replace all placeholders.
        dialog.Content = dialog.Content.Replace("PLACEHOLDER_TEXT", "LOCALIZED_TEXT");

        // Iterate through all toggles in the dialog and localize them.
        foreach (ConsentDialog.Toggle toggle in dialog.Toggles)
        {
            // Localize the toggle title.
            toggle.Title = toggle.Title.Replace("PLACEHOLDER_TOGGLE_TITLE", "LOCALIZED_TOGGLE_TITLE");

            // Localize the toggle on description.
            toggle.OnDescription = toggle.OnDescription.Replace("PLACEHOLDER_ON_DESCRIPTION", "LOCALIZED_ON_DESCRIPTION");

            // Localize the toggle off description if needed.
            toggle.OffDescription = toggle.OffDescription.Replace("PLACEHOLDER_OFF_DESCRIPTION", "LOCALIZED_OFF_DESCRIPTION");

            // Here you can also set the toggle value according to the
            // stored consent (if any) to reflect the current consent status.
            // toggle.IsOn = TRUE_OR_FALSE; 
        }

        // Iterate through all buttons in the dialog and localize them.
        foreach (ConsentDialog.Button button in dialog.ActionButtons)
        {
            // Localize the button text.
            button.Title = button.Title.Replace("PLACEHOLDER_BUTTON_TITLE", "LOCALIZED_BUTTON_TITLE");
        }

        // Show the default consent dialog. If you want to allow the user to dismiss the dialog
        // without updating their consent, pass 'true' to the 'dismissible' argument. Otherwise
        // the dialog can only be closed with one of the action buttons.
        if (!ConsentDialog.IsShowingAnyDialog())
        {
            // Subscribe to the default consent dialog events.
            // Only do this once.
            if (!hasSubscribedEvents)
            {
                dialog.ToggleStateUpdated += DefaultDialog_ToggleStateUpdated;
                dialog.Dismissed += DefaultDialog_Dismissed;
                dialog.Completed += DefaultDialog_Completed;
                hasSubscribedEvents = true;
            }

            // Now shows the dialog and don't allow the user to dismiss it (must provide explicit consent).
            dialog.Show(false);
        }
        else
        {
            Debug.Log("Another consent dialog is being shown!");
        }
    }

    // Event handler to be invoked when the value of a toggle in the consent dialog is updated.
    static void DefaultDialog_ToggleStateUpdated(ConsentDialog dialog, string toggleId, bool isOn)
    {
        Debug.Log("Toggle with ID " + toggleId + " now has value " + isOn);

        // If there's a service mandatory to the operation of your app,
        // you may disable all buttons until the toggle associated with that service
        // is turn on, so that the user can only close the dialog once they grant consent to that service.
        if (toggleId.Equals("MANDATORY_TOGGLE"))
            dialog.SetButtonInteractable("SOME_BUTTON_ID", true);   // make the button clickable
    }


    // Event handler to be invoked when the consent dialog is dismissed.
    static void DefaultDialog_Dismissed(ConsentDialog dialog)
    {
        Debug.Log("The consent dialog has been dismissed!");
    }

    // Event handler to be invoked when the consent dialog completed.
    static void DefaultDialog_Completed(ConsentDialog dialog, ConsentDialog.CompletedResults results)
    {
        // The 'results' argument contains the ID of clicked button.
        Debug.Log("The consent dialog has completed with button ID " + results.buttonId);

        // The 'results' argument also returns the values of the toggles in the dialog.
        foreach (KeyValuePair<string, bool> kvp in results.toggleValues)
        {
            Debug.Log("Toggle with ID " + kvp.Key + " has value " + kvp.Value);

            // Here you can perform relevant actions, e.g. update the consent
            // for individual services according to the toggle value...
        }
    }
}

Apart from building consent dialog using the graphical composer, you can construct a dialog completely from script, using methods such as AppendText, AppendToggle and AppendButton to add texts, toggles and buttons to the dialog content, respectively. The following example shows how a consent dialog can be constructed programmatically.

For the sake of simplicity we use sample hard-coded strings in the example script. In a practical app you may use a localization tool to pick the correct translation for each text. Also you can load the consent provided by the user previously and set the toggle values accordingly to reflect the current consent status.

using UnityEngine;
using EasyMobile;
using System.Collections.Generic;

public static class ExampleConsentDialogDisplayer
{
    // Constructs a consent dialog from script.
    public static ConsentDialog ConstructConsentDialog()
    {
        // First create a new consent dialog.
        ConsentDialog dialog = new ConsentDialog();

        // Set the title.
        dialog.Title = "SOME_CONSENT_DIALOG_TITLE";

        // Add the first paragraph.
        dialog.AppendText("FIRST_PARAGRAPH_TEXT");

        // Build and append the toggle for advertising service consent.
        ConsentDialog.Toggle adsToggle = new ConsentDialog.Toggle("ADS_TOGGLE_ID");
        adsToggle.Title = "ADS_TOGGLE_TITLE";
        adsToggle.OnDescription = "ADS_TOGGLE_ON_DESCRIPTION";
        adsToggle.OffDescription = "ADS_TOGGLE_OFF_DESCRIPTION";
        adsToggle.ShouldToggleDescription = true;   // make the description change with the toggle state.
        adsToggle.IsOn = false;     // make the toggle off by default

        // Append the toggle after the 1st paragraph.
        dialog.AppendToggle(adsToggle);

        // Build and append the toggle for notifications service consent.
        ConsentDialog.Toggle notifsToggle = new ConsentDialog.Toggle("NOTIFS_TOGGLE_ID");
        notifsToggle.Title = "NOTIFS_TOGGLE_TITLE";
        notifsToggle.OnDescription = "NOTIFS_TOGGLE_ON_DESCRIPTION";
        notifsToggle.ShouldToggleDescription = false;   // use same description for both on & off states.
        notifsToggle.IsOn = false; // make the toggle off by default

        // Append the toggle below the previous toggle.
        dialog.AppendToggle(notifsToggle);

        // Build and append the toggle for analytics service consent.
        ConsentDialog.Toggle uaToggle = new ConsentDialog.Toggle("ANALYTICS_TOGGLE_ID");
        uaToggle.Title = "ANALYTICS_TOGGLE_TITLE";
        uaToggle.OnDescription = "ANALYTICS_TOGGLE_ON_DESCRIPTION";
        uaToggle.ShouldToggleDescription = false;   // the description won't change when the toggle switches between on & off states.
        uaToggle.IsInteractable = false; // not interactable
        uaToggle.IsOn = true;   // assuming analytics is vital to our app, make its toggle on by default

        // Append the toggle below the previous toggle.
        dialog.AppendToggle(uaToggle);

        // Append the second paragraph.
        dialog.AppendText("SECOND_PARAGRAPH_TEXT");

        // Build and append the accept button.
        // A consent dialog should always have at least one button!
        ConsentDialog.Button okButton = new ConsentDialog.Button("OK_BUTTON_ID");
        okButton.Title = "OK_BUTTON_TITLE";
        okButton.TitleColor = Color.white;
        okButton.BodyColor = new Color(66 / 255f, 179 / 255f, 1);

        // Append the button to the bottom of the dialog.
        dialog.AppendButton(okButton);

        return dialog;
    }
}

You can grant or revoke the global consent of your app using the GrantGlobalDataPrivacyConsent and RevokeGlobalDataPrivacyConsent methods of the Privacy class, respectively.

// Grants global consent.
Privacy.GrantGlobalDataPrivacyConsent();

// Revokes global consent.
Privacy.RevokeGlobalDataPrivacyConsent();

You can get the current state of the global consent of your app using the GlobalDataPrivacyConsent property of the Privacy class.

// Gets current global consent.
ConsentStatus globalConsent = Privacy.GlobalDataPrivacyConsent;

These APIs of the Privacy class are actually wrapper of those of the GlobalConsentManager, which is the object that actually manages the global consent. So the above snippets are equivalent to the following script.

// Grants global consent.
GlobalConsentManager.Instance.GrantDataPrivacyConsent();

// Revokes global consent.
GlobalConsentManager.Instance.RevokeDataPrivacyConsent();

// Gets current global consent.
ConsentStatus globalConsent = GlobalConsentManager.Instance.DataPrivacyConsent;

You can also acknowledge when the global consent is updated by subscribing to the DataPrivacyConsentUpdated event.

using UnityEngine;
using EasyMobile;

public class ExampleConsentClass : MonoBehaviour
{
    void OnEnable()
    {
        // Subscribe.
        GlobalConsentManager.Instance.DataPrivacyConsentUpdated += OnGlobalDataPrivacyConsentUpdated;
    }

    void OnDisable()
    {
        // Unsubscribe.
        GlobalConsentManager.Instance.DataPrivacyConsentUpdated -= OnGlobalDataPrivacyConsentUpdated;
    }

    void OnGlobalDataPrivacyConsentUpdated(ConsentStatus consent)
    {
        if (consent == ConsentStatus.Granted)
            Debug.Log("Global consent has been granted!");
        else if (consent == ConsentStatus.Revoked)
            Debug.Log("Global consent has been revoked!");
        else
            Debug.Log("Global consent is unknown.");
    }
}

results matching ""

    No results matching ""