Tracking Apps with Adobe’s new Experience Platform SDKs and the Edge Network

Tracking mobile apps has always been fun for me. Compared to measuring websites, apps are a more controlled environment, which is great for data consistency. Sure, there are some less-fun cases (like those pesky hybrid apps) but the general experience on major platforms like Android and iOS has been quite great! Changes even happen a bit slower compared to browsers and there are way less moving parts to keep track of.

Just like when tracking websites, Adobe has been most helpful in providing us the tools we need to collect data in the most effective and consistent way. If you have been tracking mobile apps with Adobe for a while, you will know about the similarities between websites and apps (like having a trackState function that increments Page Views and trackAction for Custom Links) and nice comfort features (like automatically tracking App ID, Launches, Upgrades, etc.) that make it so much easier for us to start collecting data and get a full picture of our users. This has been true for both the old 4.x line of SDKs and the newer 5.x SDKs.

But as we all know by now there are some big changes happening in the Adobe ecosystem. Next to Adobe Analytics, there now is Customer Journey Analytics on the Experience Platform. Data is not collected as Page Views and Link Clicks anymore but in any schema we can imagine. For the web, there is the new Web SDK to unify all Adobe libraries into one. And for mobile apps, we now have some new Launch extensions as well:

The new Experience Platform Edge Network extension in Launch

Having access to this exciting new technology made me wonder how it might change the way we implement Analytics into our mobile apps. So I did what I always do in those situation: I quickly created a sandbox environment and tested it all out! This post will take you along on the journey of my first implementation using the Experience Platform for apps and tell you about my first-hand experiences. Enjoy!

All good things follow a schema

As always when doing anything related to Experience Platform, we need to think about the data we want to capture ahead of time. That is because we need to create the XDM Schema, Dataset, and Datastream in Launch before we can track anything. For our little experiment, I just quickly created a new Experience Event Schema with the AEP Web SDK Mixin. I chose the latter because it offers quite a lot of fields we want to use and (to my knowledge) there is no mobile app specific mixin that Adobe provides. My Schema looks like this:

Simple Mobile App Analytics Schema

That’s plenty of fields for the start! Next, we create a Dataset based on that schema (which is like 3 clicks of work) so we have an actual destination for our data. If you only want to send data to “normal” Analytics (which I’ve done in a previous post) you wouldn’t even need that Dataset! Next, we head over to Adobe Experience Platform Data Collection Launch, by Adobe and create a new Datastream. In my case, I only want to send data to AEP, so I only activate the respective toggle:

Funneling our data from the Edge to AEP

That’s already all we have to do in terms of configuring AEP! In Launch, we now go to (or create) a mobile property and install the new extensions. In my case, I’ve added the Edge Network, Consent, and Identity extension next to the Mobile Core and Profile extensions:

Adding the new mobile AEP extensions to Launch

Believe it or not, but that is already all we have to do to get started with a basic implementation to track data. With this little setup, we can already send data to the Edge Network and everything behind it, like AEP or Analytics. Next, we need to implement the SDKs in our app.

Bringing the SDKs to the app

I like myself, which is why I try to avoid Apple products wherever I can. That is also true when developing, which is why I’m going to demonstrate my implementation on Android. Following the (honestly pretty awesome) instructions that Launch provides in the Environments tab, we can just copy-paste the code to our app. Mine looks like this after the dependencies and imports:

Implementing the Adobe SDKs into an Android App

With that little code, we can now send data to the Edge Network already! As you may already know, all data that is sent to AEP needs to follow the schema we defined before. For my example, I’ve implemented a simple tabbed navigation that, whenever I switch the tab, sends something similar to a Page View to AEP. My code for that looks like this:

@Override
public void onTabSelected(TabLayout.Tab tab) {
    String jsonString = "{" +
            "'eventType':'Mobile SDK Page View'," +
            "'web':{" +
            "'webPageDetails':{" +
            "'pageViews':{" +
            "'id':'" + tabs.getTabAt(tabs.getSelectedTabPosition()).getText().toString() + "', 'value': 1" +
            "}" +
            "}" +
            "}" +
            "}";
    Map<String, Object> xdmData = new Gson().fromJson(
            jsonString, new TypeToken<HashMap<String, Object>>() {}.getType()
    );

    ExperienceEvent experienceEvent = new ExperienceEvent.Builder()
            .setXdmSchema(xdmData)
            .build();
    Edge.sendEvent(experienceEvent, null);
}

Let’s step through this. From line 3-12, I define the actual payload for my request. For example, in line 8, I’m setting the Page Name to the title of the current tab and increment Page Views (which we have to do manually in AEP). Writing JSON in Java sucks, so here is the payload again, with proper indentation:

{
    "eventType": "Mobile SDK Page View",
    "web": {
        "webPageDetails": {
            "pageViews": {
                "id": "Tab 1",
                "value": 1
            }
        }
    }
}

You’ll notice how this JSON follows our AEP Schema, so AEP knows where to put our data. In the Java code, I then convert the JSON to a Hash Map and attach it to the Experience Event, which is then sent off to the Edge. Easy! Once we now trigger that action, the SDKs will tells us what they are doing in Logcat:

Successfully dispatched Experience Event

That works just perfectly! We also get a full print of the event that has been sent out, which in my case looks like this:

