Cross-post from 33 Sticks: Setting up Adobe Analytics for GDPR

I recently posted on the 33 Sticks blog; I figured I’d copy the post here for posterity’s sake ;). 

There is so much documentation out there for Adobe Analytics and GDPR, it’s hard to see how it all fits together (though I do feel like Adobe’s documentation on the GDPR workflow is a good place to start). Note, I am NOT claiming to be an expert on this- I’ll defer to Adobe staff for their expertise. And I am NOT offering advice on what/how to regulate- I’ll defer to your legal/privacy team for that. But since I just had to muddle through all this, and learned a lot in the process, I figured I’d share my learnings and hopefully help others who are also muddling through.

I’ve found that in general, when folks are talking about changes in Adobe Analytics to account for GDPR, they’re talking about one of three things:

  1. Obfuscating/removing User IP addresses
  2. Adobe Data Retention Settings
  3. Client Opt-out

Obfuscating/Removing IP Addresses

This is pretty straightforward, though the documentation is a bit tricky to find. This is simply a setting you can set in the Admin Console of Adobe Analytics within General Account Settings for each Report Suite:

Adobe’s General Settings Documentation has good info on these settings. To me, the important take-aways here are:

  • Replace the last octet of IP address with 0 is basically like taking the street number off of my house’s address- you may still be able to know my general location, but you no longer have the specifics. This change applies BEFORE data is processed, meaning it WILL affect Adobe’s ability to do Bot/IP Filtering, might affect VISTA rules, and will make it so Adobe’s Geo-segmentation will have less info to work with and will therefore be at least a little less accurate.
  • IP Obfuscation affects what analysts/admins can view of the IP address, like in Data Warehouse. You can choose to leave the IP address as-is, to obfuscate it so it becomes a unique string that can’t be used to identify the user, or to replace it with “x.x.x.x” (which is the default option for EMEA suites gong forward). The obfuscation or deletion happens further along in data processing, after VISTA rules and Bot/IP filtering.

Adobe Retention Settings

After May 25, 2018, Adobe may start deleting data older than 25 months, unless you specifically work with your Adobe Account reps to extend this to up to 37 months (at a cost). Unlike Google Analytics (which will keep standard reports but just delete user/event data), Adobe truly is just deleting all data older than your retention window. When thinking about this, I’d encourage you to consider:

  1. the rareness of a user who hasn’t reset their cookies/changed devices/changed browsers in over 2 years
  2. if your site and/or implementation hasn’t significantly changed in 2+ years, then we may have bigger issues than data retention

Basically, if you’re heavily using data that is over two years old, I’m fairly certain that you’re already not looking at data that could be compared as apples-to-apples with your current site/implementation.

You can view your current data retention by going to the Data Governance interface mentioned later in this post (note, my Report Suites say anywhere from 37 months to 121 months, even though I have definitely not worked to extend it beyond 25 months- I suspect that since I have not explicitly extended it, I can’t count on it staying this way):

Client Opt-Out

This is definitely the most involved piece of GDPR compliance. Again, Adobe’s documentation on the GDRP Workflow has some good information, but here is my take on what you need to do (assuming you are already on the Experience Cloud):

Label what data needs to be “governed”

Here, on a per-Report-Suite basis, I can go through all my dimensions and metrics and flag what things should be affected by data governance. Many of my dimensions and metrics don’t NEED to be governed- for instance, browser type can probably just be left alone (Disclaimer: seriously, talk to your legal team about what to govern). Other things, like geo-location, Adobe may have automatically already applied appropriate labels to, which you just need to review/confirm:


But my own organization’s policies may dictate that I go even more stringent and also label things like US States, which Adobe didn’t auto-apply a label to. The more likely scenario is that I need to pop open the subtle drop-down menu that says “Standard Dimensions” and go to my custom Events and Dimensions so I can find my eVar that captures User ID and label it so Adobe knows how to govern it:

The labels are, unfortunately, not super straight-forward, but basically, these are your options for each dimension/metric:

Adobe will use these labels to decide what to do when it receives a request from you about a user access/deletion.

Set Up Your Privacy Portal for Capturing Adobe ID Requests

Before Adobe can “govern” anything, you need to give users a way of opting out of tracking. This means setting up a Privacy Portal on your site, and using it as a means of collecting information about who is requesting to access their data or opt out. Adobe has provided some tools to help find out about the WHO and WHAT, but then it’s up to your Data Regulator (whoever in your org is assigned to do this stuff) to pass that information along to Adobe.

