Sitecore Experience Platform

Technical guidance for GDPR (including EXM and Sitecore Commerce)

Abstract

This topic provides technical guidance for GDPR for Sitecore 8.2.7

The General Data Protection Regulation (GDPR) is a European Union regulation (EU 2016/679) that will come into effect on May 25, 2018. Sitecore has published a whitepaper that describes how you can choose to configure your Sitecore implementation to support you on your GDPR compliance journey.

This technical guidance provides information on how developers can choose to implement steps toward compliance with GDPR's individual data subject rights request requirements, including the specific rights to erasure, the right to be informed, the right to access and data portability. This topic does not provide exhaustive guidance. As a Sitecore customer, only you can assess your own risks, and we recommend you seek legal counsel to understand the applicability of any law or regulation to your business, including how you process personal data.

For Sitecore 9.0 refer to the xConnect documentation.xConnect

There is information about EXM and Sitecore Commerce as well:

This section describes how you can configure your Sitecore implementation to enable the right to erasure, also known as the right to be forgotten, as described in article 17 of the GDPR.

Your Sitecore xDB implementation stores the interaction history of contacts in the database. You can customize your Sitecore xDB implementation to find and remove an individual’s data from the database.

You use the removeContactPiiSensitiveDataæ pipeline to enable this right. It is up to you, as a developer, to decide where, when, and how to call this pipeline. You can use the pipeline as a background worker process, or in many other ways.

Because it is not possible to remove all personal data from the system if a contact has an active session, once configured by you the pipeline locks the contact before it removes data to make sure that there are no active sessions for the contact.

How the pipeline works

Once configured by you, the pipeline goes through these steps when it runs:

  1. It checks preconditions. The pipeline aborts if xDB is disabled.

  2. It locks the contact so that no edits can be made to the contact.

  3. It removes all configured contact personal and sensitive facets. Note that you must configure your Sitecore implementation to load all facets to be removed when the contact is loaded.

  4. It removes the contact identifier.

  5. It removes the device last known contact ID to break the connection between the contact and the device. Note that even though the browser cookie that stores the device ID remains in the web browser of the user, it cannot be used to identify the contact anymore.

  6. It sets the Contact.GdprStatus.ExecutedRightToBeForgotten flag to true.

  7. It saves the contact in xDB.

  8. It removes personal and sensitive data from the historical interactions of the contact.

  9. It unlocks the contact in xDB.

Once configured by you, the Engagement Automation component extends this pipeline to remove all automation states.

A contact becomes read-only after the pipeline has run. If you try to save a contact that has ExecutedRightToBeForgotten set to true, your Sitecore implementation will throw an exception.

Once configured by you, the Contact Segmentation Index component extends the contact and interaction indexing pipelines for live processing to remove data you identify as sensitive data from the search indexes.

The pipeline can also iterate over historical interactions to remove personal and sensitive data if you enable this in the pipeline arguments. The Sitecore.Analytics.Pipelines.RemoveContactPiiSensitiveData.RemoveHistoricalInteractionsPiiSensitiveDataProcessor class iterates over historical interactions, calls the removeHistoricalInteractionPiiSensitiveData pipeline (empty by default) for each of them, and stores interaction to your xDB implementation and schedules them for indexing.

You can extend this pipeline to remove personal and sensitive data. The following example shows a processor you can choose to add to the pipeline to remove personal data stored in the CustomValues collection:

public class DemoHistoricalInteractionPiiSensitiveDataProcessor : RemoveHistoricalInteractionPiiSensitiveDataProcessorBase
{
  public override void Process(RemoveHistoricalInteractionPiiSensitiveDataPipelineArgs args)
  {
    if(args.Interaction.CustomValues.ContainsKey("PersonalData"))
    {
      args.Interaction.CustomValues["PersonalData"] = null;
    }
  }
}

Note

Make sure that you save contacts with the ExecutedRightToBeForgotten flag set to xDB before you remove sensitive data. If removing sensitive data causes an unhandled exception, you can no longer save the contact and run the whole pipeline again. You would then have to unset the ExecutedRightToBeForgotten flag manually in xDB before running the pipeline again.

Note

By default, the removeContactPiiSensitiveData pipeline removes the contact and interaction data from the Collection (MongoDB) database. It does not remove any data from the Reporting database. Sitecore removes this data from the Reporting database when you fully rebuild this database.

Code example

