Saturday, June 22, 2019

Send Real-Time Adobe Analytics Events to Adobe Campaign via Triggers

Triggers are part of the Experience Cloud Activation Core Service and have been in existence for a few years now. There's a lot of documentation already out there but with this post, I'll fill in some gaps that exist in the public facing documentation. I will also provide a quick overview of Triggers from my sandbox account, cover common use cases, share a logical architecture diagram and discuss the provisioning process along with some common access issues. Let's get into it!


Overview of Triggers


Triggers allow marketers to activate Adobe Analytics events in Adobe Campaign to re-market and engage customers via emails and other channels. Adobe Campaign is the main solution that leverages Triggers to send emails or SMS based on an action performed on the site in near real-time. I will be covering the integration between Triggers and Adobe Campaign Standard (ACS) at a high level.

We can access Triggers by going to the Activation site and clicking "Manage Triggers" (provisioning covered in the next section). There are 4 types of Triggers we can create which are:

  • Abandonment (Send an email or SMS after a gap of between 10 minutes to 2 hours)
  • Actions (Send an email or SMS if a particular action is performed on the site)
  • Session Start (Send an email or SMS if an action occurred at the start of a session)
  • Session End (Send an email or SMS if an action occurred at the end of a session)

Below is the UI we see when we create a new Trigger based on an abandonment.


Once created, Triggers will start collecting data immediately based on the conditional logic. In my actual example, I've created a simple Trigger based on an action tied to a particular Page Name.




Few Considerations While Using Triggers

  • We can create up to 100 Triggers.
  • We cannot bring in any calculated metrics or segments created in Adobe Analytics.
  • There's no way to select a Visitor container like we can in the Analytics Segment UI.
  • Values from Adobe Analytics reporting don't automatically populate in the dropdown menu when we use the "Equal" operator.
  • For Products or other dimensional data, there's no way to know which particular product has been added to the cart etc. so all the data is sent as it comes in. Prior manipulation of data will have to done to specify exactly which product was sent.
  • The conditional logic to create Triggers can get really cumbersome and there's a lot of flexibility provided around boolean logic and Containers provided in the Triggers UI.


Common Use Cases For Triggers 


There are numerous use cases that can be met using Triggers and below are some examples. Please note that for these to work properly, the user would have to be signed in.

  • Abandonment (Time Bound)

    • A user abandons the cart or form and needs to be contacted within 10 minutes
    • A user signs up for an offer and you need to send a confirmation email
    • Notify of a shipment or password reset
    • A user purchases a product
  • Actions (Event Driven)
    • A user views a promotional video
    • A user completes a survey 
    • Personalize email to show last product viewed
    • Confirm when a prospect opts-in for a newsletter

  • Session Start and End-I haven't used these yet

    • A user visits a campaign landing page after clicking on an ad
    • A user did not sign up for a form and exited the site

Aside from these, we can leverage the propensity score attribute to NOT trigger an email if a user is likely to visit the website in the next 30 days.

Triggers Provisioning


Email the Digital Request Alias

Anyone can can email the Digital-Request@adobe.com alias to get Triggers enabled for their Experience Cloud Org. This team will enable Triggers in the Admin Console as well as enable Triggers in Adobe Campaign Standard (They create an additional ticket). Below is what needs to be communicated in the email:

  • Marketing Cloud Company Name 
  • IMS ORG ID
  • Analytics Login Company (could be same as marketing cloud company name)

Map Report Suites to the Experience Cloud Org

All Adobe Analytics Report Suites need to be mapped to the correct Experience Cloud Org as explained here.

Enable Triggers in the Admin Console

In the Adobe Admin console, we need to turn on the toggle to enable Triggers as shown below.

Create Data Sources

Create a data source in Customer Attributes to capture authenticated users which includes an integration code. This is needed to tie users logging in to the website with profile data in Adobe Campaign Standard. Please note that the user ID is hashed and needs to be reconciled in Adobe Campaign Standard (covered below).