1. The User Visits the Privacy Portal

adobePrivacy.js (or the Adobe Experience Cloud Privacy Launch extension) can put all the tracking identifiers we have for the current user into a JSON object.

Our user might request to merely view what data is being kept on him, in which case, he’ll have to wait- adobePrivacy.js can show us his IDs, but not much more than that. But I could at least show him the identifiers if I want. He may request to delete all past data (and/or get a copy of what was deleted). For that, I need to take that JSON object from adobePrivacy.js and pass it along to whatever mechanisms my Org has in place to organize data governance requests with with Adobe GDPR API.

For example-driven learners like me, I have an extremely unattractive example page showing how to use adobePrivacy.js.
This is what the “retrieve” response might look like:

[
 {
  "company": "adobe",
  "namespace": "visitorId",
  "type": "analytics",
  "name": "s_fid",
  "description": "Fallback Visitor ID",
  "value": "64F04470FAKE04E9-1DADD8FAKE65B7C2"
 },
 {
  "company": "adobe",
  "namespace": "CORE",
  "namespaceId": 0,
  "type": "standard",
  "name": "AAM UUID",
  "description": "Adobe Audience Manager UUID",
  "value": "610212449467061254000504ALSOFAKE"
 },
 {
  "company": "adobe",
  "namespace": "ECID",
  "namespaceId": 4,
  "type": "standard",
  "name": "Experience Cloud ID",
  "description": "This is the ID generated by Visitor and set in 1st party cookie.",
  "value": "6080944537973STILLFAKE359908301249"
 }
]

2. I Submit the Request Through the GDPR API/API Portal

I can use either the GDPR UI Portal (which I can get to from my Adobe Experience Cloud Admin Console) or the GDPR API (after I’ve set up an adobe.io integration- see Appendix on this post).

Here, I can take the JSON object I got from my portal (shown to the right in blue), batch it up with other user’s info (if desired), and let Adobe know who has made an access/delete request. Requests take 1-2 weeks. For access requests, you get a CSV that returns the status of your requests.

I happen to use Postman for my request, which is a handy UI for API requests. This is what my request might look like:

POST API request to https://platform.adobe.io/data/privacy/gdpr/
Headers:

x-gw-ims-org-id : DCF779195968NOTREAL@AdobeOrg
x-api-key: 5a7105dNotARealAPIKeyc735355
Authorization: Bearer eyJ4NXUiOiJpbXNfbmExLWtleS0xLmNlciIsImFsZyI6IlJTMjU2In0.eyJpZCI6IjE1Mjc2MTI3MjQwNTdfYjRkNjg4YTUtOThhMi00MzM2LWIwNjgtNDkwYjYzZThiMTIThisIsntARealTokenI6IjVhNzEwNWQ0YmNiMjQwZjQ4NDBmZmNmYTBjNzM1MzU1IiwidXNlcl9pZCI6IkQ2MjgzNjJDNUFGQzU1REQwQTQ5NUMxMEB0ZWNoYWNjdC5hZG9iZS5jb20iLCJ0eXBlIjoiYWNjZXNzX3Rva2VuIiwiYXMiOiJpbXMtbmExIiwiZmciOiJTTzZOSUY1UEZMTjdDSEFPQUFBQUFBQUFRND09PT09PSIsIm1vaSI6IjU5MzFhZmM5IiwiYyI6IlZFTE5iN1JHcEhhN0h5dkNYSi9SNFE9PSIsImV4cGlyZXNfaW4iOiI4NjQwMDAwMCIsInNjb3BlIjoib3BlbmlkLEFkb2JlSUQscmVhZF9vcmdhbml6YXRpb25zLGFkZGl0aW9uYWxfaW5mby5wcm9qZWN0ZWRFakeFakeFake0Q29udGV4dCIsImNyZWF0ZWRfYXQiOiIxNTI3NjEyNzI0MDU3In0.WBPyKnis4BN1sAmFFSCM1Lazg51z2rnuaniZYPcATOSscfVOB-6L-yWvo1kTjfxxMVvzBLLr9H6pNr2ZzA8PzUDbcYjzzjRvmSqVEII3vW0KFTmG5cO5fmi8j0e662WXg0cp4hUhOhr0MvGa5vRPXBKr7NmtaU0d5_bsKs_5AJBfDsUCnJ5ZcGnK_8DFKb9VIqmxFdLl_dQzKl2dMaEqsK-98cUTT32Th0nC5rQ96-N8TsuYD2fmqzSCiOCQRhXQeQ1U97UvlYOobgKTAF41WDt3gsa786ouV668YZN9-J3tVaejGosEUcHYTKpRKmpKS_jwElfA0ptNV3PCS-aBNg
Content-Type: application/json