This example shows how you use the pipeline:

var args = new Sitecore.Analytics.Pipelines.RemoveContactPiiSensitiveData.RemoveContactPiiSensitiveDataArgs(contactId)
{
  RemoveInteractionPiiSensitiveData = //true if there is personal/sensitive data on interaction to remove
};
Sitecore.Pipelines.CorePipeline.Run("removeContactPiiSensitiveData", args); 

Or, alternatively:

corePipelineManager.RunRemoveContactPiiSensitiveDataPipeline(args); //where corePipelineManager is an instance of Sitecore.Abstractions.BaseCorePipelineManager class.

This section describes how your Sitecore implementation can be configured to enable the right to be informed, which may help you meet the requirement that you are transparent about what you collect and how you use it, as described in article 12 and 13, and in article 4, number 11, of the GDPR.

As a developer you can configure your Sitecore implementation to track your efforts to inform end-users about data you collect through your privacy policy.

xDB can be configured to include a collection facet called Privacy Policy Acknowledgement. This collection has an audit trail of if and when a contact has acknowledged your privacy policy. The collection contains this:

  • Agreement Date - specifies the date that the contact they agreed to the latest privacy policy.

  • Policy Identifier - specifies the unique identifier for the policy. This can include version number.

The details are:

Namespace: Sitecore.Analytics.Model.Entities

Assembly: Sitecore.Analytics.Model (in Sitecore.Analytics.Model.dll)

Syntax:

/// <summary>
  ///   Allows a class to implement a facet that indicates information about this contact and GDPR.
  /// </summary>
  public interface IGdprStatus : IFacet
  {
    /// <summary>
    ///   Gets or sets a value indicating whether right to be forgotten was executed.
    /// </summary>
    /// <value>
    ///   <c>true</c> if right to be forgotten was executed; otherwise, <c>false</c>.
    /// </value>
    bool ExecutedRightToBeForgotten { get; set; }
    /// <summary>
    ///   Gets a <see cref="IPrivacyPolicyAcknowledgement" /> that indicates an audit trail of when this contact has
    ///   acknowledged the brand's privacy policy.
    /// </summary>
    /// <value>
    ///   The privacy policy acknowledgement.
    /// </value>
    [NotNull]
    IPrivacyPolicyAcknowledgement PrivacyPolicyAcknowledgement { get; }
  }

Code example

This example shows how you use the facet:

Sitecore.Analytics.Model.Entities.IContact contact = // Get Contact
Sitecore.Analytics.Model.Entities.IGdprStatus gdprStatus = contact.GetFacet< Sitecore.Analytics.Model.Entities.IGdprStatus>("GdprStatus");
gdprStatus.ExecutedRightToBeForgotten = true;
Sitecore.Analytics.Model.Entities.IPrivacyPolicyAcknowledgementElement privacyPolicyAcknowledgementElement = gdprStatus.PrivacyPolicyAcknowledgement.Values.Create();
privacyPolicyAcknowledgementElement.AgreementDate = System.DateTime.UtcNow;
privacyPolicyAcknowledgementElement.PolicyIdentifier = "1.0.0";

This section describes how your Sitecore implementation can be configured to enable the right of access, or allowing individuals to see what personal data you’re processing and storing, as described in article 15 of the GDPR requirements, as well as the right to data portability, providing data subjects with a copy of the personal data you have about them, as described in article 20 of the GDPR.

As a developer, you can choose to use the contact repository API to retrieve the full interaction history for the given contact:

Namespace: Sitecore.Analytics.Data

Assembly: Sitecore.Analytics (in Sitecore.Analytics.dll)

Syntax:

public virtual Sitecore.Analytics.DataAccess.HistoricalInteractionsCursorBase GetInteractionCursor(
     System.Guid contactId,
     int visitsToLoadPerBatch,
     System.DateTime maximumSaveDate)

Parameters:

  • contactId

    Type: System.Guid

    The contact ID

  • visitsToLoadPerBatch

    Type: Int32

    The visits to load in the batch. If the value exceeds the value of the [AnalyticsSettings.ContactHistory.MaxInteractions] setting, the value of this setting is used instead.

  • maximumSaveDate

    Type: System.DateTime

    A [DateTime] value that is the maximum date when the visit was saved to database, expressed as UTC, for visits to be returned. Visits saved to database after the specified date are not included in the results. DateTime.Kind should be DateTimeKind.Utc.

    Return Value: The instance of [Sitecore.Analytics.DataAccess.HistoricalInteractionsCursorBase].

