GDPR Consent Management

GDPR Consent Management

mParticle’s Consent Management framework is designed to give brands the tools they need to manage their consent and privacy obligations under the European Union’s General Data Protection Regulation (GDPR). The framework is not prescriptive and there is no single standard way to implement consent. Instead, mParticle gives you a simple standard format for collecting, storing and applying User Consent. Consent state is stored in the user profile, and can be forwarded to partners or used to control the flow of all data for the user. mParticle’s SDKs can also be configured to respect a user’s consent state when logging data.

This initial guide will introduce you to mParticle’s Consent state object and show you how to collect consent via the HTTP API or our Native SDKs.

GDPR Consent Management is implemented at the level of an mParticle Workspace. At the time you enable GDPR you must also create a set of consent “purposes”. These purposes define the scope of data collection and processing to which the user may consent. GDPR recognizes several different purposes for data collection and covers the possibility of a user consenting to some purposes of data collection but not others. mParticle does not limit you to a specific set of purposes, but rather lets you define your own purposes when you setup a workspace.

You can add purposes from Setup > GDPR Settings in the dashboard. Once a purpose has been added it cannot be removed.

For each user/workspace, consent state can be stored for each possible combination of regulation and purpose. Regulation is the legal framework for the consent. Currently, only GDPR is supported.

For each purpose, the following fields are defined. All fields are optional, except consent and timestamp_unixtime_ms. Be sure to include your privacy and compliance experts when deciding how to implement optional fields.

Property Type Example Values Notes
consented bool true / false Records if consent was given (true) or rejected (false).
document string "v23.2b" An identifier for the document, document version or experience that the user may have consented to.
location string "example.com/", "17 Cherry Tree Lane" A location where the user gave consent. This property exists only to provide additional context. It may be a physical or digital location.
hardware_id string "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702" A Hardware ID for the device or browser used to give consent. This property exists only to provide additional context and is not used to identify users .
timestamp_unixtime_ms number 1510949166 A timestamp for the creation of the consent state. mParticle’s SDKs send this field automatically. If using the HTTP API, this field must be set manually.

The current consent state for each workspace is maintained on the user profile. The purpose keys must match the purposes chosen during workspace setup.

For each Workspace, and each active combination of regulation and purpose, the User Profile stores the most recently received consent state.

{  
  "consent_state": {
    "gdpr": {
      "location_collection": {
        "consented": true,
        "document": "location_collection_agreement_v4",
        "timestamp_unixtime_ms": 1523039002083,
        "location": "17 Cherry Tree Lane",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
      },
      "parental": {
        "consented": false,
        "document": "parental_consent_agreement_v2",
        "timestamp_unixtime_ms": 1523039002083,
        "location": "17 Cherry Tree Lane",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"     
      }
    }  
  }
}

Audiences

Consent state can be used to create conditions in the Audience Builder.

Connections and Forwarding Rules

Consent state can be used to create forwarding rules. For example, you can choose to only forward data from users who have given consent for a particular purpose.

Kits and Forwarding Rules

If you set up a Forwarding Rule for an embedded kit integration, the iOS and Android SDKs will check consent status for the user on initialization. If the rule condition fails, the kit will not be initialized. Note that kits are only initialized when a session begins or on user change, so if consent status changes in the course of a session, while mParticle will immediately stop forwarding data to the kit, it is possible that an embedded kit may remain active and independently forwarding data to a partner from the client until the session ends.

When the consent state of a profile changes, that change can be communicated to mParticle event integrations. If the consent_state object on an incoming event batch contains changes from the existing profile, mParticle adds a ‘system notification’ to the batch for each consent state change before the batch is sent to incoming forwarders. This notification contains the full old and new consent state objects:

"system_notifications": [
  {
    "data": {
      "purpose": "location_collection",
      "current": {
        "regulation": "GDPR",
        "document": "location_collection_agreement_v4",
        "consented": false,
        "timestamp_unixtime_ms": 1523045332033,
        "location": "17 Cherry Tree Lane",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
      },
      "old": {
        "regulation": "GDPR",
        "document": "location_collection_agreement_v4",
        "consented": true,
        "timestamp_unixtime_ms": 1523039002083,
        "location": "17 Cherry Tree Lane",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
      }
    },
    "type": "gdpr_change"
  }
]

There are currently two ways that consent state changes are forwarded to mParticle event integrations:

  1. Some partners accept raw event batch data from mParticle, mostly for data storage or custom analytics use cases. For these partners, mParticle will forward the ‘system_notifications’ object with each relevant event batch. Forwarding of system notifications can be turned off with a user setting. Integrations that can currently receive the system notifications object include:

  2. mParticle is working with other partners to support forwarding consent state changes as a Custom Event. These events contain the new consent state information as custom attributes, a custom event type of "Consent", and an event name of "Consent Given" or "Consent Rejected". These consent events are forwarded to supporting partners as standard custom events.

    {
      "data": {
        "event_name": "Consent Given",
        "custom_event_type": "Consent",
        "custom_attributes": {
          "consented": "true",
          "document": "location_collection_agreement_v4",
          "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702",
          "purpose": "location_collection",
          "location": "17 Cherry Tree Lane",
          "regulation": "GDPR",
          "timestamp_unixtime_ms": 1523039002083
        },
        "event_type": "custom_event"
      }
    }

    Partners that currently accept these custom consent state events include:

    “GDPR Consent Change” is now listed as a data type in the Integrations directory and we will update this list as more partners add support.