Body (JSON):

{
 "companyContexts": [
  {
   "namespace": "imsOrgID",
   "value": "DCF77919596885950A495D3E@AdobeOrg"
  },
  {
   "namespace": "analytics",
   "value":"33stickssandbox"
  }
 ],
 "users": [
  {
   "key": "GDPR-1234",
   "action": ["access","delete"],
   "userIDs": [
    {
     "company": "adobe",
     "namespace": "visitorId",
     "type": "analytics",
     "name": "s_fid",
     "description": "Fallback Visitor ID",
     "value": "64F04470FAKE04E9-1DADD8FAKE65B7C2"
    },
    {
     "company": "adobe",
     "namespace": "CORE",
     "namespaceId": 0,
     "type": "standard",
     "name": "AAM UUID",
     "description": "Adobe Audience Manager UUID",
     "value": "610212449467061254000504ALSOFAKE"
    },
    {
     "company": "adobe",
     "namespace": "ECID",
     "namespaceId": 4,
     "type": "standard",
     "name": "Experience Cloud ID",
     "description": "This is the ID generated by Visitor and set in 1st party cookie.",
     "value": "6080944537973STILLFAKE359908301249"
    }
   ]
  }
 ],
 "expandIds": true
}

3. Adobe Acts Based on Data Governance Labels

Adobe sees a request to access/delete the data for ECID 64F04470FAKE04E9-1DADD8FAKE65B7C2 and sees what data we have for that user. Let’s look at three dimensions and their settings for an example:

If we have data for that user in the Domains dimension, it will see that that data has a data governance label of “ACC-PERSON” which, according to the tooltip means it “will never be returned for a GDPR access request, unless an ID-PERSON label is applied on a variable in this report suite”. I am keeping tracking of an ID for this user in one of my eVars, so the user’s access request will show what Adobe knows their domain to be.
Entry Page doesn’t have any data governance labels applied, so the Entry Page data for this user is left alone.
Entry Page Original has both a “DEL-DEVICE” and a “DEL-PERSON” label on it, meaning Entry Page Original data for this user will be anonymized.

Next Steps

I’ve submitted a few user access/deletion requests so I can see how it affects the data and what the access report looks like, so I’ll have a follow up post in a few weeks with my findings.

Appendix I: Passing along my own Identifications for Users

If I have an eVar (or prop) that I use to identify users (for example, capturing a hashed user ID), then in my data governance labels, I would check the “ID-PERSON” radio button.

Then I need to specify which NAMESPACE I’m going to keep that value in for my API requests. Basically, my API JSON objects already have the IDs that Adobe sets and knows about:

{
 "company": "adobe",
 "namespace": "ECID",
 "namespaceId": 0,
 "type": "standard",
 "name": "Experience Cloud ID",
 "description": "This is the ID generated by Visitor and set in 1st party cookie.",
 "value": "6080944537973STILLFAKE359908301249"
}

So now in my API requests I can add in the IDs that I have for that user:

{
 "namespace": "myuserid",
 "value": "malReynolds1234",
 "type": "analytics",
 "isDeletedClientSide": false
}

Then Adobe’s Data Governance tools can make the connection that IDs sent to the “myuserid” namespace in my API requests correspond to the IDs in my custom dimension that I’m labelling as “ID-PERSON”.

Appendix II: Setting Yourself Up for the API

So, that all seems simple enough, right (ha!)? For me, one of the trickier parts of getting this all set up was setting myself up to use the GDPR API through an Adobe.io integration. I had an advantage because I’ve used a similar integration for Adobe Launch Extensions, but even then for the GDPR API I had to have at least one support ticket (first through Adobe Client Care, then through the adobe.io support team- turns out the ever-evolving documentation didn’t have the right endpoint for me to use yet, but that has since been fixed.)

