Monday, October 10, 2022

AdobeDevBlog: ArgoCon Community Learnings from the Adobe IDP Workshop

Adobe was a diamond sponsor of ArgoCon and we hosted a workshop on September 21, 2022, to brainstorm and formalize the definition and capabilities of an Internal Developer Platform (IDP) with the community’s feedback. In this workshop, which was in the spirit of community open discussion, we shared our IDP journey, and brainstormed with other community thought-leaders on making IDP a reality, based on Argo and other open-source projects. In preparation for the workshop, we had shared the following GitHub document where we outlined the key capabilities of an IDP and gathered the community’s thoughts and feedback.

Here is a visual we came up with to formalize key capabilities of an IDP and here's a link to the full blog post.

Tuesday, February 1, 2022

AdobeDevBlog: Building Enhanced Security into Our Container Platform

In this post, we dive deeper into the security controls within Ethos that help safeguard our Continuous Integration/Continuous Deployment (CI/CD) pipelines, which are used to help deploy microservices across the Adobe ecosystem during service creation, onboarding, provisioning, and deployment. Here's a link to the main blog post on Medium.

Friday, November 19, 2021

AdobeDevBlog: How Ethos Powers a Cloud-Native Transformation at Adobe

I recently moved into a product management role at Adobe. This is my first post as a PM published on Adobe's Medium Tech blog about Ethos (the team I work in). Ethos is a cloud-native and cloud-agnostic platform (and principles) that streamlines the development, operation, and consumption of cloud services inside Adobe. Here's a link to it and below is a high-level architecture of Ethos.

Friday, July 16, 2021

Adobe Experience Platform Query Service Video Demo

In this post, I want to share a demo I created working for the Adobe Experience Platform Query Service product team. The target audience are primarily pre-sales and account teams but anyone can use it get a general understanding of how Query Service connects with external tools. Below is what I worked on to create this demo:

  • Identified a common telecom sector customer churn use case
  • Ingested online/offline data into Adobe Experience Platform using AWS S3
  • Mapped the incoming data files to relevant schemas and datasets
  • Used SQL to combine those datasets into one common dataset using a CTAS query
  • Created a simple churn analysis dashboard using Tableau and connected it to Query Service using PostgreSQL. 
    • Here's a link to it. Please note that the dashboard will not populate (due to AEP access requirements) but you can look at the general structure and fields being used.

Adobe Experience Platform Query Service is a powerful serverless tool that allows brands to analyze online-to-offline customer journeys and understand omnichannel attribution. Query service also allows you to join any dataset in the AEP Data Lake and capture the query results as a new dataset for use in reporting, machine learning, or for ingestion into Real-time Customer Profile. It provides customers with a rich set of SQL-based analytic capabilities to provide rich insights on customer data collected from all channels and devices.

In addition, here are some other practical applications of Query Service aside from combining AEP datasets and connecting to external data visualization tools:

  • Leverage Query Service to take a back up of AEP datasets.
  • Run pathing analysis, attribution analysis and sessionize raw data using Adobe defined functions.
  • Create new calculated attributes using existing data like creating a new calculation for Customer Lifetime Value (CLV).

Below is the video which is uploaded on YouTube and a direct link to it.

Sunday, June 6, 2021

Multi-Org Adobe Target and AEM Experience Fragment Integration and Governance Ideas

Adobe Experience Manager and Adobe Target integration is one of the most powerful and robust in the Adobe Experience Cloud. I wrote about some of the benefits of this integration back in 2019. In this post, I want to cover two topics within the context of these two solutions:

  1. Cross-IMS Org integration between AEM and Target
  2. General Target workspace governance and XF nomenclature ideas

AEM & Target Cross-IMS Org Integration

This is one topic I never got a clear answer to unless I tried and tested it myself. A well known fact about IMS orgs is that we cannot integrate solutions across which is absolutely true when it comes to the Adobe Experience Cloud Visitor ID among other solution but in this case, it is possible to integrate AEM with different Adobe Target instances via Adobe I/O. Having said this, I must also mention that it's not very common for us to see given most companies have a single Target instance but there are some Adobe customers that have multiple Target instances and orgs.

