perpetua.digital
Published on

Impression Counting in Target - Examples and Use Cases

Authors

Introduction:

Activity impression counting is exactly what it sounds like: counting the number of times a user has seen an activity. Well, more specifically, it is counting the number of times a user has seen a specific mbox parameter which is typically the name of the mbox or activity.

The most common use cases for this are:

  • Limiting the number of times an activity is shown to a user
  • Bucketing users into different experiences based on the number of times they have seen an activity
  • Showing different content to repeat vs. first-time users
  • Other fun things that involve counting

I admit those sound pretty boring, and when I write them out like that, they are. But hey, guess what, this is actually pretty interesting functionality and can be used for some fun things. For example, if you refresh this page, the introduction section title will change! Give it a try!

You can also count down! Act Quick! This coupon will expire after you see it 5 times!

Perpetua Digital

Your favorite Adobe Blog

Act Now! This coupon will expire in

Coupon Code: SAVENOW

Real Life

So these examples are kind of contrived, but they illustrate how profile parameters can be used to qualify users into different audiences based on the number of times they have seen an activity. How I have really used this in the past is to disqualify users from an activity. For example:

  • "Chaining" activities or experiences i.e., Users who have seen Activity A n times should be disqualified from it and shown Activity B instead. This is typically referred to as frequency capping.
  • Don't show the "new visitor" banner to users who have seen it more than twice.
  • Changing the "urgency" of messaging for repeat splash page visitors
  • "Lite" personalization messaging i.e., "Welcome Back" or "You have viewed this product n times!"

Counting with Profile Scripts

The counting is all done using profile scripts. If you've worked in Target for any length of time, you know that profile scripts are a powerful feature that allow you to run custom code on the server side to create profile attributes. The trivial examples usually used are assigning people into random groups or generating random numbers. While, yes, counting is also trivial, you can still do a lot with it.

A lot of the profile attribute counting examples out there are for at.js. If you are using the Web SDK, you might have tried this only to have them not work. This stems from the examples using mbox.name as an out of the box way to infer the mbox name. This does not seem to work anymore with the Web SDK. Maybe they changed the name and didn't tell anyone, but I couldn't figure it out. No matter, in place of mbox.name, you can just pass whatever parameter you want and use that as the count indicator.

Here is the profile script for the attribute that counts the number of times you've seen this blog post:

if (mbox.param('displayedScope').includes('activity-impression-counting-in-target')) {
  var postCount = user.getLocal('POST_COUNT') || 0
  postCount = postCount + 1
  user.setLocal('POST_COUNT', postCount)
  return postCount
}
return user.getLocal('POST_COUNT') || 0

And here is the sendEvent call that retrieves the activity and renders the content. Yes, it's basically straight from Adobe's rendering personalization content docs.

alloy('sendEvent', {
  xdm: {
    eventType: 'decisioning.propositionFetch',
  },
  decisionScopes: ['activity-impression-counting-in-target'],
  renderDecisions: false,
  data: {
    __adobe: {
      target: {
        displayedScope: 'activity-impression-counting-in-target',
      },
    },
  },
}).then(function (result) {
  const propositions = result.propositions || []
  propositions.forEach((proposition) => {
    if (proposition.scope === 'activity-impression-counting-in-target') {
      proposition.items.forEach((item) => {
        const { data } = item
        const { content } = data
        const { POST_COUNT } = content
        const counterElement = document.querySelector('#seenPost')
        if (counterElement && POST_COUNT) {
          counterElement.innerHTML = POST_COUNT
        }

        // send display event truncated for brevity
      })
    }
  })
})
// catch errors etc

Note the displayedScope parameter in the data.__adobe.target object. This is the parameter that is passed to the activity and ultimately to the profile script. I just made up the name displayedScope and used my mbox name as the value for the parameter; you can use whatever you want as your "counting" parameter name and value. Each time you refresh this page, the profile script will increment the count.

GIF of it COUNTING if you are too lazy to
refresh

Breaking the fourth wall over here!

Audience Setup

So now I have a counting profile parameter, here is how I can incorporate it into an activity. I want to setup 3 scenarios:

  • First time visitor (POST_COUNT = 1 or POST_COUNT is undefined)
  • Repeat visitor (POST_COUNT more than 1, but less than say 7)
  • Many time visitor (POST_COUNT more than 7)

Let's have it show the post count in the headline between visits 2-7. If it is your first time, it will say its your first time, and after 7 times it will say something like "you've been here many times".

I don't need several activities for this (although you could). Instead I'm going to have a single Experience Targeting (XT) type activity with what amounts to a cascading experience that changes as your POSTCOUNT parameter goes up. The profile parameter will be your audience qualification. It will serve to discount you from one audience and put you in another. It's important to note that profile scripts run _before the activity is returned, so in this case a first time visitor's POST_COUNT will be 1 not 0.

audience creation 1

New Visitors

audience creation 2

Repeat Visitors

audience creation 3

Many Time Visitors

Activity Setup

Because I'm rendering the content on my own, I'm returning JSON offers since that is the easiest to work with. It's also the best type of offer to use for cross platform (i.e., mobile and web) activities.

// first visit
{
  "POST_COUNT": "This is your first time reading this post!"
}
// repeat visit with post count
{
  "POST_COUNT": "You have seen this post ${user.POST_COUNT} times!"
}
// many time visitor
{
  "POST_COUNT": "You have seen this post many, many times!!!!!"
}

Here is the overview:

overview

I don't have any mbox 3rd party ID on this site, so you can reset everything by clearing cookies or using incognito mode. If I were doing this for real I would of course use a mbox 3rd party ID to tie your profile across devices and give a "true" count of how many times you've seen this post.


The concept is simple but the applications are endless. Refresh to add red squares.

Bonus Content - Setting up a Target sandbox environment for quick testing of activities

In my professional experience, Target environments are utilized to their fullest potential. Rather, setup and debugging is done in a real production or near production environment and often requires activating and deactivating activities, adding/removing QA query and mbox parameters, etc. This is tedious. I prefer to have an environment solely for Target that is a mirror of production where all activities are active so I can test without having to do much setup. Here is how I do it:

First, I have a staging environment for this site which is a mirror of production at staging.perpetua.digital. This staging domain uses my staging Launch environment. The staging Launch environment uses my staging Adobe Experience Platform Web SDK datastream.

web sdk datastreams

Datastream setup in the Web SDK Extension Configuration

Inside the Target configuration of my staging datastream, I have the environment ID of my staging Target environment.

target datastream setup

Target Datastream Configuration

Inside of Target Administration > Environments I have a staging environment. This environment is configured so that both active and inactive activities are returned. This means that I can fully test activities without having to activate them in production. I like this approach because its quick and there is no chance that I accidentally turn something on in production before its ready

target environment setup

The oft overlooked Target Environments settings

Even if you don't want to go to the lengths of hard coding anything, you can still setup an datastream with with all activities are active settings and use the AEP Debugger to switch into it via datastream overrides, etc. Try it out!

Sandbox Demo

Its easier to see this part all connected in a video than trying to understand it from screenshots :)