Sync the Hashed User IDs with the Experience Cloud


This is a very important piece of this integration and is a required step to sync Customer or Declared IDs captured on the site with AAM or Customer Attributes and eventually with Campaign. This can be done easily in a Tag Manager like Launch.


Reconcile Triggers with the ID Service in Campaign Standard

The final step is to reconcile the an encrypted ID with a Declared ID data source in Adobe Campaign Standard. Below is an example of a Declared ID data source in ACS which is a new data source that needs to be created tied to the authenticated Customer ID by going to Administration -> Application settings -> Shared Data Sources. The link below the image covers this step in more detail.
Here's some more information on how to configure Triggers to send emails in Adobe Campaign Standard: 


Triggers are also Accessible via Adobe I/O

I recently wrote about Adobe APIs last time and covered how to create an integration in Adobe I/O but this link covers how to connect with the Triggers API.


Common Access Issues


I recently ran into some issues while trying to access Triggers and had to log tickets internally at Adobe so if you run into these issues, you'll have to ask your Campaign consultant to log these on your behalf.

The first issues I ran into was around not being able to create a trigger. The fix for this was to map the report suites to the Experience Cloud (covered above).

This is an issue which I'm currently facing for a client where I'm unable to create an authenticated Customer ID Data Source. I had to log an internal ticket to get this resolved.


Simplified Integration Architecture


Below is a simplified architecture diagram I put together to outline the integration between Analytics and Adobe Campaign Standard using Triggers. I've leveraged some internal documentation to provide more details primarily around steps 4-6. Below is a screenshot of that and a summary of the various steps.

1 - AEM Services the page
2a - ECID Service is called and relevant IDs are returned back to the page 

2b - If the visitor is logged in, an Authenticated "Declared ID" will be paired with the ECID
3 - Analytics image request fires and page/event level data gets sent to Adobe Analytics
4 - Real-Time Events sent via Analytics are detected using the Triggers State Machine
5 - Events are "enriched" with the Customer ID sent from the ID Service
6 - The enriched trigger events are sent through Pipeline Services and made available to Campaign. ACS "listens" for Trigger data that comes in as IDs starting with analyticsHitSummary
7 - Campaign queries data sources to build personalized multi-channel messages
8 - Campaign ingests/shares data from/to other data sources
9 - ACS delivers marketing messages across channels (Email, SMS) based on Triggers
10 - Customer clicks on the email and is routed back to the client website

So that was it! I hope you found this post helpful and hope that it will pique your interest in Triggers if you aren't already using it. Here's a link to another post where I've written about how to use webhooks to listen for Triggers.

Sunday, May 26, 2019

Access Adobe APIs Using Postman

APIs (Application Programming Interface) facilitate the transfer of information between two systems and are leveraged in a magnitude of industries today ranging from Travel to Retail. Adobe offers open source APIs in its solutions across the Document, Creative and Experience Clouds. Major companies leverage APIs to allow users to do the following:

  • Share content on Social Media (Facebook)
  • Retrieve flight information (Alaska Airlines)
  • Real-time access to item price and availability (Amazon)
  • Access maps using GPS (Google Maps)
  • Tracking information on shipments (FedEx)
  • Server Side Analytics Implementation (Adobe)

In this post, I will cover how to leverage Adobe APIs for Launch by Adobe and Audience Manager but these APIs are also available to use across some other Experience Cloud solutions such as Adobe Analytics and Adobe Target via Adobe I/O. We won't go into the basics of how to create integrations as there's a lot of documentation available on it but we'll cover the steps on how to call the APIs using authentication tokens in Postman. Please note that Audience Manager is not part of Adobe I/O yet and we'll specifically cover REST APIs to work with elements within the AAM UI. Let's jump right in!

Launch By Adobe APIs


The first solution we will cover is Launch where we'll create a property and you can use this format to create , data elements, rules, environments etc. The first step is to go to the Adobe I/O console which shows you all the integrations setup for your experience cloud org. In this case, we've created an integration with Launch APIs using Adobe I/O.