I've included the steps I took to set this up where I tested this using a single AEM author and two Target instances across two IMS orgs. Let's a closer look:

In AEM (6.5.x), go to Security - > Adobe IMS Configurations and either click on an existing Target integration or create a new one. In this case, I already have two integrations set up with two Target instances (2 IMS orgs). 

The first few steps are outlined in the next two screenshots which is key where we first need to generate the public certificate/key in AEM.

The next step is to upload the public key (called AEM-Adobe-IMS.crt) generated in AEM in the Adobe I/O console to integrate AEM with Target. I did this twice by uploading the public keys for both IMS configurations separately into each of the Adobe I/O consoles per IMS org.

You can follow the rest of the steps to set this up in Adobe's official documentation here and once it's set up, you can test the connection for both IMS orgs.

The final step is to connect to each Target instance and send Experience Fragments (XF) separately to both Target instances (and workspaces) in different IMS orgs.

Adobe Target Workspace and AEM XF Governance

This is another important topic that a lot of customers often ask about that's tied to best practices around creating a standardized process for organizing and naming workspaces and XFs in Target and AEM respectively. I previously wrote about a slightly similar topic about creating a segmentation governance strategy in AAM. 

A colleague of mine Ryan Lillis took the first pass at the Target workspace governance strategy so want to give credit where it's due and a lot of these concepts are also covered in Adobe Target's official enterprise permissions documentation so I highly recommend you review it.

Before we can set governance in any solution, it's important for us to understand the concepts of user access in any solution. I'm not going to explain each of the user roles or the core access functionality in Target (covered in great depth in the documentation) but I have taken a stab to visualize WHAT the users are given access to in Target. 

As you can see, the "Default Workspace" in Target has access to all Target properties and any additional workspaces do not have access to Target properties by default so you will have to manually add them to the workspace. This is an important concept as in AEM 6.5, you can share Experience Fragments directly to Target workspaces. 

Target Workspace Governance

Here are some options for you to consider when you're deciding your Target workspace strategy:

  • Workspaces by Brand: This works well in companies that have multiple brands and each business group operates differently.
  • Workspaces by Geography/Locale: This works well in companies that have multiple country sites/implementations/teams. 
  • Workspaces by Environment: Workspaces are tied to each unique site environment like Dev, QA, Stage etc. This is getting more and more common as more companies start sending XFs to these environments for testing before a launching to production.
  • Hybrid Workspaces: This typically works well for a large companies that are organized by various functions but eventually, it always makes sense to formalize it based on some fundamental construct.
It's also important to note that a company's organizational structure (divisional vs functional etc.) can also dictate how the workspaces are laid out but it's not very common as not every department necessarily has a testing program.

 Experience Fragment Nomenclature Ideas

I've seen examples where XFs are named as "XF1" to something which is well structured like "Site:Location:Offer".

In my experience, a good XF nomenclature has a delimited set of values that have a predefined logic to it and I'm only referring to cases where they're meant to be shared with a Target workspace. Some examples are:

  • XFs based on Brand: <brand>:home:summercampaign
  • XFs based on Geography: en-us:home:springcampaign
  • XFs based on Environment: <dev/stage>:home:wintercampaign
  • Hybrid XFs: <brand>:en-us:home:fallcampaign:20%off

These examples are probably oversimplified and generic but the main point I'm trying to make is that it's important to add some sort of structure to how XFs are named as we want to minimize any confusion and redundancy when these land up as offers in Adobe Target. The other important point is that both the developers in AEM and Target users should align on these before applying these widely to save time. 

Even though Target has robust filtering capabilities for offers (and others), this is how XFs will look in Target if the two groups won't align which in this example, shows inconsistency.

So, that was it! Hope you found this topic helpful. Please feel free to share with me your ideas on workspace organization or XF nomenclature best practices that you've seen work well. 

Sunday, February 21, 2021

Overview of Adobe Experience Platform Event Forwarding