Pulling largely from the Adobe.io Experience Cloud and GDPR whitepaper, here are the steps I took:

    1. You will need to generate a public and private key. I find the easiest way to do this is to open up a Terminal (aka Command Prompt), navigate to a sensible folder (eg, “cd analytics/gdpr”) and type in the following:
      openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt

      It will prompt you to fill in some information about yourself and your org- complete the prompts, and you should now have two files in your folder: “certificate_pub.crt” and “private.key”. You’ll use these in a moment.

    2. If you don’t already have one, you’ll need to create an adobe.io account (with the same email you use for the experience cloud). Sign in to the adobe.io console.
    3. Create a new integration. On the second screen, select “Access an API”. On the third screen, select the service “GDPR API”.
    4. On the final screen, give it a name (like “GDPR API for Acme, Inc”) and description. Take the “certificate_pub.crt” you created in step 1 and upload it to the “Public keys certificates” field. Click “Create Integration” then “Continue to Integration Details”.
    5. On the Integration Details screen, note your Organization ID (eg “DCF7791959688FAKEID495D3E@AdobeOrg”)- this should match your Experience Cloud Org ID for your company. You’ll need this for the “x-gw-ims-org-id” field in your API Request Headers.
    6. Also on the Integration Details Screen, note your API Key (Client ID) (eg, “765f21b62606FAKEapiKEYb3e656048a910e”). You’ll need this for the “x-api-key” field in your API Request Headers.
    7. On the Integration Details screen, click the “JWT” tab. It will have generated a JWT that you can basically ignore. Open the “private.key” file you created in step 1 in a text editor, copy the contents (including the “——BEGIN PRIVATE KEY——“ and “——END PRIVATE KEY——“ lines) and paste into the “Paste Private Key” field.
    8. Copy the “Sample CURL Command” value and paste it into your Terminal/Command Prompt and hit enter. This should return something like this:
      {
       "Token_type":"bearer",
       "access_token":"eyJ4NXUiOiJpbXNfbmExLWtleS0xLmNlciIsImFsZyI6IlJTMjU2In0.eyJpZCI6IjE1Mjc2MTkzNjUzMzBfODYzOGM5NTYtOTM4My00ZTk5LTg0OTYtYz-hmYTM0OGQ5NjQyX3VlMSIsImNsaWVudF9pZCI6Ijc2NWYyMWI2MjYwNjQyNTlhMmIzZTY1NjA0OGE5MTBFAKETOKENDONOTCOPYME0N0I1NUIwRDlEQjQwQTQ5NUUyQ0B0ZWNoY-WNjdC5hZG9iZS5jb20iLCJ0eXBlIjoiYWNjZXNzX3Rva2VuIiwiYXMiOiJpbXMtbmExIiwiZmciOiJTTzZVRUY1UEhMTjcySEFPQUFBQUFBQUFZRT09PT09PSIsIm1vaSI6IjZh-NDBlMTg4IiwiYyI6IkVVVVgwOVdML1VKbE9pY2Y2Tk5NOTAREALTOKENNfaW4iOiI4NjQwMDAwMCIsInNjb3BlIjoib3BlbmlkLEFkb2JlSUQscmVhZF9vcmdhbml6YXRpb25zL-GFkZGl0aW9uYWxfaW5mby5wcm9qZWN0ZWRQcm9kdWN0Q29udGV4dCIsImNyZWF0ZWRfYXQiOiIxNTI3NjE5MzY1MzMwIn0.a4sUwZjuJyU_g3STYAnK5uQrDLj2AOeRlj3GmTuY-MeK5MrWnXFg3MTdLxgz1cbdkJiV42sAxjoWUtsTfANa1wnIIPimHpVvgypJBJ4VcaQk7h0iio1asPxmeUq3NUrVM7WjnVwqwc6fHlou2OFGbkiL_OulM7D4Yj-kzI68GAV0wJbi-D38rWGlI_nPpq_ICR_0WU3w4l4KPfqk3B6gkaFDedVY6fLpqTQLfad6NQI7BujC1ljsV1RuQnaQ6o59WR6d20IRNVF0N9P2j2SnGasjayQ9uoDSuDp4r-N1I40w6ExOBeGzRGLg-KFxFkTgOhqE1XnqKJfBzuJ9QWKHg",
       "expires_in":86399993
      }

      The portion in purple is your API Authorization Token for the next 24 hours. After that, you need to repeat steps 7 and 8 to generate a new temporary token.

Leave a Reply

Your email address will not be published. Required fields are marked *