Make sure you either select the Developer role or the Admin role (while creating the integration) in order to create properties. I had chosen Approver as listed in the instructions in our documentation which walks us through how to create an integration but that didn't let me create a Launch property.



The following screen will show you your API credentials which you'll need to access the API and the ones which is required is API Key and Client Secret. We'll also need the Org ID that needs to be sent as an additional attribute in one of the requests we'll make in one of the API calls covered later in this post.


The next step is to generate the JWT (JSON Web Token) which will be used to authenticate and access the Launch APIs. The Private Key is generated as part of the public certificate (CRT file) creation process outlined in the Launch documentation. Please note that during the creation of the certification, an additional file called private.key is generated which contains this information.


The next step is to use the generated JWT to create a Launch token that will be used to access Adobe APIs. 


We need to now copy the generated JWT in Postman to create a new access token (valid for 24 hours) but before that, I want to share with you a tip which my colleague Gil Jimenez shared with me. The tip is to create global variables in Postman to store sensitive values that you'll need to access over and over again. You can do that by clicking on the Environment icon as shown below. The other thing you can do is to save these API calls as collections in the form of separate folders as shown below in the left section.


Generate a Launch Access Token

The next step is to generate an access token using the client_id, client_secret and jwt_token parameters by making a POST request to https://ims-na1.adobelogin.com/ims/exchange/jwt/ as explained here. Note how we're using the global variables to store sensitive information and accessing it in the call. We need copy this access token and store it. In our case, we're storing it in a separate variable calls access-token which is different that the jwt-token we need to create it.


Make a POST Request to Create a Property


We'll now create a new Launch property by making a POST request to https://reactor.adobe.io/companies/:company_id/properties as covered here. We can also create Launch rules, data elements, environments etc using this method. Below is how we can make this call.


Once we press send, we successfully (if everything goes well) create a Launch property as shown below. So using APIs, developers can literally do everything in Launch without  having to login to Launch. These APIs are open source and super powerful!


Make a GET Request for a Property


We'll now cover how make a GET request to https://reactor.adobe.io/properties/:id t
o fetch the details of the Launch property we just created by entering the property ID (starting with PR) which you can get from the response you get when you created the property. We're going to leverage some mandatory attributes defined here as shown below (The {{property}} value stores the property ID). You can use this to get access to a lot of information such as name, creation timestamp, domains etc. We can also fetch the details of data elements, rules and extensions among other things.



Adobe Audience Manager REST APIs


We'll now cover how to make GET and POST requests for AAM using Postman to access REST APIs (centered around the AAM UI) which allow you to perform some basic functions without logging into the AAM UI. Please note that there's another set of APIs called DCS APIs (send data to AAM) which I'll save for a future post.

Generate an AAM Access Token

As I mentioned earlier, the AAM APIs are not yet part of Adobe I/O so in order to access the REST APIs, we need the following credentials to access the APIs:
  • AAM API user name (AAM Admin UI)- Adobe consultant can provide this
  • AAM API password (AAM Admin UI)- Adobe consultant can provide this
  • AAM UI Username (bank.demdex.com login)
  • AAM UI Password (bank.demdex.com login)
Once you have these credentials, we can leverage Postman to get the access token which is only valid for a few minutes. Here we enter the AAM API and password using Basic Auth and send a POST request to https://api.demdex.com/oauth/token. 


The next step is to enter the AAM UI credentials as shown below to generate the access token that will be used to access additional APIs.





Make a POST Request to Create a Folder


We can access all AAM APIs in the Swagger API portal. The first thing we want to create is a folder by sending a POST call to https://api.demdex.com/v1/folders/traits/ using the Bearer Token auth type as shown below. The folder is "REST API Test" and it will be placed under the root "All Traits" folder.


Once the call goes through successfully, we should see the following message and the folder should show up in the AAM UI immediately.




Make a POST Request to Create a Trait