Happy (belated) New Year 2021! There is no denying the fact that the introduction of the Adobe Experience Platform Web SDK has revolutionized data collection. There are a lot of advantages of this approach but the main ones are reduced page latency, fewer cookies, a consolidated tracking library and the ability to directly stream data to Adobe Experience Cloud solutions to name a few. It's no surprise that Adobe is openly propagating this approach as the recommended path to implement all client-side solutions moving forward. I coauthored a post about the high level migration approach to the Web SDK on Adobe's official Medium blog site.

Assuming that we know the basics of the Adobe Experience Platform Web SDK, XDM and setting up the AEP schemas & datasets which will all apply in this case, this article will solely focus on Event forwarding which is a recently launched service by the Adobe data collection team. I'm working with one of my clients to evaluate the feasibility of this feature and have already set this up on my sandbox which I'll cover in this article.

Overview and Use Case

Event forwarding allows customers to federate or distribute data to a 3rd party platform such as Google Analytics or any system that has an API endpoint. The data is first collected from the page via the Adobe Web SDK client-side library and then sent over to a 3rd party endpoint from the Adobe Edge network. Even though it is called Event forwarding, data still needs to be collected at the source on the page.

The primary use case for leveraging this feature is to stream data in real-time to a Data Lake for on-site personalization, decisioning or simply for data collection to run offline queries, build dashboards or create ML models.

You can essentially leverage the implementation you have on your website to send data directly to your Data Lake which isn't very common for a lot of clients who usually send hourly or daily data feeds to their backend platform. With this, they can basically collect cherry picked data which is streamed in near real-time.


I had originally created this simplified architecture diagram for a blog I wrote explaining the AEP Real-Time CDP which I've slightly tweaked to explain the concept of the how data is federated server-side to 3rd party platforms (explained in 3b). Basically, the AEP Edge Network is the system that federates data both to our own Adobe solutions and to 3rd party platforms.

Steps to Implement

In this section, I will cover how to implement this in Tags (formerly Launch) and also show how to collect data streamed from my sandbox using ngrok which is a localhost webhook development tool that allows me to make my endpoint URL public. Please note that I'll just cover the basic steps that will help you make a call to a 3rd party endpoint but a more exhaustive tutorial on this can be found here. So let's take a look.

The first step is to create a separate property under the Server Side section by clicking on the drop down as shown below. Please note that you will not have access to this by default so please contact your Adobe Customer Success Manager to request access and get details around licensing.