Consent state can be logged via the HTTP API simply by including a consent state object in a batch.

"consent_state": {
  "gdpr": {
    "location_collection": {
      "document": "location_collection_agreement.v43",
      "consented": true,
      "timestamp_unixtime_ms": 1523039002083,
      "location": "dtmgbank.com/signup",
      "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
    },
    "parental": {
      "document": "standard_parental_consent.v2",
      "consented": true,
      "timestamp_unixtime_ms": 1523039002083,
      "location": "dtmgbank.com/signup",
      "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
    }
  }
}

In the context of a complete batch, it looks like this:

{
  "events": [
    {
      "data": {
        "timestamp_unixtime_ms": 1402521613976,
        "event_name": "deposit",
        "custom_event_type": "other",
        "amount": 0.02,
        "custom_attributes": {
          "reluctance": "high"
        }
      },
      "event_type": "custom"
    }
  ],
  "device_info": {},
  "user_identities": {
    "customerid": "Michael_Banks1904"
  },
  "user_attributes": {
    "investment_prefs": [
      "Railways to Africa",
      "Dams across the Nile",
      "Plantations of ripening teeeeaaaa"
    ],
    "current_balance": 0.02
  },
  "consent_state": {
    "gdpr": {
      "location_collection": {
        "document": "location_collection_agreement.v43",
        "consented": true,
        "timestamp_unixtime_ms": 1523039002083,
        "location": "dtmgbank.com/signup",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
      },
      "parental": {
        "document": "song_about_tuppence.v2",
        "consented": true,
        "timestamp_unixtime_ms": 1523039002083,
        "location": "dtmgbank.com/signup",
        "hardware_id": "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702"
      }
    }
  },
  "application_info": {
    "application_name": "DTMGFidelityFiduciaryBanking",
    "application_version": "1.0",
    "package": "com.DTMG.sh.Investment"
  },
  "schema_version": 2,
  "environment": "production",
  "ip": "127.0.0.1"
}

Consent state can be logged in mParticle’s native SDKs using the Consent State API. Once a consent state is set, it cannot be modified. To change the consent state for a given purpose, you can either remove it, or replace it with a new complete consent state object.

iOS

MParticleUser *user = [MParticle sharedInstance].identity.currentUser;

// Create consent objects
MPGDPRConsent *locationCollectionConsent = [[MPGDPRConsent alloc] init];
gdprConsent.consented = YES;
gdprConsent.document = @"location_collection_agreement_v4";
gdprConsent.timestamp = date;
gdprConsent.location = @"17 Cherry Tree Lane";
gdprConsent.hardwareId = @"IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702";

MPGDPRConsent *parentalConsent = [[MPGDPRConsent alloc] init];
gdprConsent.consented = NO;
gdprConsent.document = @"parental_consent_agreement_v2";
gdprConsent.timestamp = date;
gdprConsent.location = @"17 Cherry Tree Lane";
gdprConsent.hardwareId = @"IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702";

// Add to consent state
MPConsentState *consentState = [[MPConsentState alloc] init];
[consentState addGDPRConsentState:locationCollectionConsent purpose:@"location_collection"];
[consentState addGDPRConsentState:parentalConsent purpose:@"parental"];
user.consentState = consentState;

// Remove consent state
MPConsentState *consentState2 = user.consentState;
[consentState2 removeGDPRConsentStateWithPurpose:@"parental"];
user.consentState = consentState2;

Android

 MParticleUser user = MParticle.getInstance().Identity().getCurrentUser();
        
// Create GDPRConsent
GDPRConsent locationCollectionConsent = GDPRConsent.builder(true)
        .document("location_collection_agreement_v4")
        .location("17 Cherry Tree Lane")
        .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702")
        .build();

GDPRConsent parentalConsent = GDPRConsent.builder(false)
        .document("parental_consent_agreement_v2")
        .location("17 Cherry Tree Lane")
        .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702")
        .build();

// Add to your consent state
ConsentState state = ConsentState.builder()
        .addGDPRConsentState("location_collection", locationCollectionConsent)
        .addGDPRConsentState("parental", parentalConsent)
        .build();

user.setConsentState(state);

// Remove Consent State
ConsentState updatedState = ConsentState.withConsentState(state)
        .removeGDPRConsentState("parental")
        .build();

user.setConsentState(updatedState);

Javascript

var user = mParticle.Identity.getCurrentUser()
// Create consent 
var location_collection_consent = mParticle.Consent.createGDPRConsent(
    true, // Consented
    Date.now(), // Timestamp
    "location_collection_agreement_v4", // Document
    "17 Cherry Tree Lane", // Location
    "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702" // Hardware ID
);

var parental_consent = mParticle.Consent.createGDPRConsent(
    false, // Consented
    Date.now(), // Timestamp
    "parental_consent_agreement_v2", // Document
    "17 Cherry Tree Lane", // Location
    "IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702" // Hardware ID
);

// Add to your consent state
var consentState = mParticle.Consent.createConsentState();
consentState.addGDPRConsentState("location_collection", location_collection_consent);
consentState.addGDPRConsentState("parental", parental_consent);
user.setConsentState(consentState);

// Remove consent state
consentState = user.getConsentState();
if(consentState) {
  if (consentState.getGDPRConsentState()["parental"]) {
    consentState.removeGDPRConsentState("parental");
    user.setConsentState(consentState);
  }
}