We'll now create a simple trait by sending a POST request to https://api.demdex.com/v1/traits/. The only additional attributes we're adding is the Folder ID and the Data Source ID which we can get from the AAM UI. The result is the following as shown in the screenshots below.

Please note that the API doesn't have a way to create traits in bulk so you can leverage BAAAM to do so which is a custom solution.



Make a GET Request to Retrieve all Traits


This is the final request in this post to get details about traits but you can retrieve data for segments, destinations, data sources etc. We send a GET request to https://api.demdex.com/v1/traits/ to retrieve all traits within our AAM instance. In our case, we can see that the trait we just created can be accessed using this method and you can export this JSON output and perform additional searches.


So, this was just a small glimpse into what's possible via APIs where we're able to perform the same tasks that we usually do in the Adobe solution specific UIs. This also shows us that almost everything that happens in the UI is driven by APIs so in a way we took a look under the hood of Launch and Audience Manager. Hope you found this post useful.

Saturday, April 20, 2019

Implement CTR tracking in Adobe Analytics via Launch

A client asked me to come up with a solution on how to track Click Through Rate (CTR) without tracking clicks due to server call constraints. Historically, I've always tracked Click Through Rate on a particular page by capturing the page name in an eVar along with a custom event for page view. For clicks, I've used a custom link name eVar and a custom click event. Then I would create a calculated metric which divides the custom clicks by custom page views (CTR %) and include that as a metric in the page name report. 

This client didn't want to use ActivityMap due to security constraints as they had some links which had borderline sensitive information. The other requirement was to control the logic that constitutes a "click" but a majority of my clients use ActivityMap though and I do like it. 
So, they asked me how to calculate CTR WITHOUT capturing a click event as they were concerned about server calls which is a fair ask. After a few unsuccessful tries, I eventually stumbled upon this article from Adam Greco. This post will cover how to implement Adam's solution using Launch and show how that materializes in actual reporting.

What we need to set this up

  • A Tag Management Solution like Launch or some other TMS
  • A custom plug-in called getPreviousValue which will allow us to capture the value of the previous page name
  • A JavaScript variable to capture the previous page name
  • Products string
  • s.pageName
  • 1 eVar (Merchandizing eVar to capture Page Name)
  • 2 events (Clicks, Page Impressions)

Implementation In Launch

The first step is add the getPreviousValue plug-in to the custom code section of the Adobe Analytics extension instead of a rule. This is how I implement plug-ins in Launch so that they're readily available across the board and populate on every hit if needed. 

  
The next step is to create a global page load rule tied to DOM Ready where we need to add some more custom code to track to wrap this solution up.



This is the crux of the solution where use the products string to create "fake" products and store the previous page name in a global variable called PrevPn. The code captures the current page name on page view along with a unique page view event (event7) on page view. On the next page, our code populates the current page name (eVar7) tied to event7 (Page Impressions) and also captures the previous page name in the same eVar7 along with a separate event8 (Page Clicks). Please note that we've assigned "fake" SKUs of "imp" and "click" in the products string which will show up in the Products report. Also, the if statements are key for this to work as each condition is meant to identify a page view with or without a previous page name.

Click to zoom in

Validation

In my sandbox site, I can see that I'm capturing both the current (company) and previous page name (activewear) in the products string after clicking a link.


Reporting

The first step is to create a calculated metric to calculate CTR (Page Clicks/Page Impressions) which I've shown here.




The next step is to put it all in a report to show how it all comes together. This report shows the merchandizing Page name along with the custom events and a calculated metric to capture CTR.




Drawback of this Solution and an Alternative


There's no way to differentiate which link performed well but an alternative will be to store the link name on click in a cookie and then retrieve that on the next hit in a separate merchandizing eVar within the products string. This will be in addition to the existing solution to track CTR based on the page name eVar.


So, that's a wrap and hope you like it! With this, we're able to implement a solution that captures the CTR on a page without tracking clicks thereby saving server calls.