Sitecore and GDPR in practice

This article is a supplement to my sitecore.stackexchange response, to “Sitecore, personal data and General Data Protection Regulation (GDPR)” question, please check it before reading.

I won’t cover here what GDPR is in general. There are already many great articles about it from Sitecore: GDPR Sitecore 6, 7, 8, GDPR for Sitecore 9, or external: http://www.sphammad.com/blog/gdpr-all-you-you-need-to-know-with-templates or http://www.gdpr-legislation.co.uk/ Instead I will focus on GDPR related issues you may find in your Sitecore XP implementation.

Personal Data Gathered by Sitecore Experience Platform

If you think about Sitecore and personal data, most probably you have in mind Experience Profile contact’s details:

The data displayed in Experience Profile is loaded directly from Analytics Database (MongoDb in Sitecore 8) from:

  • Contacts collection:

  • Identifiers collection (identifier may be for example email address):

Basic personal data is also available in Experience Profile contacts list:

The data for it is loaded from sitecore_analytics_index in Sitecore 8:

How personal data may appear in Experience Profile?

when anonymous visitor is identified:

  • visitor is identified by custom code, e.g. while registering, login, reading geolocation data from IP, etc. Example Sitecore 8 code to identify contact:
  • visitor is identified by WFFM “Update contact details” save action
  • visitor is identified by custom connector

when contacts are uploaded in List Manager app, eg for EXM:

Data used in this app in Sitecore 8 is stored in:

  • sitecore_analytics_index:
  • Analytics Database in Contacts collection
  • SQL Reporting database:

when Sitecore gathers specific page events or query string parameters from visitor interactions:

Personal data may appear in Analytics database in Interactions collection (and sitecore_analytics_index in Sitecore 8) with your custom goals, page events or query string parameters related with visit, so you should check what additional data you are saving there (e.g. you may have there full history of the user’s search, or parameters you pass to fill WFFM form, etc).

 

Personal data gathered by XP for contacts enrolled into marketing automation plan can be also displayed in Marketing Automation app:

Hints:

  • Sitecore Contact’s Id is persisted in SC_ANALYTICS_GLOBAL_COOKIE in visitor’s browser:This value is saved to databases (analytics and reporting) and sitecore_analytics_index.
  • To have same values of Contact Id in Mongo Analytics database and in the cookie, you should use .Net encoding. For example with this option in Robo:
  • In sitecore_analytics_index contact id is usually (but not always) stored without dashes.
  • Sitecore 9 won’t index personal data in by default. It also won’t index your custom facets data if you mark it [PIISensitive] attribute.

Personal Data in Sitecore User Manager

You may also have user’s personal data stored in Sitecore User Manager:

Data source for this, is typically ASP.Net Membership database tables (which are by default in Sitecore core database), but in can be also implemented in custom way (e.g. with Active Directory connector). Profile data can be also manipulated from code with:

Restrict Access to Personal Data in Sitecore Back-office

Because user has the right to be informed what is going on with his personal data (you should inform him about his rights on your website, e.g. in pop-up window), you need to have full control who has access to this data. Otherwise you cannot guarantee how personal data gathered by you is used. In Sitecore back-office you can achieve this with limiting access to admin account and setting security rights on following core db items:

  • SPEAK applications under:
  • Launchpad buttons under:
  • For WFFM reports, you will need to change security settings for ribbon button as well:

Right to be Forgotten

Sitecore 8 prior 8.2 update 7: Sitecore doesn’t have documented API to remove data from MongoDB, but you can rather easily delete the data using standard MongoDB .Net provider shipped with the platform.

For updating Analytics Index you can use https://github.com/vhil/helpfulcore-analytics-index-builder, it’s very simple actually, e.g. to update index for contact entity:

