Implementing Personalization Based on User Actions and State in Adobe Target — Step-by-Step Guide

Introduction

In modern digital experiences, personalization based on real-time user actions and persisted user state is key to increasing engagement and conversions.
Adobe Target offers powerful tools to deliver dynamic, relevant content based on user behavior and profile data.

This post provides a practical step-by-step approach to implementing such personalization using segmentation, activities, trackEvent, profile scripts, and getOffer API.

Step 1: Define Your Personalization Goals

Start by identifying which user actions and states should drive personalized experiences.

Examples of Personalization Based on User Events and State:

  • Displaying different product recommendations based on a user’s clicks.
  • Personalizing content and CTAs based on user journey stage (e.g., showing “Continue registration” if the user completed Step 1 but didn’t finish).
  • Delivering targeted offers or messages based on previous interactions (e.g., showing a discount if a user visited the pricing page multiple times).

Step 2: Choose the Right Personalization Method

Option A: VEC (Visual Experience Composer)

  • Use VEC for seamless, visual content personalization, including banners, text, images, and layout modifications.
  • Best suited for A/B testing, experience targeting, and segment-driven personalization without requiring custom coding.
  • Limitation: VEC does not automatically update content mid-session when a user qualifies for a new segment. A page reload or new session is required for segmentation-based updates to take effect. If real-time updates are required within the same session, use trackEvent() with getOffer() and applyOffer().

Option B: Form-Based Activity with getOffer()

  • Use Form-Based + getOffer() for dynamic, real-time content updates without reloading the page.
  • Ideal for dynamic content updates, API-driven personalization, and real-time in-session experiences

Example for dynamic content fetch:

Even the required parameters including profile parameters through getOffer API.

adobe.target.getOffer({
mbox: "mboxname", // Also possible to send paramaters
params: {
"profile.attr": "value"
},
success: function(offer) {
console.log("Offer response:", offer);
if (offer && offer.length > 0) {
adobe.target.applyOffer({
mbox: "mboxname",
selector: "#test", //Element selector to apply the offer
offer: offer
});
} else {
console.log("No offer received");
}
},
error: function(status, error) {
console.log("Target error:", status, error);
}
});

Step 3: Ensure Cross-Device Personalization with mbox3rdPartyId

To maintain personalization across devices and browsers, pass mbox3rdPartyId globally on every page.

Example of setting mbox3rdPartyId globally:

<script>
function targetPageParams() {
return {
"mbox3rdPartyId": "[email protected]"
};
}
</script>

Important Notes:

  • Set this once globally, and it will be applied to all Adobe Target calls (page loads, trackEvent, getOffer).
  • Ensures consistent user identity and personalization even if users switch devices.
  • You do not need to pass it separately in each trackEvent or getOffer call once set globally.

Step 4: Capture Real-Time User Actions and States with trackEvent()

Use trackEvent() to capture user behavior and update profile attributes.

Example: Capture when a user reaches Step 2 of a form:

adobe.target.trackEvent({
"mbox": "mboxname",
"params": {
"profile.param1": "value"
}
});

This makes the user’s stage available for future personalization.

Step 5: Set Up Audience Segments in Adobe Target

Goal: Define who should see personalized content based on user state.

Navigate to Adobe Target → Audiences and create audience segments using profile attributes (e.g., profile.profile_attribute == 'value').

These segments control which experiences are shown to different users.

Use Profile Scripts to enhance the user-specific data for personalized experiences e.g. setting a default value, transforming the values and etc.

Example Profile Script for form stage:

if (profile.get('profileParam')) {
return profile.get('profileParam');
} else {
return "default value";
}

Step 6: Bringing It All Together — End-to-End Personalization Flow

Use Case Example: Personalizing Content Based on User Journey Stage

Goal: Personalize content or CTA based on user’s progress in a journey — like registration or onboarding.

Scenario:

  • User completed Step 1 (Contact Info) but didn’t proceed to Step 2 (Company Info). You can create additional stages as required to meet your business requirements e.g. stage_complete to notify user completed the process so that you can show different experience.
  • On return visit or on the same session, show personalized CTA:
    “You are almost done! Complete your registration now”

Implementation:

1. Configure mbox3rdPartyId:

Capture the unique mbox3rdPartyId, which represents the user across browsers and devices (e.g., login ID or email), as part of the targetPageParams.

<script>
function targetPageParams() {
return {
"at_property": "xxxxxxxxxx",
"mbox3rdPartyId": ""[email protected]"
};
}
</script>

2. Capture user’s stage when they proceed:

adobe.target.trackEvent({
"mbox": "user_form_stage",
"params":
{
"profile.form_stage": "step_2"
}
});

3. Segment users in Adobe Target:

Create two new audiences, use the Visitor Profile, and select the profile attribute e.g form_stage

4. Personalized content:

Create a new activity using the VEC Editor and enable different experiences for Step 1 and Step 2 users. Step 1 users will see the text: ‘Start your registration today!’, while Step 2 users will see: ‘You are almost done! Complete your registration now.’