The next step is to create a new property (Rohan's Test in my case) in this section and add the extension called "Adobe Cloud Connector". Please note that there's another extension which allows you to federate data to Google Analytics as well.

Next, we need to create a new API endpoint. I'm using ngrok to map it to create a public facing URL tied to port 3000. The public facing domain ends with

I have a Node.js webhook (mapped to port 3000) which I ran while doing this test. I mapped the ngrok domain to my webhook/API endpoint and modified the URL to add '/ssftest' which is my final API endpoint URL.

The next step is to enable the toggle to enable Event forwarding and pick your newly created property ID and Environment.

Next, we need to a new rule tied to the Adobe Cloud Connector extension and pick the option called "Make Fetch Call". Please note that you can also need to create new data elements in this property in case you want to pass any additional data to your API endpoint.

Next, I mapped the API endpoint URL within the action. In this screen, we have the option to make different types of calls but in my case, I'm going to make a POST request. Note that I am also sending some test query string parameters as part of the JSON request. We can also add the XDM data and send it in the body of the request.

Finally, we need to go to the website and load the page with the Web SDK deployed which is the ideal scenario. In my case, my sandbox already has the AEP Web SDK deployed so as soon as I refresh the page, a call gets made both to Adobe Experience Platform and to my webhook (API endpoint).

Here, I can see the query string parameter I sent in the request and some default parameters which also get sent in. If I would've sent in the XDM data object, you would've seen it here too.

What Else Would I Like to See

Below are a few additional things I'd like to see included in Launch Server Side:

  • The ability to do the same thing on a mobile app client-side implementation. Adobe is working on a Mobile app equivalent of the Web SDK so hopefully we'll see it soon.
  • It'll be great if the Launch Server Side team can collaborate with the Data/Bulk Ingestion API team and see if they can come up with shared learnings to standardize server side data collection within Adobe's own solutions as well.
  • Being able to replicate the same data elements created in the client-side Launch property to avoid redundancy.
  • Include more extensions in addition to Google Analytics to federate data server side which is collected by the Edge Server . This will hopefully allow clients to get rid of additional 3rd party scripts from the page such as Facebook and Google conversion pixels.

Even though this is a relatively new service, I'm confident it will become more and more popular as we get closer to the impending deprecation of 3rd party cookies and introduction of more stringent data sharing policies. Hope you found this post helpful and please don't hesitate to reach out with any questions!

Saturday, December 19, 2020

Overview of Adobe Privacy Service and Data Repair API

Imagine a world where user data and information flows freely without any regulations and guidelines. Information ranging from your date of birth, health records to credit card number is accessible by anyone on the Internet. Well, given that we're still in the middle of a pandemic, let's not make things worse and get back to reality. 

We know that web analytics and data management platforms (barring CDPs) are not supposed to store PII or PHI information and are designed to capture anonymous behavioral user information with the ability to store demographic data using indirectly identifiable encrypted IDs. However, it's virtually impossible to control what data gets sent into these tools and in my personal experience working with a lot of different clients and tools, I've seen PII data such as email address, phone number and even SSN still being passed accidentally. Now, I don't think there ever can be a situation where we can completely guarantee that this won't ever happen again but we can certainly put in the right guardrails in place before data is captured.

GDPR and CCPA (and other regulations) are some of the ways which put more power in the hands of individuals to know, opt-out and delete any data collected on them and understand how it's used. This article explains the impact of these two regulations on marketers but before that it is also important to understand the difference between data subjects, data processor and data controller as explained here.

In this post, I will cover how Adobe Analytics customers can obfuscate or delete data which is done using either the Adobe Privacy Service (UI) and Data Repair API respectively. Given that my article will primarily cover how these two tools can be used to execute the deletion requests, please review the official documentation on these two tools for the finer details which I won't cover. So, let's dive in!

Adobe Privacy Service

The Adobe Privacy Service provides Adobe customers with a user interface and APIs to help manage their customer data requests AFTER the data has been collected as opposed to an opt-in service such as OneTrust which blocks all data from being captured in real-time. The Privacy Service allows you to selectively delete data from all Adobe solutions such as Adobe Analytics, Target etc. based on user identifiers or namespaces such as ECID or encrypted user ids. Please note that the Privacy API should not be used to delete PII data captured accidentally but should only be used to serve delete requests from data subjects. Also, note that I will specifically cover the privacy UI in this post but there also a privacy service API which allows you to accomplish the same tasks if you want to do it programmatically.

Use Case

The primary use case for leveraging the Privacy Service is to either access or delete data for users who explicitly reach out to a brand to request a copy of all their personal data or ask for their personal data to be deleted. A good example of how users can do so is shown here.

Overview of Privacy Labels

In order to access or delete any data from Adobe Analytics, Adobe Experience Platform and other solutions, the first step is to add privacy labels to each attribute which contains sensitive data. The labels are classified into three primary categories as covered here so please review these as the scope of my article doesn't cover what these are. In this article, I will use two Adobe Analytics variables Internal Search Term and User Name as examples to first perform a data deletion request through the Privacy Service UI and then through the Data Repair API. 

The first step is to go to the Data Governance section by visiting Analytics > Admin > Data Governance within Adobe Analytics. You'll first land on the page which lets you select your report suite and will also show you the data retention policy for now long your data will be retained.

Once you select your report suite, you can see that in my case, Internal Search Term (eVar1) variable has a l1 label which essentially means that there's PII information in this variable which is captured for some user names captured in eVar50 which has the label l2 (indirectly identifiable). Please note that only the variables which are labelled will be part of the delete requests and unlabelled variables will be left as-is.

We also need to pick some data data governance labels where I'm specifying that I want to delete all data at the person level. The labels are explained in more detail for eVar50 below. Please note that in order to delete data tied to a custom variable, you will need to define a custom namespace (profile_id in my case) which will be the primary identifier to delete IDs. You can name it anything or can use an OOTB namespace such as ECID.

Privacy Job Request

A privacy job request can be made by visiting the privacy page (requires IMS authentication). There is an option to pick the regulation type (GDPR, CCPA etc.) and delete IDs either manually or in bulk by uploading IDs in a JSON file (covered below). I will cover how to do it using both methods but before I do so, let's take a look at the data captured in eVar1 and eVar50. One thing to note is that only data tied to user ids "abc123" and "def456" will be obfuscated as I will only be processing delete requests for these ids and the rest of the data will be left as-is.

Here are the two methods by which you can send a delete request from the privacy UI.

I'll first process a delete request using the manual method. Please note that you can process a request for any of the solutions mentioned but in my case, I'll be deleting (obfuscating) data from Adobe Analytics for the user id "abc123" captured in eVar50 which is tied to the namespace "profile_id" so anytime I enter the value manually, it will be obfuscated but this is not a scalable approach if you want to delete ids in bulk.

Once you click create, you will see that a job id is created which contains my user name "abc123". 

I'll now process a delete request using the JSON upload method which allows you to upload up to 1000 IDs at a time. In my case, I only have 1 ID to delete called "def456" but you can upload up to 1000 per request but limit the requests to up to 10,000 IDs per day. Below is what my JSON looks like. Note that you need to include your IMS org, specify the namespace and add more ids in the "users" array among other attributes.

I also had my network tab open while doing this so you can see the request actually makes an API call to the Privacy Service and sends over the necessary fields to process a delete request.

Impact on Adobe Analytics Data

Once the requests have completely processed which typically takes anywhere between 5-7 days, you can see that the status is marked as "complete". I've purposely hidden the job id and requester email address.

As far as data in Analytics is concerned, you will see that data in the two variables in question will contain the word "privacy-" followed up with a unique identifier for every record tied to the user IDs I sent in the request.

There's a lot of information available in the official Adobe document but I've only covered information relevant to my use case.

Data Repair API

The Data Repair API provides Adobe Analytics customers access to APIs which allows them to delete any data which they want to remove. This API scans all rows of data for a particular report suite and deletes all data in a custom variable defined as part of the API request.

Use Case

The primary use case for leveraging the Data Repair API is to completely delete data from Adobe Analytics variables. The typical scenario is when a customer may have inadvertently captured PII data in an Analytics variable.

Data Repair API Request

The official documentation covers all information around the prerequisites (admin console, access token, global company id etc.) and caveats so I highly recommend that you read that. In this section, I'll cover how I went about sending the API requests using Postman.

Populate the access token, client id (from I/O Console) and global company ID (from Analytics) and as headers in the /serverCallEstimate GET call.

Pass the start and end dates as query string parameters in the same request. You will see that the API response generates a validation token along with specifying the total number of server calls.

The request is the actual delete POST request where we specify the variable that needs to be deleted. You can add multiple variables as part of the same request but I only sent a request for eVar50 in this example. Also, take a look at the response which provides us with a job ID and status.

So, that was the extent of what I will cover but a lot of other useful information is covered in the official Adobe documentation.

Impact on Adobe Analytics Data

Once the request is processed, all data is deleted from Adobe Analytics as shown below.

What Else Would I Like to See Added

Even though I'm happy that we finally have a productized solution for deleting PII data, I would like to see the following enhancements added to it:

  • A user interface to make these requests in addition to APIs
  • Ability to add regex or conditional logic built into the UI to selectively delete data instead of deleting everything 
  • Make this API available for other solutions including AAM and others
  • This is not a big deal but when I tried to send multiple requests (one for each variable), I ran into the following error. It will be nice if users are able to send multiple requests without waiting. Regardless, you can get around this by sending a delete requests for multiple variables as part of the same call.

All in all, it is a great tool for customers who want to delete data using a productized solution which is much cheaper to use. Given that I learnt about this API recently, I wanted to share my learnings with everyone. Hope you found this post informative.