{
    "xdm": {
        "identityMap": {
            "ECID": [
                {
                    "id": "17185530724949200459088397104758368790",
                    "authenticatedState": "ambiguous",
                    "primary": false
                }
            ]
        }
    },
    "meta": {
        "state": {
            "entries": [
                {
                    "maxAge": 15552000,
                    "value": "general=in",
                    "key": "kndctr_9D8885579828F7F000101_AdobeOrg_consent"
                },
                {
                    "maxAge": 34128000,
                    "value": "CiYxNzE4NTUzMDcyNDk0OTIwMDQ1OTA4ODM5NzEwNDc1ODM2ODc5MFILCJXx_Z2ZLxgBIATwAZXx_Z2ZLw==",
                    "key": "kndctr_9D8885579828F7F000101_AdobeOrg_identity"
                }
            ]
        },
        "konductorConfig": {
            "streaming": {
                "lineFeed": "\n",
                "enabled": true,
                "recordSeparator": "\u0000"
            }
        }
    },
    "events": [
        {
            "xdm": {
                "web": {
                    "webPageDetails": {
                        "pageViews": {
                            "id": "Tab 1",
                            "value": 1
                        }
                    }
                },
                "eventType": "Mobile SDK Page View",
                "_id": "e4aecef2-02a6-42af-ba5e-6cf7404d39e1",
                "timestamp": "2021-05-23T12:09:23Z"
            }
        }
    ]
}

What’s most important is the lower part, starting at line 37, which contains the data we defined a second ago in the code. It really worked quite nicely!

Now if we want to track something similar to a Link Click, we can just as easy do that, still following our AEP Schema, like this:

{
    "eventType": "Mobile SDK Action",
    "web": {
        "webInteraction": {
            "linkClicks": {
                "id": "Mail Icon Click",
                "value": 1
            }
        },
        "webPageDetails": {
            "pageViews": {
                "id": "Tab 1",
                "value": 0
            }
        }
    }
}

Here is the funny part: If we want to set a Page Name, but not increment Page Views, we need to set it like above with a value of zero. If we just omit the value parameter completely, AEP will throw an error when trying to ingest it. Believe me, I’ve done it wrong the first time too and needed some time to figure out what I need to change! When we now check our data on AEP, we can see that it arrived just as we wanted:

Viewing our tracked data in Experience Platform

It worked just as expected! We are now able to track data to AEP and the Edge network, so we could send it to Analytics just as easy. But there is one thing I want to point out: There is not a lot of data there in addition to what we tracked manually. If we look at the environment namespace of the schema, there is just the User Agent set:

Not a lot of information is tracked by default

Where is all the information we would expect from the mobile SKDs? With the current ones, we get things like the App Version, Operating System, Days sind last upgrade, etc. None of that is there! Luckily, there is something we can do about that with Launch.

Enriching mobile data with Data Elements

One thing that I never needed to do with the 5.x SDKs is to use Rules and Data Elements in Launch. It could all be done in the app and would automatically contain a lot of useful information. Since that is not the case anymore with the new AEP SDKs, we need to enrich the data ourselves.

Once we create a new Data Element from the Mobile Core Extension, we can choose from quite an extensive list of options:

Mobile Data Elements

There we have exactly what I was looking for! All the information is still there, but now we need to actively choose what we want to have. I wish we wouldn’t need to do this, but what do I know. Once we create a Data Element like above, we can create a Rule and set it to trigger when data is sent to the Edge Network and let it modify the data:

Using Launch Rules in Mobile Apps

There are two actions to choose from: Attach Data and Modify Data. The difference is how they handle conflicts. When a variable is already set in the code of your app and you set it again in the Rule Action, Modify Data will overwrite what was set in the code while Attach Data will not. You can think of Attach Data as a fallback value, that only gets used if there is no value set.

So if we want to set the Carrier Name, we just have to create a Data Element for it and use it in the Attach Data action. Note how the syntax again follows our XDM Schema:

Setting variables in Mobile Apps with Launch

In our App, we can now watch our rule working in Logcat:

Modifying Data with Launch Rules

We can see that our JSON now looks like this. Note the new Carrier name field which we defined in our rule:

{
    "xdm": {
        "environment": {
            "carrier": "Android"
        },
        "web": {
            "webPageDetails": {
                "pageViews": {
                    "id": "Tab 1",
                    "value": 0
                }
            },
            "webInteraction": {
                "linkClicks": {
                    "id": "Mail Icon Click",
                    "value": 1
                }
            }
        },
        "eventType": "Mobile SDK Action",
        "_id": "343f96cf-a3e0-4122-adcf-57c3d724f57f",
        "timestamp": "2021-05-23T12:55:33Z"
    }
}

How cool is that! Now we can get a lot of the information that I was missing back, which is really awesome! But we can do even more!

Combining Event Data

There is an exciting new type of Data Element called “Free Form”, which lets us define a path in the event data that should be pulled into the Data Element like this:

Pulling Event Data into a Data Element

Let’s pretend for a second that we may want to combine the value from the Page Name (in xdm.web.webPageDetails.pageViews.id) and Link Name (xdm.web.webInteraction.linkClicks.id) in a new value. All we have to do is create two Data Elements for Page Name and Link Name and use it in a Attach Data action like this:

Combining data for mobile apps

The value {%%Page Name%%}: {%%Link Name%%} will be replaced at runtime to contain the actual page and link names. Pretty cool, right? One thing that is different from the web is that if any of the two Data Elements is empty, the whole value will not be set as there is no fallback value with mobile Launch.

Conclusion

This was a fun Saturday-afternoon project for me. Just as before, I have to say that I miss a bit of the comfort that the “old” SKDs provide compared to the Edge Network extension. It would be quite convenient to have the same variables auto-populated that we are so used to, like App ID, Operating System, etc. Besides that, the process was quite smooth and simple.

For myself, I will stick with the old SDKs for a while until the new ones are a bit more feature rich. There are some features I really like, like the Data Elements and options to modify and attach data, but it needs to be a bit more fleshed-out. Especially fallback values are a must for Data Elements in my opinion.

I hope you found this post useful. Have a great day!