Code examples

This example shows how you use the API:

var cursor = _repository.GetInteractionCursor(contactId, visitsToLoadPerBatch, maximumSaveDate);
var interactions = new System.Collections.Generic .List<Sitecore.Analytics.Model.VisitData>();
while (cursor.HasNextBatch)
{
  interactions.AddRange(cursor.GetNextBatch());
}

This section describes what you must be aware of in the Email Experience Manager (EXM) concerning GDPR.

Note

This information is only valid for EXM 3.5, Update 2.

Pipelines

The removeContactPiiSensitiveData pipeline has a RemovePiiSensitiveExmData pipeline processor. This processor does the following:

  • Removes any rows related to the contact from the EmailOpenEvents table in the EXM.WEB database

  • Removes any rows related to the contact from the LinkClickEvents table in the EXM.WEB database

  • Removes any rows related to the contact from the DispatchQueue table in the EXM.MASTER database

  • Removes any rows related to the contact from the Suppressions table in the EXM.MASTER database

The RemoveHistoricalInteractionsPiiSensitiveExmData pipeline processor of the removeHistoricalInteractionPiiSensitiveData pipeline removes any personal data created by EXM for interactions. It changes the email address of the custom values to PII data removed, and changes custom data on page events (first name, last name, and email address) to PII data removed.

Reporting data

The Click and Unsubscribe events are the only events EXM tracks for contacts that have triggered the right to be forgotten. This means that the reporting data for an email campaign appears non-aligned.

For example, if a contact triggers the right to be forgotten in an email message and later clicks a link in the same email message, EXM records the Click event and adds it to the reporting data for the email campaign. However, because the contact has triggered the right to be forgotten, EXM does not track the Open event. Therefore, it is possible that the number of contacts that have opened an email campaign is lower than the number of links clicked for the same email campaign in the reporting data.

Scaled environments

When you configure your EXM implementation to call the removeContactPiiSensitiveData pipeline for the content delivery (CD) role in a scaled environment, the EXM.MASTER database is not cleaned. The same is true for the EXM:WEB database if the removeContactPiiSensitiveData pipeline is called on the content management (CM) role in a scaled environment.

Therefore, after the removeContactPiiSensitiveData pipeline has been called either on a CD or CM instance, you must execute the RemoveSensitiveData pipeline on the other role. For example:

Guid contactId; //Id of the contact
string emailAddress; //Email address of the contact. Only necessary if run on the CM and you want to remove data from the Suppressions table
 
var args = new RemoveSensitiveDataPipelineArgs(contactId, emailAddress);
CorePipeline.Run("RemoveSensitiveData", args, "exm.gdpr");

Note

This information is valid for Sitecore Commerce 8.2.1, Update 3.

Support for GDPR provided in Sitecore Commerce 8.2.1 Update3 follows the technical guidance for GDPR described above.

For Sitecore Commerce interaction, Personal Data is collected and stored in two contexts:

  • User contact and page event information collected when users interact with Sitecore Commerce-powered sites is stored in the Sitecore xDB. When the GDPR “Right to Erasure” principle is exercised, any Personal Data is removed from the specified contact(s) through the removeContactPiiSensitiveData pipeline (as described above). The corresponding Commerce Connect pipeline processors are called to remove all of the commerce-related browsing and order data, for both registered and anonymous users, as would normally appear on the Commerce tab of the Experience Profile page (for example, interactions such as products browsed, or outcomes such as orders placed). The new pipeline processors and all commerce-related page eventIds are defined in the Website\App_Config\Include\Sitecore.Commerce.config file. If you have your own custom page events containing Personal Data, you can add these page eventIds to this configuration file as flagged to be removed when the GDPR “Right to Erasure” operation is performed.

  • Transaction-related data (that is, information captured during activities such as user registration or order placement) is stored in the Commerce databases. To support the GDPR “Right to Erasure” principle, you can remove the associated user accounts through the Sitecore User Manager application and the Commerce Server Customer and Orders Manager.

Note

Any Personal Data associated with orders (for example, first and last name, billing address), are retained. Such data is required for potential audit purposes and warrantee requirements (for example, returns, or product recalls). If your company’s GDPR compliance requires that all Personal Data must be removed from Commerce Order data, you must do so manually.