For some of entities you  would need to use Sitecore.ContentSearch API to search and remove documents from the index (for example entries gathered by EXM can’t be removed with the module from Github, cause they don’t connect with Contact entity directly (they connect to interactions instead):

If you removed user from list manager (there’s no point to keep anonymous users without email address in the list), you will also need to update recipients count in list item using ListManager<TContactList, TContactData> class to keep your data consistent.
Additionally you need to update Contacts table in SQL Reporting database for ContactId equals _id from Contacts collection:

Sitecore 8.2 update 7: you call new pipeline, responsible for removing personal data:

You can look at this pipeline configuration in Sitecore.Analytics.config and add your custom facets you want to remove. By default it removes: Addresses, Emails, Personal, Phone Numbers and Picture facets.

Sitecore 9: you can call ExecuteRightToBeForgotten method from XConnectClient class: https://doc.sitecore.net/developers/xp/xconnect/xconnect-client-api/contacts/right-to-be-forgotten.html

Exporting Personal Data (Right to Data Portability)

Sitecore 8 prior 8.2 update 7: You can extract all the data form xDB Contacts and Interactions collections using Mongo.Net driver and export it to Json. For example for interactions:

Sitecore 8.2 update 7: You can call new method in ContactRepositoryBase to export visits:

Sitecore 9: You can use xConnect API: https://doc.sitecore.net/developers/xp/xconnect/xconnect-client-api/contacts/export-all-contact-data.html

Modifying Personal Data (Right to Data Rectification)

You should allow the user to change personal facets in Tracker.Current.Contact.
Alternatively in Sitecore 8 you will need to directly call ContactManager to lock and update contact:

In Sitecore 9 you can use xConnect API to modify contact data: https://doc.sitecore.net/developers/xp/xconnect/xconnect-client-api/contacts/set-contact-facet.html

Right to be Informed

For every version you need to implement custom message box where you inform the users about their rights and your privacy policy.

Sitecore 8 prior 8.2 Update 7: you need to implement custom facet to store audit trail of when the contact acknowledged the organization’s privacy policy.

Sitecore 8.2 Update 7: you can use built-in GdprStatus facet to store privacy policy acknowledged info:

Sitecore 9: ConsentInformation facet will be the good place to store privacy policy acknowledged info. You can access it with xConnect client:

Check next part of this article where I cover GDPR in WFFM/Forms and EXM.

  • Hi Tomasz,
    this is a great post, thanks a lot for compiling the information & adding all the details from various sources!

    I have one question:
    you state “Sitecore 9 won’t index personal data in by default.” – can you elaborate further on this point? I understood it, that this relates to Sitecore 9 won’t create the “SC_ANALYTICS_GLOBAL_COOKIE” by default; but which seems not to be the case (and required programming) as described in the StackExchange article here: https://sitecore.stackexchange.com/questions/1454/disable-xdb-tracking-for-single-requests

    So what exactly are you referring to, when you say “Sitecore 9 won’t index personal data in by default.” ?

    Thanks a lot,
    Oliver

    • whuu

      Hi Oliver, thanks for your feedback.

      With this statement I meant that Sitecore 9, by default won’t add personal facets (marked by [PIISensitive] attribute) to the sitecore_xdb search index (which replaced sitecore_analytics index from 8).
      In practise, it means this information won’t be stored in the index in Solr/Azure Search, but only in xDB. This resolves issue with protecting and anonymizing the data in Solr/Azure Search part of your system (cause it’s not there :). The drawback is that you won’t be able to search it using the index.

      To change this behaviour you can edit the config:
      https://doc.sitecore.net/developers/xp/xconnect/xconnect-search-indexer/enable-pii-indexing.html

      You can check for example “Sitecore.XConnect.Collection.Model, 9.0.json” file in xConnect directory, to find which OOTB facets are marked with PIISensitive attribute.

      I don’t think that “SC_ANALYTICS_GLOBAL_COOKIE” behaviour changed in 9. Anyway, it only stores visitor id, which you don’t need to worry about in terms of GDPR, as far as you keep your analytics data anonymous.

      • Thanks for the follow-up & clarifications, Tomasz.

        As a side note, you do have to care about the SC_ANALYTICS_GLOBAL_COOKIE tough – because a visitor should be able to specify his/her cookie settings on your site in a way, to be not tracked at all; which means, you must programatically ensure that this cookie is not written at all.