This behavior works across browsers and devices as we are passing a unique email ID as the mbox3rdPartyId. However, the updated personalized message will only be visible after a page reload or a new session, as it does not update dynamically within the same session.

On Edge, after the user progresses to Stage 2 and reloads the page, the Step 2 personalized message is displayed as expected.

On Chrome, the same user is seeing the correct updated experience.

To display the updated experience within the same session, we can use an activity based on the Form Editor and the getOffer() API

Once the user stage change, use the getOffer and applyOffer methods to get and apply the updated experience content.

adobe.target.getOffer({
mbox: "user_form_stage", // Also possible to send paramaters
success: function(offer) {
console.log("Offer response:", offer);
if (offer && offer.length > 0) {
adobe.target.applyOffer({ // If needed, the offer can be parsed and applied to specific elements directly, without using the applyOffer API.
mbox: "user_form_stage",
selector: ".cmp-helloworld__title", //Use element id if required e.g #test
offer: offer
});
} else {
console.log("No offer received");
}
},
error: function(status, error) {
console.log("Target error:", status, error);
}
});

Now, personalized content is displayed within the same session based on the user’s journey completion. The user first completes the stage, event details are sent to Target, and the getOffer() and applyOffer() APIs are used to update and display the content dynamically within the same session. Additionally, the experience is consistently displayed across browsers and devices.

Apply Third-Party Data in Adobe Target

Integrating External Data Using a Data Provider

If personalization requires data from a third-party service (e.g., a CRM or loyalty system), Adobe Target Data Providers can be used to fetch and inject data dynamically.

Example: Fetching Loyalty Status from an External API — add the below script to the Head section of the page

 
<script>
var loyaltyDataProvider = {
name: "loyaltyDataProvider",
version: "1.0.0",
timeout: 2000,
provider: function(callback) {
console.log("Inside Loyalty Data Provider");

fetch("http://localhost:3000/api/[email protected]") // Replace with actual API
.then(response => response.json())
.then(data => {
console.log("Loyalty API Response:", data.loyaltyStatus);
callback(null,{
"profile.loyalty_Status": data.loyaltyStatus || "Basic", // Default value if missing
});
})
.catch(error => {
console.error("Data Provider Error:", error);
callback(eror);
});
}
};

// Register Data Provider in Adobe Target
window.targetGlobalSettings = {
dataProviders: [loyaltyDataProvider]
};

</script>

Now, use the loyalty_status profile parameters to create the required audience and personalize the experience, as we discussed earlier.

Sending External Data Using Profile API/Delivery API

The Single profile update API or Bulk profile update via batch can be used to share profile data from an external system to Adobe Target. These are update APIs, meaning the user must already exist in Adobe Target with a matching mbox3rdPartyId (in our case, we use mbox3rdPartyId for known users, but Adobe Target pcId can also be used when mbox3rdPartyId is not applicable). We will explore these topics in more detail in another post.

The Single Profile Update API updates existing profiles only and does not create new ones. Bulk Profile Update API v1 also updates existing profiles without creating new ones. However, Bulk Profile Update API v2 can both update existing profiles and create new ones if the specified pcId or mbox3rdPartyId does not exist in Adobe Target.

e.g. Sing profile API

https://<Client Code>.tt.omtrdc.net/m2/<Client Code>/profile/update?mbox3rdPartyId=<Unique Profile ID e.g email>&profile.<attr name>=<Value>

Now, the loyalty_Status will be updated in the Adobe Target profile, matching the mbox3rdPartyId for [email protected].

The updated profile details can be retrieved using the Profiles API. In addition to mbox3rdPartyId, tntId, and ECID can also be used to fetch the profile. In our case, mbox3rdPartyId is used to ensure cross-browser and cross-device support.

https://<Client Code>.tt.omtrdc.net/rest/v1/profiles/thirdPartyId/<mbox3rdPartyId>?client=<Client Code>

Profile attributes can be used to build segments and activities within Adobe Target. Profile updates made through the Single or Bulk Profile Update API are stored immediately and can be retrieved via the Profile Retrieval API. These updates typically apply in the next session after 30 minutes of inactivity when a new session starts. However, full propagation across Adobe Target’s infrastructure for segmentation and targeting may take up to 24 hours.

Key Takeaways

Use VEC for content changes based on user segments; changes apply in the next session or after a page reload.
Use trackEvent() and getOffer() for real-time, event-driven personalization within the same session.
Use Profile Scripts to store and recall user-specific states (e.g., form stage, user preferences).
Use mbox3rdPartyId to persist personalization across devices and sessions for known users.
Use DataProviders to fetch external data and share it with Adobe Target for personalization.
Use the Single or Bulk Profile Update API to sync external profile data with Adobe Target for persistent personalization.

By combining these tools, you can create highly personalized, seamless user journeys that adapt to user behavior and state.

Conclusion

Following this structured approach, you can build responsive, dynamic personalization in Adobe Target — adapting content in real-time, based on what users do and where they are in their journey.

Whether it’s onboarding flows, lead forms, product journeys, or dynamic offers, Adobe Target enables true stateful personalization when used with the right combination of events, profiles, and APIs.

Adblock test (Why?)