<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.pedromonjo.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.pedromonjo.com/" rel="alternate" type="text/html" /><updated>2026-03-01T16:47:52-05:00</updated><id>https://www.pedromonjo.com/feed.xml</id><title type="html">The Digital Marketing Architect</title><subtitle>Sharing my experience as an Adobe consultant</subtitle><author><name>Pedro Monjo</name></author><entry><title type="html">Conditional Adobe Target Rendering</title><link href="https://www.pedromonjo.com/2026/03/conditional-adobe-target-rendering.html" rel="alternate" type="text/html" title="Conditional Adobe Target Rendering" /><published>2026-03-01T00:00:00-05:00</published><updated>2026-03-01T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2026/03/conditional-adobe-target-rendering</id><content type="html" xml:base="https://www.pedromonjo.com/2026/03/conditional-adobe-target-rendering.html"><![CDATA[<p>When using Adobe Target, in the most general case, you always want to show the new experience: the page loads with the default content, Web SDK requests alternate content from Adobe Target, and this new content replaces the default content. This is how most of our customers use Adobe Target. However, there are legitimate reasons for not always wanting to show the response from Adobe Target. I will not explain here the use cases when this behavior makes sense, but rather how you need to set up Web SDK so that you can control the rendering.</p>

<!--more-->

<h2 id="proposition-impressions">Proposition Impressions</h2>

<p>You may think that the easy solution is just to prevent the Web SDK code, which renders the content in Adobe Target’s response, from running. However, it is not that easy, as I will explain below. Before I continue, I want to clarify that this response is usually called a proposition. The documentation uses this word, and so will I throughout this post.</p>

<p>Adobe Target has no way of knowing what has happened in the browser. It therefore considers the returned experience rendered and increases the impression counter for that experience. This counter, in turn, is used to calculate lift and confidence, the two main metrics of Adobe Target. In other words, if we do nothing, in cases where a proposition is not shown and the impression counter is increased, the reports will be incorrect.</p>

<p>Fortunately, there is a solution. Adobe Target can be told <strong>not</strong> to increment the impression counter automatically. Instead, a different process needs to be followed:</p>

<ol>
  <li>Request the proposition from Adobe Target, without incrementing the counter.</li>
  <li>Decide whether to render the proposition.</li>
  <li>If the proposition is rendered, send a view event back to Adobe Target.</li>
</ol>

<h2 id="web-sdk">Web SDK</h2>

<p>If you are using Adobe <del>Launch</del> Tags, you have to configure the Adobe Target send event action at the top of the page with these checkboxes.</p>

<ul>
  <li>Disable “guided events”. By default, Web SDK will try to make your life simpler by only allowing you to configure the typical options. We want to go our own way.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/guided-events.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/guided-events-300-3fb72bb9f.png" alt="Guided Events" srcset="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/guided-events-300-3fb72bb9f.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/guided-events-450.0-3fb72bb9f.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/guided-events-600-3fb72bb9f.png 2.0x"></a></li>
  <li>Disable “render visual personalization decisions”. You can only change this checkbox after disabling guided events.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/render-visual-personalization-decisions.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/render-visual-personalization-decisions-300-62cb73be3.png" alt="Render visual personalization decisions" srcset="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/render-visual-personalization-decisions-300-62cb73be3.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/render-visual-personalization-decisions-450.0-62cb73be3.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/render-visual-personalization-decisions-600-62cb73be3.png 2.0x"></a></li>
</ul>

<p>With these two parameters, you will get the propositions, but nothing else will happen: Adobe Target will not increase the counters, and Web SDK will not show the proposition. Now you have to decide whether you should render the propositions and, if so, render them and notify Adobe Target.</p>

<p>It is beyond the scope of this post to go into the details of how to decide and render the propositions. This will entirely depend on the business requirements for the decision and the structure of your website’s HTML. What I can do is guide you on how to implement it.</p>

<p>The Platform Web SDK tag extension provides a “Send Event Complete” event, which can be used to trigger a new rule when a response from a Send Event action is received. I can think of two options for how to use it:</p>

<ul>
  <li>If the decision to render can easily be constructed in a rule condition and the rendering is simple:
    <ul>
      <li>Add the condition to the rule</li>
      <li>Add an action of type “Apply propositions” and configure it to render the proposition.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/apply-proposition.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/apply-proposition-300-82b71827d.png" alt="Apply Proposition" srcset="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/apply-proposition-300-82b71827d.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/apply-proposition-450.0-82b71827d.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/apply-proposition-600-82b71827d.png 2.0x"></a></li>
    </ul>
  </li>
  <li>If the decision and rendering require custom code, add a “Custom code” action, where you will add the necessary code to evaluate the decision to show the proposition and handle its rendering. In your code, you will want to use <code class="language-plaintext highlighter-rouge">event.propositions</code> to get the response from Adobe Target.</li>
</ul>

<p>Refer to this <a href="https://experienceleague.adobe.com/en/docs/platform-learn/implement-web-sdk/applications-setup/setup-target#process-the-response-from-target">help page</a> for more information.</p>

<p>Finally, it is time to report back to Adobe Target whether the proposition has been rendered, which includes activities with <a href="https://www.pedromonjo.com/2016/08/analytics-for-target-a4t.html">Analytics for Target (A4T)</a>. This can easily be done using a normal send event action in Web SDK. Since this event is only for sending data, you can try to use the “collect” method:
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/proposition-display.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/proposition-display-300-11d59475a.png" alt="Proposition Display" srcset="https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/proposition-display-300-11d59475a.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/proposition-display-450.0-11d59475a.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2026/2026-03-01-conditional-adobe-target-rendering/proposition-display-600-11d59475a.png 2.0x"></a></p>

<p>In the previous screenshot, the XDM data is missing. It must contain the proposition information (the Adobe Target experience details) following this structure:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"_experience"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nl">"decisioning"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"propositions"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="err">&lt;PROPOSITION_ID&gt;</span><span class="p">,</span><span class="w">
        </span><span class="nl">"scope"</span><span class="p">:</span><span class="w"> </span><span class="err">&lt;PROPOSITION_SCOPE&gt;</span><span class="p">,</span><span class="w">
        </span><span class="nl">"scopeDetails"</span><span class="p">:</span><span class="w"> </span><span class="err">&lt;PROPOSITION_SCOPE_DETAILS&gt;</span><span class="w">
      </span><span class="p">}]</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The values for <code class="language-plaintext highlighter-rouge">propositions[].id</code>, <code class="language-plaintext highlighter-rouge">propositions[].scope</code>, and <code class="language-plaintext highlighter-rouge">propositions[].scopeDetails</code> are just a copy of the values that came from the Adobe Target response. You will have noticed that <code class="language-plaintext highlighter-rouge">propositions</code> is an array, in case you have multiple propositions to report on in a single call. Again, refer to this <a href="https://experienceleague.adobe.com/en/docs/platform-learn/implement-web-sdk/applications-setup/setup-target#process-the-response-from-target">help page</a> for your reference.</p>

<h2 id="alloyjs">Alloy.js</h2>

<p>If you are not using Adobe Tags and Web SDK, you will have to do everything above manually, in code. The documentation in Experience League explains it fairly well; you just need to find it, as it is a bit scattered. While I cannot provide boilerplate code, I can provide some guidance. Before I continue, I have to warn you that this code is completely untested.</p>

<p>To get the propositions and prevent Web SDK from rendering them, you will set <code class="language-plaintext highlighter-rouge">renderDecisions</code> to <code class="language-plaintext highlighter-rouge">false</code> and customize <code class="language-plaintext highlighter-rouge">decisionScopes</code> to your needs:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">alloy</span><span class="p">(</span><span class="dl">"</span><span class="s2">sendEvent</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
  <span class="na">personalization</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">decisionScopes</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">__view__</span><span class="dl">"</span><span class="p">],</span>
    <span class="na">sendDisplayEvent</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
    <span class="na">defaultPersonalizationEnabled</span><span class="p">:</span> <span class="kc">true</span>
  <span class="p">},</span>
  <span class="na">renderDecisions</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
  <span class="na">xdm</span><span class="p">:</span> <span class="p">{</span> <span class="cm">/* Your XDM */</span> <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Again, the decisioning and rendering are out of scope for this post.</p>

<p>The last step is to send the display event back to Adobe Target:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">alloy</span><span class="p">(</span><span class="dl">"</span><span class="s2">sendEvent</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span> 
  <span class="na">xdm</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">eventType</span><span class="p">:</span> <span class="dl">"</span><span class="s2">decisioning.propositionDisplay</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">_experience</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">decisioning</span><span class="p">:</span> <span class="p">[{</span>
        <span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">:</span> <span class="o">&lt;</span><span class="nx">PROPOSITION_ID</span><span class="o">&gt;</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">scope</span><span class="dl">"</span><span class="p">:</span> <span class="o">&lt;</span><span class="nx">PROPOSITION_SCOPE</span><span class="o">&gt;</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">scopeDetails</span><span class="dl">"</span><span class="p">:</span> <span class="o">&lt;</span><span class="nx">PROPOSITION_SCOPE_DETAILS</span><span class="o">&gt;</span>
      <span class="p">}],</span>
      <span class="na">propositionEventType</span><span class="p">:</span> <span class="p">{</span> 
        <span class="na">display</span><span class="p">:</span> <span class="mi">1</span> 
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>I have used these references:</p>

<ul>
  <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/collection/js/commands/sendevent/renderdecisions"><code class="language-plaintext highlighter-rouge">renderDecisions</code></a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/platform-learn/implement-web-sdk/applications-setup/setup-target#process-the-response-from-target">Process the response from Target</a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/collection/use-cases/personalization/render-manual-propositions">Manually render propositions</a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/collection/use-cases/personalization/display-events">Manage display events in the Web SDK</a></li>
</ul>

<h2 id="atjs">at.js</h2>

<p>What??? You are still using <code class="language-plaintext highlighter-rouge">at.js</code>? You should <em>really</em> consider migrating to Web SDK. Well, I should not be judgmental.</p>

<p>I will not explain how you should do it, as my knowledge of <code class="language-plaintext highlighter-rouge">at.js</code> is very rusty by now. What I will share is the following:</p>

<ul>
  <li>The process is the same as above: retrieve, and conditionally render and notify.</li>
  <li>Use the <a href="https://developer.adobe.com/target/implement/delivery-api/">Adobe Target Delivery API</a> for both retrieval and notification.</li>
  <li>For experience retrieval, you use <code class="language-plaintext highlighter-rouge">prefetch</code>.</li>
  <li>For display notification, you use <code class="language-plaintext highlighter-rouge">notifications</code>.</li>
</ul>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@austinchan?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Austin Chan</a> on <a href="https://unsplash.com/photos/this-is-the-sign-youve-been-looking-for-neon-signage-ukzHlkoz1IE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="MSA" /><summary type="html"><![CDATA[When using Adobe Target, in the most general case, you always want to show the new experience: the page loads with the default content, Web SDK requests alternate content from Adobe Target, and this new content replaces the default content. This is how most of our customers use Adobe Target. However, there are legitimate reasons for not always wanting to show the response from Adobe Target. I will not explain here the use cases when this behavior makes sense, but rather how you need to set up Web SDK so that you can control the rendering.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/personalized-content.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-03-01-conditional-adobe-target-rendering/personalized-content.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AI at Adobe</title><link href="https://www.pedromonjo.com/2026/02/ai-adobe.html" rel="alternate" type="text/html" title="AI at Adobe" /><published>2026-02-15T00:00:00-05:00</published><updated>2026-02-15T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2026/02/ai-adobe</id><content type="html" xml:base="https://www.pedromonjo.com/2026/02/ai-adobe.html"><![CDATA[<p>Adobe has been announcing multiple Artificial Intelligence (AI) capabilities as part of the Adobe Experience Cloud. This is just an evolution of Adobe Sensei, the collection of Machine Learning (ML) features that have been released over the last 10+ years. However, with AI things are getting more complicated and it is not always easy to understand where each feature belongs to. I wanted to summarize and classify the features, both for you and me, as our memory is fragile.</p>

<!--more-->

<p>Before I continue, if you have landed on this page looking for AI tools related to the Adobe Document Cloud or the Adobe Creative Cloud, I am afraid I have very little to say about them. Photoshop is as alien for me as Adobe Experience Platform is for you.</p>

<p>With that being said, let’s get to the heart of the matter. I have classified these AI capabilities in three broad groups: assistants, content optimizers and end user support. In the remainder of this post I will explain each one.</p>

<h2 id="assistants">Assistants</h2>

<p>Adobe uses the icon <svg height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg" focusable="false" aria-hidden="true" role="img" class="  ZuUmpre12 FuUmpre12 _va12 I67logd12"><path d="m6.25,18.99805c-.09961,0-.19922-.01953-.29395-.05957-.27637-.11816-.45605-.38965-.45605-.69043v-3.25h-.75c-2.06738,0-3.75-1.68262-3.75-3.75v-5.5c0-2.06738,1.68262-3.75,3.75-3.75h3.95312c.41406,0,.75.33594.75.75s-.33594.75-.75.75h-3.95312c-1.24023,0-2.25,1.00977-2.25,2.25v5.5c0,1.24023,1.00977,2.25,2.25,2.25h1.5c.41406,0,.75.33594.75.75v2.23633l2.88379-2.77637c.13965-.13477.32617-.20996.52051-.20996h4.8457c1.24023,0,2.25-1.00977,2.25-2.25v-1.27148c0-.41406.33594-.75.75-.75s.75.33594.75.75v1.27148c0,2.06738-1.68262,3.75-3.75,3.75h-4.54297l-3.93652,3.79004c-.14258.1377-.33008.20996-.52051.20996Z" fill="var(--iconPrimary, #222)"></path><path d="m13.27832,9.08301c-.18848,0-.37793-.04883-.54883-.14746-.41602-.23926-.62695-.71484-.52637-1.18359l.45996-2.125-1.45996-1.61035c-.32227-.35547-.37793-.87207-.13867-1.28711.24023-.41504.7207-.62598,1.18359-.52637l2.125.45996,1.61035-1.45996c.35547-.32129.875-.37598,1.28711-.13867.41602.23926.62695.71484.52637,1.18359l-.45996,2.125,1.45996,1.61035c.32227.35547.37793.87207.13867,1.28711-.24023.41602-.7168.62891-1.18359.52637l-2.125-.45996-1.61035,1.45996c-.20801.18848-.47168.28613-.73828.28613Zm2.50391-1.88672l-.00293.00293.00293-.00293Zm-2.62988-3.2627l.75977.83789c.23633.25781.33496.62109.26074.96875v.00098l-.23926,1.10645.83789-.75977c.25879-.23633.62598-.33398.96875-.26074l1.10742.23926-.75977-.83789c-.23633-.25781-.33496-.62109-.26074-.96875l.23926-1.10742-.83789.75977c-.25781.2373-.62305.33691-.96875.26074l-1.10742-.23926Zm-.35156,1.8457l.00293.00293-.00293-.00293Zm-.09473-.35352h0Zm4.49023-1.20801l.00293.00293-.00293-.00293Zm-2.97559-1.41699l-.00293.00293.00293-.00293Z" fill="var(--iconPrimary, #222)"></path><path d="m7.93262,11.50391c-.12891,0-.25781-.0332-.375-.10059-.28223-.16309-.42676-.48926-.3584-.80762l.17773-.82031-.56348-.62109c-.21875-.24121-.25684-.59668-.09375-.87891s.49121-.4209.80762-.3584l.82031.17773.62109-.56348c.24219-.21875.5957-.25684.87891-.09375.28223.16309.42676.48926.3584.80762l-.17773.82031.56348.62109c.21875.24121.25684.59668.09375.87891s-.49219.42383-.80762.3584l-.82031-.17773-.62109.56348c-.1416.12793-.32227.19434-.50391.19434Z" fill="var(--iconPrimary, #222)"></path></svg> to denote an AI assistant. You will see it in multiple places, for example:</p>

<ul>
  <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/ai-assistant/home">Adobe Experience Platform</a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/journey-optimizer/using/content-management/ai-assistant/ai-assistant-landing-page">Adobe Journey Optimizer</a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-overview/cja-b2c-overview/ai-assistant">Customer Journey Analytics</a></li>
  <li><a href="https://experienceleague.adobe.com/en/docs/target/using/introduction/assistant-ai/ai-assistant">Adobe Target</a></li>
</ul>

<p>All these assistants have one thing in common: they are meant to help the user of the corresponding tool. Think of them as a virtual intern that takes your orders (your prompt) and works on them in the background. The initial use case was to help you learn more about the tool. However, they are still evolving and, over time, they will do more and more.</p>

<p>Disclaimer: what I am going to explain is not <em>currently</em> available; I am sure it will be in the future. In my wildest dreams, I envision a meta assistant or assistant orchestrator where, based on a brief, it would create every step of a campaign. For example, for an email campaign you would get:</p>

<ul>
  <li>The email content, including A/B testing and personalization</li>
  <li>The AJO campaign, ready to be activated</li>
  <li>The RTCDP segment for the AJO campaign</li>
  <li>The CJA dashboard for this campaign</li>
</ul>

<h2 id="content-optimizers">Content Optimizers</h2>

<p>If you are like me and come from the data world, you may not be that familiar with the content world. We like to think of AEP as the center of our universe. However, once you learn and understand the predominant role of Adobe Experience Manager (AEM), you realize how big <a href="https://www.pedromonjo.com/2023/09/data-content.html">the world beyond data</a> is. While I am not an AEM expert, I can tell how it plays a key role in big corporations. All my clients use it as their content management system and it is a central component of their digital marketing stack.</p>

<p>It should be no surprise, then, that Adobe has released AI tools specifically designed for content:</p>

<ul>
  <li><a href="https://experienceleague.adobe.com/en/docs/experience-manager-sites-optimizer/content/home">AEM Sites Optimizer</a>. It analyzes and improves the performance of websites built on AEM. Not only does it audit your website, but it can also apply the changes to AEM to improve it.</li>
  <li><a href="https://experienceleague.adobe.com/en/docs/llm-optimizer/using/home">Adobe LLM Optimizer</a>. With the advent of Large Language Models (LLM) and the chat engines in front of them, webmasters want their websites to rank high in the popular LLMs, so that they become the reference of certain prompts. This is called <a href="https://www.pedromonjo.com/2023/09/data-content.html">Generative Engine Optimization</a> (GEO). Well, LLM Optimizer was designed with this goal in mind: help websites become the reference of AI chat assistants.</li>
</ul>

<h2 id="end-user-support">End User Support</h2>

<p>You are all familiar with those chat tools <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32"><defs><style>.cls-1 {fill: #4b4b4b;}</style></defs><path class="cls-1" d="M17.99316,30.06445a1.98415,1.98415,0,0,1-1.48828-.67383L10.82422,23H5.05957A5.0659,5.0659,0,0,1,0,17.93945V7.05957A5.06506,5.06506,0,0,1,5.05957,2H26.93994A5.06548,5.06548,0,0,1,32,7.05957V17.93945A5.06632,5.06632,0,0,1,26.93994,23H20v5.0625a1.98517,1.98517,0,0,1-1.28955,1.86914A2.00829,2.00829,0,0,1,17.99316,30.06445ZM5.05957,4A3.06278,3.06278,0,0,0,2,7.05957V17.93945A3.06361,3.06361,0,0,0,5.05957,21h6.21387a.99954.99954,0,0,1,.74756.33594L18,28.0625V22a.99974.99974,0,0,1,1-1h7.93994A3.06372,3.06372,0,0,0,30,17.93945V7.05957A3.06288,3.06288,0,0,0,26.93994,4Z"></path><g><circle class="cls-1" cx="9.70414" cy="12.5" r="2.09862"></circle><circle class="cls-1" cx="16" cy="12.5" r="2.09862"></circle><circle class="cls-1" cx="22.29586" cy="12.5" r="2.09862"></circle></g></svg> that many websites have. They are mainly call deflectors: they try to help end users who have basic questions, so that they can self-serve and do not need to call the client support center. However, the existing chat tools are very basic. Every time I have tried to use one, I have ended up having to interact with a human, as the tool could not do what I needed.</p>

<p>With <a href="https://experienceleague.adobe.com/en/docs/brand-concierge/content/home">Adobe Brand Concierge</a>, Adobe is entering this space, offering an AI tool to manage end user conversations. This is one of the rare occasions where the Adobe Experience Cloud offers a tool that is specifically designed for the end users, the customers of our customers (anybody remembers Adobe Survey?). This tool is in its infancy, but if it delivers on the promise, we will finally get a chat that works.</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@boliviainteligente?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">BoliviaInteligente</a> on <a href="https://unsplash.com/photos/a-close-up-of-a-computer-processor-with-many-components-frbBBb2l2SI?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[Adobe has been announcing multiple Artificial Intelligence (AI) capabilities as part of the Adobe Experience Cloud. This is just an evolution of Adobe Sensei, the collection of Machine Learning (ML) features that have been released over the last 10+ years. However, with AI things are getting more complicated and it is not always easy to understand where each feature belongs to. I wanted to summarize and classify the features, both for you and me, as our memory is fragile.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-02-15-ai-adobe/ai.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-02-15-ai-adobe/ai.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Thinking is Cheap</title><link href="https://www.pedromonjo.com/2026/02/thinking-is-cheap.html" rel="alternate" type="text/html" title="Thinking is Cheap" /><published>2026-02-01T00:00:00-05:00</published><updated>2026-02-01T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2026/02/thinking-is-cheap</id><content type="html" xml:base="https://www.pedromonjo.com/2026/02/thinking-is-cheap.html"><![CDATA[<p>Imagine the following scenario. You have just purchased a plot with sea views. You are eager to build a house to start enjoying it. However, you want to save money and do not hire an architect to design the house. Instead, you go directly to the construction company. They ask for the blueprint, but you tell them that it is not needed, that they should just look at the houses in the neighborhood and build something similar. Would you do that? I am sure the answer is “no”. So, why do we see this approach so often in technology?</p>

<!--more-->

<h2 id="execution-is-expensive">Execution is Expensive</h2>

<p>While the situation with the house described above is completely imaginary, I have seen this in technology. It goes without saying that they tend to end in fiasco.</p>

<p>I was once assigned to a project, where the customer had already implemented the data architecture of the <a href="https://www.pedromonjo.com/category/platform/">Adobe Experience Platform</a> (AEP). Schemas and datasets had been created in the production sandbox, they were already loading data, and some destinations had been configured. With this part of the implementation done, they asked the business for use cases. To their horror, very few could be delivered with that implementation. The problem was that the IT department had implemented what they thought was the right design for the data, without ever asking the business team for their input.</p>

<p>After multiple discussions with this customer, we made the hard decision to reset the production sandbox. I actually clicked the button, I felt really bad. That probably was $500k (or more) going down the drain.</p>

<p>Unfortunately, this is not an isolated case; I still see this behavior in some of the engagements I have been part of. IT directors argue that a discovery and design phase is a waste of time and money, that it is just a “lift and shift” and they need to show value quickly. I have bad news for them.</p>

<h2 id="thinking-is-cheap">Thinking is Cheap</h2>

<p>While I am not in sales, I work closely with them. A typical hurdle they face when negotiating contracts with customers is that architects, business consultants, and digital strategists are expensive. I beg to differ. I am not going to dispute that our hourly rate is higher than that of a developer, but:</p>

<ul>
  <li>In a healthy project, the number of architect or strategist hours should always be significantly smaller than the total development time. We are in technology, not philosophy.</li>
  <li>Fixing a mistake on a whiteboard or redoing an architecture diagram that does not support the use cases costs a fraction of having to redo an implementation that is not fit for purpose.</li>
  <li>As I have explained multiple times, you must start with the <em>why</em>, and to find this why, you need to spend time thinking before you start developing.</li>
</ul>

<p>I can understand the anxiety to show value. In my post <a href="https://www.pedromonjo.com/2025/01/buy-raspberry-pi.html">Buy a Raspberry Pi</a>, I explain how our customers expect a return on their investment when they buy enterprise-grade software like the Adobe Experience Cloud. However, this should not be an excuse to put the cart before the horse.</p>

<p>In summary, and based on my experience, I can confidently say that “thinking is cheap”.</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/photo-of-woman-in-deep-thought-3768144/">Photo by Andrea Piacquadio</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[Imagine the following scenario. You have just purchased a plot with sea views. You are eager to build a house to start enjoying it. However, you want to save money and do not hire an architect to design the house. Instead, you go directly to the construction company. They ask for the blueprint, but you tell them that it is not needed, that they should just look at the houses in the neighborhood and build something similar. Would you do that? I am sure the answer is “no”. So, why do we see this approach so often in technology?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-02-01-thinking-is-cheap/thinking.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-02-01-thinking-is-cheap/thinking.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Support Shopping</title><link href="https://www.pedromonjo.com/2026/01/support-shopping.html" rel="alternate" type="text/html" title="Support Shopping" /><published>2026-01-18T00:00:00-05:00</published><updated>2026-01-18T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2026/01/support-shopping</id><content type="html" xml:base="https://www.pedromonjo.com/2026/01/support-shopping.html"><![CDATA[<p>I have been at Adobe for more than 13 years, and this has been my only job as a consultant. I explain this because I do not have previous experience in other consulting roles. However, during all this time I have regularly seen a behavior that I want to talk about today: support shopping.</p>

<!--more-->

<h2 id="what-is-support-shopping">What is Support Shopping?</h2>

<p>I do not think that there is a standard definition for this concept. In fact, I heard it for the first time from a coworker not that long ago. Since then, though, I have used it when needed and everybody understood me. If I had to provide such a definition, it would be something like:</p>

<blockquote>
  <p>The activity of requesting help from multiple people simultaneously, without telling them that you have also asked others.</p>
</blockquote>

<p>I am sure you have seen this behavior in the past. Someone has a problem with a technology, and they ask their technical representative and their account manager, and open a ticket with support. I understand why our clients do that: they do not always know who to ask or they are in a hurry and need an urgent response. However, there are important downsides.</p>

<h2 id="the-issue-with-support-shopping">The Issue with Support Shopping</h2>

<p>The main problem with this behavior is that the outcome can make things worse.</p>

<p>Let’s consider a scenario where a client wants to know what the best color in a particular scenario is. The client raises the question to the provider, asking four different people. Three reply “blue”, which is the one that the provider has documented as the best color, but one outlier misunderstands the question and says “pink”. It turns out that the client wanted pink as the color, as it is the color they already have. So, they go with pink. Later, when it is clear that this was the wrong color, they will claim that it is the provider’s fault, as they recommended pink.</p>

<p>I want to be very clear about one point: the person who replied “pink” is not to be blamed. Any of us could have done it.</p>

<p>The more I work with internal teams at Adobe, the more I understand the origin of this problem:</p>

<ul>
  <li>Client Care manages dozens, if not hundreds of tickets daily. Very few are problems with the Adobe products, most are related to issues with the client implementation. They do not have the knowledge or the time to research the exact details, and will mostly fall back to the published best practices.</li>
  <li>Customer Success Managers (CSM) are mostly non-technical employees. They understand the technology at a high level, but their role is about value realization, not Java code.</li>
  <li>Account Directors (AD) lead the sales team, not the implementation team.</li>
  <li>Technical Account Managers (TAM) are technical and have the knowledge to support the customers, have access to backend tools, but they are not always asked first or may not have been exposed to the context needed to answer correctly.</li>
  <li>Consultants usually know the technical details of the implementation and most likely they have the best answer, but not all our clients have a consulting engagement.</li>
</ul>

<h2 id="my-solution">My Solution</h2>

<p>OK, we have a problem. What do we do about it?</p>

<p>The starting point is to avoid support shopping altogether. Instead, a process should be agreed with the technology provider. I cannot provide a generic process, as there are too many permutations and I have only seen what we do at Adobe.</p>

<p>What I can explain is what I have done with some customers, where I have been involved as an Enterprise Architect.</p>

<ol>
  <li>All issues should be routed first to me or the TAM. We are in the best position to evaluate the problem.</li>
  <li>If this is something we (EA or TAM) can resolve, we just go ahead and do it.</li>
  <li>If we need someone else, but we know who this other person should be, we engage them.</li>
  <li>If the problem is related to not having a license, we will talk with the AD.</li>
  <li>Finally, if we see this is a product issue, we will help the client open a ticket with Client Care, making sure this ticket has all the relevant information, and we will follow up with Client Care.</li>
</ol>

<p>Let me know in the comments if you have seen this behavior or you have implemented a different solution.</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@jezar?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jezael Melgoza</a> on <a href="https://unsplash.com/photos/group-of-people-standing-To5wAJDt1IM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[I have been at Adobe for more than 13 years, and this has been my only job as a consultant. I explain this because I do not have previous experience in other consulting roles. However, during all this time I have regularly seen a behavior that I want to talk about today: support shopping.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-01-18-support-shopping/shopping.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-01-18-support-shopping/shopping.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AEP Connecting Tissue</title><link href="https://www.pedromonjo.com/2026/01/aep-connecting-tissue.html" rel="alternate" type="text/html" title="AEP Connecting Tissue" /><published>2026-01-04T00:00:00-05:00</published><updated>2026-01-04T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2026/01/aep-connecting-tissue</id><content type="html" xml:base="https://www.pedromonjo.com/2026/01/aep-connecting-tissue.html"><![CDATA[<p>When licensing a tool like the Adobe Experience Platform (AEP), you should expect an implementation effort at the beginning. One area that is often overlooked is the integration between AEP and other tools. Most of my customers deal with it as with any other integration, but to some it has come as a surprise.</p>

<!--more-->

<h2 id="friction-point">Friction Point</h2>

<p>The reason why I wanted to write this post in the first place is to clarify the unnecessary friction that integrating AEP with the rest of the ecosystem has caused. Some of my previous customers had an expectation that this tool can connect to any data source or destination seamlessly, without any additional development.</p>

<p>AEP, like any other advanced software, was built to be as generic as possible. We have thousands of customers, each with a completely different setup. It is impossible to build a piece of software that supports every single case.</p>

<p>As I was preparing this post, I remember my days with <a href="https://www.pedromonjo.com/category/analytics-tips/">Adobe Analytics</a> and <a href="https://www.pedromonjo.com/category/aam/">Adobe Audience Manager</a>, when this was not a major issue. I guess that, since these tools were very specific and <em>simple</em> compared to AEP, such an expectation did not exist. I also assume that Adobe Experience Manager (AEM) requires a large implementation, which allows for developer time to create any custom integration.</p>

<h2 id="out-of-the-box">Out of the Box</h2>

<p>Let’s start with the out-of-the-box integrations that already exist. AEP boasts a large number of <a href="https://experienceleague.adobe.com/en/docs/experience-platform/sources/home">data sources</a> and <a href="https://experienceleague.adobe.com/en/docs/experience-platform/destinations/catalog/overview">destinations</a>.</p>

<p>The catalog has dozens of integrations; I stopped counting a long time ago. Some of the categories that you will see are:</p>

<ul>
  <li>Other Adobe applications</li>
  <li>Advertising platforms</li>
  <li>Cloud storage</li>
  <li>CRM platforms</li>
  <li>Databases</li>
</ul>

<p>Expect more to be added and feel free to suggest new ones to your Adobe representative.</p>

<p>Most of my customers have all they need in the existing catalog. If you find one that suits you, just go ahead and use it. However, be mindful that you cannot change the behavior other than what is available in the configuration wizard.</p>

<h2 id="custom-integrations">Custom Integrations</h2>

<p>This is where the friction I mentioned at the top arises. I have had customers who were annoyed with me when I told them that the integration they wanted to set up was not possible. I would argue that nobody should be surprised when licensing SaaS tools as complex as AEP, when a custom layer needs to be built. In other words, my point is that, if you are implementing AEP, you should expect some level of custom integration, which will require development effort.</p>

<p>These are some examples I have seen where a custom integration was needed:</p>

<ul>
  <li>Source data format needs to be adapted to XDM format to take full advantage of AEP’s features.</li>
  <li>Connecting to a data source needs to follow a particular security standard not currently supported.</li>
  <li>AEP sends the data too fast to a destination.</li>
</ul>

<p>The solutions I have seen in the past can be grouped into two groups: ETLs and microservices. Let me know in the comments if you used other approaches.</p>

<h3 id="etls">ETLs</h3>

<p><a href="https://en.wikipedia.org/wiki/Extract,_transform,_load">Extract-Transform-Load</a> (ETL) tools have existed for a very long time. With them, you can adjust the format of a data source to the format expected by a destination. I do not have the numbers, but I believe that most AEP implementations use ETLs to extract marketing data from internal systems and convert it to XDM or CSV format to be ingested by AEP. The main limitation of an ETL tool is that it usually only supports batch processes.</p>

<p>I would assume that all my customers would have, at least, one ETL tool. To my dismay, I have had customers who refused to use one.</p>

<h3 id="microservice">Microservice</h3>

<p>I am using here the term “microservice” very loosely. I am referring to a custom development that receives data from a source and does all the necessary adjustments so that the destination can receive the data. I know it sounds like an ETL, but there are a couple of major differences:</p>

<ul>
  <li>Microservices can support real-time use cases.</li>
  <li>Microservices can do anything that you can do with a programming language, which is more than what ETLs can usually do.</li>
</ul>

<p>Let me share a few examples of microservices my customers have needed:</p>

<ul>
  <li>The <a href="https://experienceleague.adobe.com/en/docs/experience-platform/destinations/catalog/streaming/http-destination">HTTP API connection</a> was sending the data too fast and in bursts, causing the downstream system to crash. This destination was designed to be as fast as possible, so it is not possible to make it slower. The solution was to build a microservice with a large buffer, to adjust the speed.</li>
  <li>An Adobe Journey Optimizer (AJO) journey required accessing data in a way that AJO custom actions could not support. A microservice was created, which would receive a call from a custom action, retrieve the additional data, and send it in an event back to AEP, which was captured by the journey.</li>
  <li><a href="https://experienceleague.adobe.com/en/docs/journey-optimizer/using/orchestrate-journeys/about-journey-building/using-custom-actions">AJO Custom Actions</a> send calls individually, whereas a particular receiver end required microbatching and a slower rate. A microservice took care of this mismatch.</li>
</ul>

<p>In summary, with AEP (and, I assume, with our competitors), you should always expect to develop a connecting layer around AEP.</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@barkiple?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">John Barkiple</a> on <a href="https://unsplash.com/photos/assorted-electric-cables-l090uFWoPaI?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[When licensing a tool like the Adobe Experience Platform (AEP), you should expect an implementation effort at the beginning. One area that is often overlooked is the integration between AEP and other tools. Most of my customers deal with it as with any other integration, but to some it has come as a surprise.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-01-04-aep-connecting-tissue/connections.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2026/2026-01-04-aep-connecting-tissue/connections.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">2025 Retrospective</title><link href="https://www.pedromonjo.com/2025/12/2025-retrospective.html" rel="alternate" type="text/html" title="2025 Retrospective" /><published>2025-12-22T00:00:00-05:00</published><updated>2025-12-22T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2025/12/2025-retrospective</id><content type="html" xml:base="https://www.pedromonjo.com/2025/12/2025-retrospective.html"><![CDATA[<p>Another year comes to a close. Today is my first day of PTO, so I am still not fully feeling it. I have woken up at the usual time because I have a lot to do in the coming days before I go on a trip. However, it is the perfect moment of the year to reflect and look back.</p>

<!--more-->

<h2 id="life">Life</h2>

<p>I think that most of us can agree that the political situation all around the world has seen better days. Most big and influential countries have had their fair share of drama. I have lived in three countries and all three have major issues. While it would be great if I could ignore all those problems, it is impossible, at least for me. I guess I worry too much about what would happen if things go really wrong.</p>

<p>My work at Adobe is going well. Looking back into this year that is ending makes me realize how much I have learned. I feel more and more confident in my role as a manager (part-time), and I like working with my customers, with whom I have a very good working relationship. I still go to the office three days a week, which gives me the opportunity to meet my coworkers.</p>

<p>The most significant change that I have noticed is the continuous disruption caused by AI. I can see how knowing the technology behind AI can have an impact. In fact, I recommend that you learn AI as deeply as you can. I have understood <a href="https://en.wikipedia.org/wiki/Neural_network">neural networks</a> for many years, but the AI tools we have today go way beyond neural networks. Being an expert in prompt engineering will help you with your day-to-day, but if you want to be more employable you need to understand how <a href="https://en.wikipedia.org/wiki/Large_language_model">LLMs</a> work.</p>

<p>I have some vague knowledge and, to catch up a bit with this technology, I have just purchased a new computer with a powerful enough processor and lots of RAM, so I can play with <a href="https://ollama.com/">Ollama</a> and other related tools. I do not think I can ride the AI wave, but at least I will be able to take more advantage of it.</p>

<p>For us working at Adobe, not only do we need to know how to use conversational AI tools, but also know how our own AI tools work: <a href="https://firefly.adobe.com/">Firefly</a>, <a href="https://www.adobe.com/acrobat/generative-ai-pdf.html">AI Assistant for Acrobat Studio</a>, or <a href="https://experienceleague.adobe.com/en/docs/brand-concierge/content/home">Adobe Brand Concierge</a>. I have seen parts of the architecture behind the latter and it is anything but simple.</p>

<h2 id="blog">Blog</h2>

<p>I always want to talk about my blog, as it is an important part of my life. I usually publish every two weeks. It is a lot of effort. For context, a standard post takes around four hours. If I want to make it more complex, with code examples or steps in the UI, it will take even longer. I wish I had more time to write more often.</p>

<h3 id="metrics">Metrics</h3>

<p>Let me share a few metrics with you:</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-22-2025-retrospective/2025-basic-metrics.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/2025-basic-metrics-300-c7434b6e5.png" alt="2025 Basic Metrics" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/2025-basic-metrics-300-c7434b6e5.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/2025-basic-metrics-450.0-c7434b6e5.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/2025-basic-metrics-600-c7434b6e5.png 2.0x"></a></p>

<p>I was expecting this drop in numbers, so I am not concerned:</p>

<ul>
  <li>Most of 2025 was flat, except for something weird around October. This means a steady flow of visits, which is what I would expect.</li>
  <li>The metrics in <a href="https://www.pedromonjo.com/2024/12/2024-retrospective.html">2024</a> showed an increase in traffic that did not make sense.</li>
  <li>We should all expect decreases in organic traffic, as AI becomes more prevalent. My customers have already noticed it.</li>
</ul>

<h3 id="countries">Countries</h3>

<p>The top 5 countries are the same as last year:</p>

<ol>
  <li>Singapore: 31.3%</li>
  <li>United States: 26.7%</li>
  <li>India: 14.7%</li>
  <li>United Kingdom: 3.4%</li>
  <li>Canada: 3.2%</li>
</ol>

<p>Surprisingly, Singapore is still at the top. I assume that many people are using a VPN that exits through this country, otherwise I cannot believe that such a small country brings more traffic than the U.S. Where could these visitors come from? China?</p>

<h3 id="traffic-sources">Traffic Sources</h3>

<p>To me, this is the most interesting report to evaluate in 2025. As I said above, AI is replacing search engines at a slow but steady pace. I can already see it in the traffic sources report:</p>

<ol>
  <li>Search Engines: 45.9%</li>
  <li>Types/Bookmarked: 40.5%</li>
  <li>Social Networks: 9.4%</li>
  <li>Other Websites: 4.0%</li>
  <li>Conversational AI: 0.3%</li>
</ol>

<p>These are the OOTB Adobe Analytics classifications and it is important that you understand them:</p>

<ul>
  <li>Adobe only added “Conversational AI” in the last few months.</li>
  <li>Before adding “Conversational AI”, those tools showed up under “Other Websites”.</li>
  <li>Search engines often show an AI-generated response to your query; if you click on it, the referrer will still be classified as “Search Engine”.</li>
</ul>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-22-2025-retrospective/ai-referrals.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/ai-referrals-300-76f6d45d7.png" alt="AI referrals" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/ai-referrals-300-76f6d45d7.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/ai-referrals-450.0-76f6d45d7.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-12-22-2025-retrospective/ai-referrals-600-76f6d45d7.png 2.0x"></a></p>

<p>The good news is that conversational AI tools believe that my blog is a reliable source of information.</p>

<h2 id="looking-into-2026">Looking into 2026</h2>

<p>I hope that the new year comes with more positive news. As I said above, I am not very happy with how 2025 has behaved.</p>

<p>For this blog, I will start posting more about AI in relation to Adobe technologies. I need to learn more and, as I do, I will share my knowledge with you. That being said, I want to mention that, in my humble opinion, there has been too much hype around AI, and <a href="https://duckduckgo.com/?q=ai+hype&amp;ia=web">I am not the only one thinking along these lines</a>.</p>

<p>Happy 2026!</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@boliviainteligente?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">BoliviaInteligente</a> on <a href="https://unsplash.com/photos/year-2026-displayed-on-cubes-1AgT_-D6SiU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[Another year comes to a close. Today is my first day of PTO, so I am still not fully feeling it. I have woken up at the usual time because I have a lot to do in the coming days before I go on a trip. However, it is the perfect moment of the year to reflect and look back.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-22-2025-retrospective/2026.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-22-2025-retrospective/2026.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">SPAs and Attribution</title><link href="https://www.pedromonjo.com/2025/12/spas-attribution.html" rel="alternate" type="text/html" title="SPAs and Attribution" /><published>2025-12-07T00:00:00-05:00</published><updated>2025-12-07T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2025/12/spas-attribution</id><content type="html" xml:base="https://www.pedromonjo.com/2025/12/spas-attribution.html"><![CDATA[<p>I wanted to share an issue one of my customers recently encountered. They called me saying that they had found issues in Adobe Analytics attribution and they were questioning the quality of the data. After digging into it, we found that the problem was due to their Single Page Application (SPA) implementation. If your website uses any SPA technology, this post interests you.</p>

<!--more-->

<h2 id="page-views">Page Views</h2>

<p>In traditional websites (i.e., those that do not use any SPA technology), every page view is a full page download. After clicking on internal links, the browser unloads the previous page, releasing all the resources, and loads the new page. From a technical perspective, it is very clear what a page view is, and you can easily configure Web SDK to send data with every new page view.</p>

<p>However, with SPAs, only the first page is a full download. All subsequent clicks trigger the download of only the content specific to the new page. The rest of the page stays the same: menu, header, side bars, footer… In other words, while the end users feel like they are moving from page to page, technically, the browser does not unload any pages nor release any resources, and thinks it is always on the first page. Page view events are sent to Adobe Analytics or <a href="https://experienceleaguecommunities.adobe.com/t5/adobe-experience-platform-blogs/introduction-to-the-aep-edge-network/ba-p/658579">Adobe Experience Platform Edge</a> based on arbitrary rules included in the SPA controller, typically when more than 50% of the content of the page changes.</p>

<p>This behavior has a direct impact on the page metadata, in particular, the previous URL or referrer, which is accessible through <code class="language-plaintext highlighter-rouge">document.referrer</code>. Web SDK uses this parameter for the previous page URL.</p>

<p>In the case of traditional websites, this parameter is automatically updated with every page refresh, and, as expected, it holds the URL to the previous page. However, in SPAs, since the browser only fully loads the first page, the referrer does not get updated again with every click.</p>

<h2 id="the-attribution-problem-in-spas">The Attribution Problem in SPAs</h2>

<!-- markdownlint-capture -->
<!-- markdownlint-disable MD034 MD055 MD056 -->

<p>Let’s consider a scenario with the following Adobe Analytics <a href="https://www.pedromonjo.com/2016/09/marketing-channels-fundamentals.html">Marketing Channels</a> rules:</p>

<table class="table table-bordered">
  <thead>
    <tr>
      <th style="text-align: right">Order</th>
      <th>Channel</th>
      <th>Rules</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Paid Search</td>
      <td>Referrer is search engine <br /> AND campaign ID is present</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Natural Search</td>
      <td>Referrer is search engine</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Paid Social</td>
      <td>Referrer is social site <br /> AND campaign ID is present</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Natural Social</td>
      <td>Referrer is social site</td>
    </tr>
  </tbody>
</table>

<p>Next, consider the following chain of events from an end user perspective, where the website is an SPA:</p>

<table class="table table-bordered">
  <thead>
    <tr>
      <th style="text-align: right">#</th>
      <th>Event</th>
      <th>Referrer</th>
      <th>Campaign ID</th>
      <th>Marketing Channel</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Searches in Google</td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Clicks on paid link and lands on website</td>
      <td>https://www.google.com/</td>
      <td>a1b2c3d4e5</td>
      <td>Paid Search</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Clicks on an internal link</td>
      <td>https://www.google.com/</td>
      <td> </td>
      <td>Natural Search</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Clicks on another internal link</td>
      <td>https://www.google.com/</td>
      <td> </td>
      <td>Natural Search</td>
    </tr>
  </tbody>
</table>

<p>As you can see, on the landing page, the marketing channel was correctly identified, but it then gets updated to a wrong value from the second page onwards. Any conversion further down the line would then be attributed to “Natural Search”, when it should have been attributed to “Paid Search”.</p>

<p>If you think that Adobe Analytics has enough information to know that it is an internal link, think again. Consider this alternative series of events:</p>

<table class="table table-bordered">
  <thead>
    <tr>
      <th style="text-align: right">#</th>
      <th>Event</th>
      <th>Referrer</th>
      <th>Campaign ID</th>
      <th>Marketing Channel</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">1</td>
      <td>Searches in Google</td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td>Clicks on paid link and lands on website</td>
      <td>https://www.google.com/</td>
      <td>a1b2c3d4e5</td>
      <td>Paid Search</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Clicks on back button and lands on Google again</td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Clicks on organic link and lands on website</td>
      <td>https://www.google.com/</td>
      <td> </td>
      <td>Natural Search</td>
    </tr>
    <tr>
      <td style="text-align: right">5</td>
      <td>Clicks on an internal link</td>
      <td>https://www.google.com/</td>
      <td> </td>
      <td>Natural Search</td>
    </tr>
    <tr>
      <td style="text-align: right">6</td>
      <td>Clicks on another internal link</td>
      <td>https://www.google.com/</td>
      <td> </td>
      <td>Natural Search</td>
    </tr>
  </tbody>
</table>

<p>With this new scenario, although events 5 and 6 should not carry any marketing channel value, the value they get is actually correct, and attribution would be fine. However, the crucial question is: how can Adobe Analytics know the difference between this example and the one before? It cannot. They both look exactly the same, as Google does not send any data to Adobe Analytics.</p>

<p>This problem does not exist on a traditional website. The clicks on internal links will carry the correct URL in the referrer. They will be correctly identified as internal URLs and will not generate new Marketing Channel values. I want to also clarify that this explanation refers to last-touch attribution; first-touch attribution should always be correct.</p>

<!-- markdownlint-restore -->

<h2 id="the-solution">The Solution</h2>

<p>Ideally, you would want to tweak the Marketing Channels rules to deal with this scenario. Unfortunately, this is not always possible. Marketing Channels rules only evaluate the current hit, with no context of previous hits. Crucial information needed to correctly identify the marketing channel is present in these previous hits. For example, in event 3 of the second table above, the Marketing Channels engine only sees that the referrer is Google.</p>

<p>The best solution is to modify your Web SDK implementation, either manually or through Adobe Tags. Your rules should keep track of the previous page that was shown and use it to populate <code class="language-plaintext highlighter-rouge">web &gt; webReferrer &gt; URL</code> (see the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/xdm/field-groups/event/web-details">Web Details field group</a>) with the correct, internal URL. If you use Adobe Tags, you will probably need a Data Element.</p>

<p>For more information, read this Experience League post: <a href="https://experienceleaguecommunities.adobe.com/t5/adobe-analytics-blogs/web-sdk-part-4-avoiding-banana-peels-and-other-things-that-can/ba-p/644750">Web SDK Part 4: Avoiding Banana Peels</a> (Banana Peel #6).</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@alexbertha?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Alex Bertha</a> on <a href="https://unsplash.com/photos/woman-in-water-pool-Jyg7xHRmXiU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Analytics Tips" /><summary type="html"><![CDATA[I wanted to share an issue one of my customers recently encountered. They called me saying that they had found issues in Adobe Analytics attribution and they were questioning the quality of the data. After digging into it, we found that the problem was due to their Single Page Application (SPA) implementation. If your website uses any SPA technology, this post interests you.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-07-spas-attribution/spa.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-12-07-spas-attribution/spa.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Unified Profile Service and Unified Identity Service</title><link href="https://www.pedromonjo.com/2025/11/ups-uis.html" rel="alternate" type="text/html" title="Unified Profile Service and Unified Identity Service" /><published>2025-11-23T00:00:00-05:00</published><updated>2025-11-23T00:00:00-05:00</updated><id>https://www.pedromonjo.com/2025/11/ups-uis</id><content type="html" xml:base="https://www.pedromonjo.com/2025/11/ups-uis.html"><![CDATA[<p>If you have been following my posts, you now understand the concept of profile projection, and the roles of the Unified Identity Service (UIS) and the Unified Profile Service (UPS). However, for others who are not familiar with these concepts, I am going to explain them from a different angle.</p>

<!--more-->
<style type="text/css">
   ol { list-style-type: decimal; }
   ol ol {list-style-type: lower-alpha; }
</style>

<p>As usual, since I have been writing about the Adobe Experience Platform (AEP), I will use the following diagram as reference:</p>

<p><a href="https://www.pedromonjo.com/assets/images/common/aep-reference-architecture.svg" data-toggle="lightbox"><img src="https://www.pedromonjo.com/assets/images/common/aep-reference-architecture.svg" alt="AEP Reference Architecture" width="300" /></a></p>

<p>And just to set the stage, today I will describe the “Profile Store” and the “Identity Store” boxes in the previous diagram.</p>

<h2 id="unified-profile-service">Unified Profile Service</h2>

<p>This is the simplest of the two, but before I get into the details, I will start by explaining what it is <em>not</em>. It is very tempting to think that this is a relational database where each row corresponds to a profile, with the columns being the schema parameters. Let me assure you that this is not the case. There is no SQL database behind the scenes, nor are we issuing SELECTs, UPDATEs or INSERTs. If this were the case, <a href="https://www.pedromonjo.com/2022/10/profile-collapse.html">profile collapses</a> would be totally unsolvable, whereas in reality, there are various solutions.</p>

<p>Instead, you have to think of UPS as a <strong>store of fragments</strong>, which behaves as follows based on the type of dataset:</p>

<ul>
  <li>Profile datasets: it keeps the last update received from the data source, for each primary identity.</li>
  <li>Events datasets: it keeps all events whose TTL has not been reached.</li>
</ul>

<p>All these fragments are keyed by their primary identity. Think of it as a key-value pair database, where the key is the primary identity and the value is an array of fragments. This is why it is so important to decide on the primary identity in a schema: it will be the key used to find fragments in UPS. The same applies to the <code class="language-plaintext highlighter-rouge">primary</code> field in the <code class="language-plaintext highlighter-rouge">identityMap</code>.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-23-ups-uis/aep-primary-identity.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-primary-identity-300-6752bbed5.png" alt="AEP Primary Identity" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-primary-identity-300-6752bbed5.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-primary-identity-450.0-6752bbed5.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-primary-identity-600-6752bbed5.png 2.0x"></a></p>

<p>You can also see how time plays a role: as new profile fragments are received from data sources, previous fragments are deleted, and every day, events whose TTL has been reached are deleted. Remember that the <a href="https://www.pedromonjo.com/2023/05/data-lake.html">Data Lake</a> keeps all data until the batch is deleted.</p>

<p>I want you to pause and see how in this database, a fully formed profile is nowhere to be found. All you have are scattered pieces of information.</p>

<h2 id="unified-identity-service">Unified Identity Service</h2>

<p>Now that we have all the previous fragments, how do we know which need to be combined to project a profile?</p>

<p>If there is only one identity involved, the solution is simple. However, in scenarios where there are multiple identities associated with a single profile, we need a place to <strong>store linked identities</strong>. This is the role of the UIS. Think of it as a specialized storage that keeps track of namespaces, identities, and links between identities. I like how HubSpot depicts this identity graph:</p>

<p><a href="https://blog.hubspot.com/hs-fs/hubfs/Google%20Drive%20Integration/What%20Is%20an%20Identity%20Graph%3F%20[The%20Plain-English%20Guide]-1.png" data-toggle="lightbox"><img src="https://blog.hubspot.com/hs-fs/hubfs/Google%20Drive%20Integration/What%20Is%20an%20Identity%20Graph%3F%20[The%20Plain-English%20Guide]-1.png" alt="Hubspot Identity Graph" width="300" /></a></p>

<p>In AEP, you can view many details of UIS in the “Identities” menu:</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-23-ups-uis/aep-identities.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-identities-300-49a433dac.png" alt="AEP Identities" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-identities-300-49a433dac.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-identities-450.0-49a433dac.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-11-23-ups-uis/aep-identities-600-49a433dac.png 2.0x"></a></p>

<p>While UPS cares only about primary identities, UIS wants to know about additional identities, those not marked as primary. As records are ingested from data sources, UIS takes the following steps:</p>

<ol>
  <li>Checks that the primary identity is present; if it is not, rejects the record.</li>
  <li>If there is an additional identity:
    <ol>
      <li>If the identity is already in another graph in the database, both graphs will be collapsed into a single graph.</li>
      <li>If the identity is new, it will be added to the store and linked to the primary identity in the record.</li>
    </ol>
  </li>
</ol>

<p>You will have noticed in the screenshot above that the minimum size of the identity graph is 2. Although you could have, theoretically, a graph with just one node, it does not make sense to store it. Only when two or more nodes are required is a graph created. As a consequence, 2.b above may also create a new graph.</p>

<p>UIS keeps track of where the links between identities came from and when these links were stored in the graph. This key feature has two consequences:</p>

<ul>
  <li>If you delete a dataset or a batch in a dataset, all links between identities that were formed from this dataset or batch will be deleted. I have built solutions around this capability to un-collapse profiles.</li>
  <li>The <a href="https://www.pedromonjo.com/2025/08/identity-graph-linking-rules.html">Identity Graph Linking Rules</a> feature could be implemented, as it can detect the age of a link between identities.</li>
</ul>

<h2 id="where-is-the-profile">Where is the Profile?</h2>

<p>So, we have fragments and identity graphs, not profiles. However, we always talk about a profile. How do we get it?</p>

<p>I will not explain it here, as I wrote a blog post where I described the process step by step: <a href="https://www.pedromonjo.com/2025/04/profile-projection.html">profile projection</a>. I recommend that, if you have not read it, you do so now. Both posts will make a lot of sense when read together.</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/group-of-diverse-young-people-with-different-appearances-6238122/">Photo by Monstera Production</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[If you have been following my posts, you now understand the concept of profile projection, and the roles of the Unified Identity Service (UIS) and the Unified Profile Service (UPS). However, for others who are not familiar with these concepts, I am going to explain them from a different angle.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-23-ups-uis/identities.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-23-ups-uis/identities.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Obsession with Lighthouse Scores and GEO</title><link href="https://www.pedromonjo.com/2025/11/obsession-lighthouse-scores-geo.html" rel="alternate" type="text/html" title="Obsession with Lighthouse Scores and GEO" /><published>2025-11-02T00:00:00-04:00</published><updated>2025-11-02T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/11/obsession-lighthouse-scores-geo</id><content type="html" xml:base="https://www.pedromonjo.com/2025/11/obsession-lighthouse-scores-geo.html"><![CDATA[<p>In my post on <a href="https://www.pedromonjo.com/2024/12/flicker-personalization-speed.html">Flicker, Personalization and Page Speed</a>, I mentioned the obsession with the Google Lighthouse scores. The LinkedIn comments I received suggested that I was not alone in my views. I planned to write another post, deepening my point of view, but recent developments have significantly changed the landscape.</p>

<!--more-->

<h2 id="summary-of-the-past">Summary of the Past</h2>

<p>Before I explain what is changing, I will start with what I have seen in the last few years.</p>

<p>One of the approximately <a href="https://duckduckgo.com/?q=google+200+parameters">200 ranking factors that Google uses in its ranking algorithm</a> is page load time. Let me repeat that again: only one out of ~200 parameters that Google considers in its algorithm is the time the page takes to load.</p>

<p>This has led hordes of zealots to take full control of websites and demanded major changes to achieve some absurd number. These people would not try to find compromises. The consequences have been noticeable in digital marketing: the capability to personalize websites without flicker has diminished. I have been in my fair share of <em>battles</em> with them and I was never able to win. 😞</p>

<p>I never believed that such extortionate measures were positive. I agree that a website that takes 10+ seconds to load on a desktop connected to a fiber connection offers a very bad experience. However, those 10 seconds on a patchy 3G connection are to be expected. All my customers are well-known companies, who are usually searched for by name. In this case, the brand is so strong that a slightly slower website would not be noticeable in the search results. In other words, site speed, while necessary, is not a deal breaker.</p>

<h2 id="the-new-kid-in-town">The New Kid in Town</h2>

<p>In the last few years, generative AI has taken the market by storm. So much so that one of the immediate consequences has been that <a href="https://www.forbes.com/sites/torconstantino/2025/04/14/the-60-problem---how-ai-search-is-draining-your-traffic/">organic search traffic to websites has dropped significantly</a>. People are changing the way they search for information, especially the younger generations. Instead of using a few, carefully selected keywords in a search engine, you now describe your problem in detail and the generative AI platform replies with all the information you need.</p>

<p>The first consequence is that fewer prospects, although more qualified, will land on your websites. With search engines, we had to manually check multiple links until we found what we wanted. Now, the generative AI tool of choice will do that for us automatically by reviewing multiple pages. Only when the prospect is ready to take the next step, they will click on a reference to your website.</p>

<p>Another consequence is that this new technology will force a change in how digital marketing teams distribute their budgets. There is a new discipline that will soon become a significant part of those marketing efforts: <a href="https://www.pedromonjo.com/2025/09/from-seo-to-geo.html">Generative Engine Optimization</a> (GEO). Not only will you want your website to score high in search engines, but you will also need to be the reference used by Large Language Models (LLMs) when providing a response to a prompt relevant to your business. Adobe has just launched a product called <a href="https://experienceleague.adobe.com/en/docs/llm-optimizer/using/essentials/overview">LLM Optimizer</a> precisely with this goal in mind. As a clarification, LLMs are the backbone of generative AI tools.</p>

<h2 id="my-point-of-view">My Point of View</h2>

<p>In my opinion, and given all that I am seeing and my experience, this is what I expect for the near future:</p>

<ul>
  <li><strong>Content will still be king</strong>. That was an expression used with SEO, but with GEO, it will even be more important. Quality content is what an LLM will use to select a website.</li>
  <li>While Gemini and other LLMs rely on Google data, and thus, page speed will still matter somewhat, not all successful engines will use Google’s index.</li>
  <li>LLMs have a different set of parameters to evaluate whether a website is relevant or not. I doubt page load time will be one.</li>
  <li>There will be a tension between SEO and SEM on the one side, and GEO on the other. I expect <strong>GEO to win</strong>.</li>
  <li>Page speed will always be important, within reasonable expectations. However, the pursuit of perfect <strong>Google Lighthouse scores will become irrelevant</strong>.</li>
  <li>The aggressive approach that many companies have taken to achieve these perfect scores will have to be backtracked to allow <strong>personalization and optimization tools</strong> to do their job.</li>
</ul>

<p>In summary, being able to <strong>use all digital marketing tools at their full capacity</strong> to increase conversion will be more important than ever. Companies will have a smaller window of opportunity to convince a new visitor to stay and convert.</p>

<p>What is your point of view? Will we still have to battle with impossible page speed requirements or will we get back all the tools we need to convince prospects?</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/white-and-black-lighthouse-near-the-blue-sea-6006948/">Photo by Tom D’Arby</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[In my post on Flicker, Personalization and Page Speed, I mentioned the obsession with the Google Lighthouse scores. The LinkedIn comments I received suggested that I was not alone in my views. I planned to write another post, deepening my point of view, but recent developments have significantly changed the landscape.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-02-obsession-lighthouse-scores-geo/lighthouse.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-11-02-obsession-lighthouse-scores-geo/lighthouse.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Profile Merge Policies</title><link href="https://www.pedromonjo.com/2025/10/profile-merge-policies.html" rel="alternate" type="text/html" title="Profile Merge Policies" /><published>2025-10-19T00:00:00-04:00</published><updated>2025-10-19T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/10/profile-merge-policies</id><content type="html" xml:base="https://www.pedromonjo.com/2025/10/profile-merge-policies.html"><![CDATA[<p>I have been dodging the profile merge policies bullet for quite some time, mainly because I never needed to dive deep into it. In fact, I still inadvertently say <a href="https://www.pedromonjo.com/2019/09/introduction-profile-merge-rules.html">profile merge rules</a>, from my <a href="https://www.pedromonjo.com/category/aam/">Adobe Audience Manager</a> days. However, this week I needed to provide a solution that involved creating a new merge policy. So it is high time I explained this capability.</p>

<!--more-->

<h2 id="profile-projection">Profile Projection</h2>

<p>Unless you know very well how a profile gets projected, before you continue reading this post, I highly recommend that you read my post on <a href="https://www.pedromonjo.com/2025/04/profile-projection.html">profile projection</a>. The summary of the process is:</p>

<ol>
  <li>A profile is requested for a given identity.</li>
  <li>The identity graph is queried to get all identities linked to the one provided.</li>
  <li>The profile store is queried to get all the fragments with these identities.</li>
  <li>The fragments are combined following a set of rules.</li>
  <li>The projected profile is returned.</li>
</ol>

<p>In the rest of the post, I will refer to “step [X]”, where X is one of the steps in the process above.</p>

<p>Although I only briefly explained it in my other post, merge policies govern this process. So much so that one of the parameters of the first step is the merge policy to use. Let’s see how this functionality works.</p>

<h2 id="id-stitching">ID Stitching</h2>

<p>One of the parameters that you have to configure when creating a new merge policy is how identities are stitched.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/merge-policy-id-stitching.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-id-stitching-300-5aaa907ea.png" alt="Merge Policy ID Stitching" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-id-stitching-300-5aaa907ea.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-id-stitching-450.0-5aaa907ea.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-id-stitching-600-5aaa907ea.png 2.0x"></a></p>

<h3 id="none">None</h3>

<p>With this value, the profile projection process completely skips step [2] (querying the identity graph). Yes, I know, it sounds weird, especially when one of the main features of the Adobe Experience Platform (AEP) is to stitch identities. However, in some scenarios, it can be very useful.</p>

<p>Let me try to explain it differently, as I am sure some may not have understood it. When you set “ID Stitching” to “None”, and you project a profile, the algorithm will only use the identity that you have supplied in step [1] to look for profile fragments in step [3].</p>

<p>A typical use case when this value becomes very useful is for some scenarios of <a href="https://www.pedromonjo.com/2022/10/profile-collapse.html">profile collapse</a>. Sometimes you do not need the full profile, only the profile fragments that have been submitted with one of the identities. In a way, with this approach, you “uncollapse” the profile. Remember that the profile is not stored anywhere; the profile store only keeps fragments.</p>

<h3 id="private-graph">Private Graph</h3>

<p>This is the default value. In step [2], the algorithm makes a call to the identity store. The identity store subsequently returns all other identities that have been linked to the identity given in step [1].</p>

<h2 id="default-and-edge">Default and Edge</h2>

<p>Let’s move on to the next two parameters.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/merge-policy-default-edge.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-default-edge-300-bdd33b735.png" alt="Default and Edge Merge Policies" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-default-edge-300-bdd33b735.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-default-edge-450.0-bdd33b735.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-default-edge-600-bdd33b735.png 2.0x"></a></p>

<h3 id="default-merge-policy">Default Merge Policy</h3>

<p>There always needs to be a default merge policy, which is the one that will be used if, in step [1], no merge policy is supplied. AEP provides one, but you can change it to one of your own.</p>

<h3 id="active-on-edge-merge-policy">Active-On-Edge Merge Policy</h3>

<p>When the <a href="https://www.pedromonjo.com/2025/03/aep-edge-network.html">AEP Edge Network</a> requests a profile to the core, the process is no different, and it also has to supply a merge policy. It could use the default merge policy, but you have the flexibility to use a different one, if your use case requires it. Since the <a href="https://www.pedromonjo.com/2022/04/edge-network-server-api.html">Edge Network Server API</a> does not have the capability to supply a merge policy, you have to predefine it.</p>

<h2 id="merge-method">Merge Method</h2>

<p>The next configuration parameter that you need to set is the merge method.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/merge-policy-method.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-method-300-fa44a2f21.png" alt="Merge Policies Methods" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-method-300-fa44a2f21.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-method-450.0-fa44a2f21.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-method-600-fa44a2f21.png 2.0x"></a></p>

<p>This method governs how step [4] works. The output of step [3] is a bunch of fragments. However, fragments can overlap; that is, some attributes may be present in multiple fragments. If this happens, which fragments prevail?</p>

<h3 id="timestamp-ordered">Timestamp Ordered</h3>

<p>All fragments include a timestamp of when they were last updated in AEP. If you select this option (the most common), AEP will choose the fragment with the timestamp closest to now, irrespective of where it came from. This is the most common option; in fact, I have not seen any customer use the next value.</p>

<h3 id="dataset-precedence">Dataset Precedence</h3>

<p>Instead of relying on the last fragment update to take precedence, you define a priority of datasets. So, if there is a collision between fragments, AEP will choose the one coming from the dataset highest in the hierarchy.</p>

<p>This capability can be useful when you have datasets coming from various sources, some more reputable than others. For example, you may be ingesting data from your CRM and from 3<sup>rd</sup>-party data providers. If there is any overlap between these data sources, you will likely want your own data, which you control, to take precedence over other sources, which are out of your control.</p>

<p>When you select this option, the UI shows you the datasets, which you have to choose and order. You have to do it for both profile and event datasets. One feature that you also get with this option is that you can leave out some datasets from this merge policy. In other words, you can create a merge policy that will only show a partial profile. I am not sure when I would leave out datasets, but it is always good to have options.</p>

<h2 id="usage">Usage</h2>

<p>OK, now you have your shiny, custom merge policies. How do you use them?</p>

<h3 id="profile-ui">Profile UI</h3>

<p>The first place where you can use them is when you want to browse some profiles in the UI. You may have already noticed that the first parameter is the merge policy, although you probably have ignored it so far. You can remove the default value and select a new one. I find this option very interesting to see how different merge policies generate different profiles.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/merge-policy-profile-ui.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-profile-ui-300-26c79a994.png" alt="Merge Policy Selection in Profile UI" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-profile-ui-300-26c79a994.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-profile-ui-450.0-26c79a994.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-profile-ui-600-26c79a994.png 2.0x"></a></p>

<h3 id="segmentation">Segmentation</h3>

<p>While the profile UI has its uses, when you can really take advantage of merge policies is in segmentation. This means that, when evaluating segments, the profiles sent for activation will be generated by using the selected merge policy.</p>

<p>In order to configure this parameter, in the new audience interface, you should see a gear icon. I had never used it until now. When you click on it, you get a few configuration parameters, one of which is the merge policy.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/merge-policy-segmentation.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-segmentation-300-143bb7f64.png" alt="Merge Policy in Segmentation" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-segmentation-300-143bb7f64.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-segmentation-450.0-143bb7f64.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-10-19-profile-merge-policies/merge-policy-segmentation-600-143bb7f64.png 2.0x"></a></p>

<h3 id="profile-api">Profile API</h3>

<p>Being AEP API-first, the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/profile/api/entities">Profile API</a> also supports passing a merge policy. In fact, if you read the documentation under “retrieve an entity”, you get the following explanation:</p>

<blockquote>
  <p>Additionally, usage of the following query parameter is <em>highly</em> recommended:</p>

  <ul>
    <li><code class="language-plaintext highlighter-rouge">mergePolicyId</code>: The ID of the merge policy you want to filter the data with. If no merge policy is specified, your organization’s default merge policy will be used.</li>
  </ul>
</blockquote>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/scrabble-letters-spelling-rules-on-a-wooden-table-19856614/">Photo by Markus Winkler</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[I have been dodging the profile merge policies bullet for quite some time, mainly because I never needed to dive deep into it. In fact, I still inadvertently say profile merge rules, from my Adobe Audience Manager days. However, this week I needed to provide a solution that involved creating a new merge policy. So it is high time I explained this capability.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/policies.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-19-profile-merge-policies/policies.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Conversion Funnel and Adobe Tools</title><link href="https://www.pedromonjo.com/2025/10/conversion-funnel-adobe-tools.html" rel="alternate" type="text/html" title="Conversion Funnel and Adobe Tools" /><published>2025-10-05T00:00:00-04:00</published><updated>2025-10-05T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/10/conversion-funnel-adobe-tools</id><content type="html" xml:base="https://www.pedromonjo.com/2025/10/conversion-funnel-adobe-tools.html"><![CDATA[<p>Today’s post is going to be different from my typical post where I explain how to solve for something or I explain my point of view. I will just list the Adobe tools based on a particular order, the order defined by the conversion funnel. It is just a reference, a mental map of tools, and very personal.</p>

<!--more-->

<style type="text/css">
  table.table td:first-child {
    font-weight: bold;
    /* width: 28%; */
  }
  @media screen and (min-width: 768px) {
    table#table-funnel {
      width: auto;
    }
    table#table-funnel td:first-child {
      width: auto;
    }
  }
</style>

<h2 id="conversion-funnel">Conversion Funnel</h2>

<p>I am sure you are all familiar with the typical sales or conversion funnel. There are many ways to show it, and it differs between business-to-business (B2B) and business-to-consumer (B2C). In the B2B world, Marketo will be at the center of most marketing activities.</p>

<p>In this post, though, I will explain a B2C case, as I am more familiar with it. This is a typical B2C conversion funnel:</p>

<p><img src="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-05-conversion-funnel-adobe-tools/sales-funnel.svg" alt="Conversion Funnel" width="200" class="img-responsive" /></p>

<table id="table-funnel" class="table table-bordered">
  <thead>
    <tr>
      <th style="text-align: center">Initial</th>
      <th style="text-align: left">Full word</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">A</td>
      <td style="text-align: left">Awareness</td>
    </tr>
    <tr>
      <td style="text-align: center">I</td>
      <td style="text-align: left">Interest</td>
    </tr>
    <tr>
      <td style="text-align: center">D</td>
      <td style="text-align: left">Desire</td>
    </tr>
    <tr>
      <td style="text-align: center">A</td>
      <td style="text-align: left">Action</td>
    </tr>
  </tbody>
</table>

<p>And it is a funnel because, as you go from top to bottom, there are fewer people in each section.</p>

<p>Let’s go step by step and identify what Adobe tools I believe belong to each one.</p>

<h2 id="top-of-the-funnel-awareness">Top of the Funnel: Awareness</h2>

<p>At the top of the funnel we find the <em>awareness</em> state. I like the definition of this stage that I found on <a href="https://www.bol-agency.com/blog/awareness-consideration-conversion-marketing-funnel">this post</a>:</p>

<blockquote>
  <p>This is where potential customers first become aware of your brand or product. They might not be actively looking to buy anything yet, but you want to make them aware of your existence and pique their interest.</p>
</blockquote>

<p>Since you know nothing about them and they do not know your company, you have to fish them outside of your properties. Your options with Adobe tools are:</p>

<table class="table table-striped">
  <tbody>
    <tr>
      <td>Adobe Advertising</td>
      <td>This tool has had multiple names, but the idea is always the same: place paid ads on different platforms, such as search, media, and social. Remember, you need to tell the rest of the world that you exist.</td>
    </tr>
    <tr>
      <td>Adobe Audience Manager</td>
      <td>If you still have this tool and are ingesting third-party data, you can create segments of these cookies and share them with demand-side platforms.</td>
    </tr>
    <tr>
      <td>Adobe Campaign</td>
      <td>This is a bit of an edge case, but if you have the rights to use a list of email addresses of non-customers, you could send them an email. I would not use Adobe Journey Optimizer (AJO) for this.</td>
    </tr>
    <tr>
      <td>Adobe Experience Manager</td>
      <td>You may be wondering why I am including AEM here, when a potential customer has not even visited your website. The reason is that your marketing content needs to be attractive to search engines (SEO), <a href="https://www.pedromonjo.com/2025/09/from-seo-to-geo.html">and now generative AI too</a>, so that they promote your content.</td>
    </tr>
  </tbody>
</table>

<h2 id="middle-of-the-funnel-interest--desire">Middle of the Funnel: Interest &amp; Desire</h2>

<p>Now you have piqued the interest of a potential buyer. They have found you somewhere in the wild Internet and they have clicked a link that takes them to your website. Now it is your opportunity to show that you are their best option.</p>

<p>The difference between these two steps is subtle, and many combine them into one step. However, you could say that <em>interest</em> is just curiosity and research, while <em>desire</em> shows an appetite to buy your products or services.</p>

<p>At this stage, you can use these Adobe products:</p>

<table class="table table-striped">
  <tbody>
    <tr>
      <td>Adobe Experience Manager</td>
      <td>This is the sweet spot for AEM. Successful online businesses need a steady flow of new content to show visitors. This content needs to show exactly what the potential buyer is looking for. Such a large volume of content requires a tool that helps you manage it.</td>
    </tr>
    <tr>
      <td>Adobe Analytics<br />Customer Journey Analytics</td>
      <td>After landing on your website, you can start tracking your visitors to understand what they want, what they do not like, the issues they are having, and a bit about who they are.</td>
    </tr>
    <tr>
      <td>Adobe Target</td>
      <td>You should be running A/B tests on landing pages to see which version resonates the most, and personalization based on information that you have about the visitor: location, language, previous pages, traffic source...</td>
    </tr>
    <tr>
      <td>Real-Time Customer Data Platform</td>
      <td>The moment a new <a href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html">ECID</a> is sent to the <a href="https://www.pedromonjo.com/category/platform/">Adobe Experience Platform</a> (AEP), a <a href="https://experienceleague.adobe.com/en/docs/experience-platform/profile/ui/prospect-profile">prospect profile</a> is created. You can use it to create segments.</td>
    </tr>
    <tr>
      <td>Adobe Campaign<br />Adobe Journey Optimizer</td>
      <td>In some cases, the prospect may provide you with an email address, for example, if they sign up for a newsletter. This is gold, and you can use it to send them tailored marketing material.</td>
    </tr>
  </tbody>
</table>

<h2 id="bottom-of-the-funnel-action">Bottom of the funnel: Action</h2>

<p>You will also see this stage named <em>conversion</em>. This is when the customer finally opens their wallet and buys your products or services. I know that there are some cases where the action is not necessarily paying for something, but the tools needed to manage it remain mostly the same.</p>

<p>This is my selection:</p>

<table class="table table-striped">
  <tbody>
    <tr>
      <td>Adobe Experience Manager</td>
      <td>You still need some web pages to manage the conversion.</td>
    </tr>
    <tr>
      <td>Adobe Commerce</td>
      <td>This is the sweet spot for this tool, where you manage the catalog, payment, shipping, and anything else related to the final sale.</td>
    </tr>
    <tr>
      <td>Adobe Analytics<br />Customer Journey Analytics</td>
      <td>Again, you want to track and measure what is happening, to identify trends or issues with the conversion. You want to make sure that the process is as frictionless as possible. Besides, you want to report on how much money you are making and attribute this revenue to the traffic source.</td>
    </tr>
    <tr>
      <td>Adobe Campaign<br />Adobe Journey Optimizer</td>
      <td>If the prospect drops out at the last minute, you should encourage them to come back, which is usually called a *cart abandonment* campaign. If the prospect converts and becomes a customer, you will need to send them a welcome email or updates related to the purchase.</td>
    </tr>
  </tbody>
</table>

<h2 id="retention">Retention</h2>

<p>So, someone has taken the action that you wanted. Congratulations!</p>

<p>However, is that the end? Absolutely not! Now you have to keep making this customer happy and, in the future, when they want to buy similar products or services again, they buy from you. And here you have an ace up your sleeve: you already know who they are and what they like. You can, and should, be using this information to your advantage.</p>

<p>All your Adobe tools are there to support you:</p>

<table class="table table-striped">
  <tbody>
    <tr>
      <td>Adobe Experience Manager</td>
      <td>Create new content that your customers will love.</td>
    </tr>
    <tr>
      <td>Adobe Commerce</td>
      <td>Be ready for any up-sell or cross-sell, and have offers available.</td>
    </tr>
    <tr>
      <td>Adobe Analytics<br />Customer Journey Analytics</td>
      <td>Understand what your customers want.</td>
    </tr>
    <tr>
      <td>Adobe Campaign<br />Adobe Journey Optimizer</td>
      <td>Keep your customer informed until the service or product is delivered. Then, make sure they know what you are doing and what new things you are working on.</td>
    </tr>
    <tr>
      <td>Adobe Target</td>
      <td>Personalize the content of the website or app, knowing what this customer likes or wants.</td>
    </tr>
  </tbody>
</table>

<p>And this is my list. What is yours?</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/orange-and-gray-concrete-structures-749380/">Photo by Anton H</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><category term="MSA" /><summary type="html"><![CDATA[Today’s post is going to be different from my typical post where I explain how to solve for something or I explain my point of view. I will just list the Adobe tools based on a particular order, the order defined by the conversion funnel. It is just a reference, a mental map of tools, and very personal.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-05-conversion-funnel-adobe-tools/funnel.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-10-05-conversion-funnel-adobe-tools/funnel.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AEP Identity Strategy</title><link href="https://www.pedromonjo.com/2025/09/aep-identity-strategy.html" rel="alternate" type="text/html" title="AEP Identity Strategy" /><published>2025-09-21T00:00:00-04:00</published><updated>2025-09-21T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/09/aep-identity-strategy</id><content type="html" xml:base="https://www.pedromonjo.com/2025/09/aep-identity-strategy.html"><![CDATA[<p>It has been more than three years since I wrote my <a href="https://www.pedromonjo.com/2022/05/understanding-aep-identities.html">first post on AEP identities</a>. I think it is time to revisit this topic. Not only have I learned a lot about AEP since then, but there were many questions in that post which clearly indicated that it is a complex topic not well understood.</p>

<!--more-->

<h2 id="first-things-first">First Things First</h2>

<p>Once you have the requirements ready, all Adobe Experience Platform (AEP) implementations must <strong>start with the identity strategy</strong>. Let me repeat that: do not take any further step in AEP until you have a long-term design for the identities that you will use in AEP.</p>

<p>I know how tempting it is to start designing a data model, logging into AEP, and creating schemas and datasets. However, you should begin on paper or a whiteboard. I also know how stressful it is to see a project delayed because of something so <em>basic</em>. Believe me, it will be time well spent. Modifications on paper or a whiteboard are incredibly cheap. Resetting the production sandbox can be very expensive, not because of Adobe’s cost but because of the amount of work that goes down the drain.</p>

<p>Remember one thing: once you have configured AEP identities and <a href="https://www.pedromonjo.com/2022/09/enable-for-profile.html">enabled schemas and datasets for profile</a>, there is no going back. You are stuck with your decisions. If you later realize that you made a mistake in your design and have to start from scratch, you will need to reset the sandbox you were working on.</p>

<p>In the most complex AEP implementation I have ever had, we spent a significant amount of time discussing the identity problem while the project was still in the red. This customer had a very specific setup, which needed a complex solution. It took weeks of discussions, learning all their cases, ensuring that the customer understood AEP identities, and going back and forth with various solutions. I managed to come up with a design that mostly satisfied their requirements, and I am proud to say that they are still using it to this day.</p>

<h2 id="number-of-identifiers">Number of Identifiers</h2>

<p>While designing the strategy, one parameter that you will have to consider is the number of identifiers. At a minimum, you will have two: the <a href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html">ECID</a> and one person identifier.</p>

<p>However, there are many cases when there will be more than one person identifier:</p>

<ul>
  <li>Different business units have their own Customer Relationship Management (CRM) tools.</li>
  <li>Data sources may not all have access to the CRM and manage identity in different ways.</li>
  <li>Data coming from third-party data providers will have their own ID.</li>
  <li>The CRM ID is not available on the web data layer and a different ID is used only for the web.</li>
</ul>

<p>My recommendation is to limit the number of identifiers to a minimum.</p>

<p>Throughout the rest of this post, I will only refer to the person identifier. The ECID is already provided by Adobe. If you are using its cousin, the <a href="https://www.pedromonjo.com/2025/06/fpid.html">FPID</a>, remember that it is converted into an ECID internally.</p>

<p>AEP engineers usually refer to the ECID as the “durable ID”, while referring to the person identifier as the “transient ID”.</p>

<h2 id="what-makes-a-good-identifier">What Makes a Good Identifier?</h2>

<p>Not all identifiers are created equal. Some are good, some are bad, and sometimes you have to use ugly ones.</p>

<h3 id="the-good">The Good</h3>

<p>The best identifiers are those that you control. The typical example of this type of identity is a CRM ID. I expect all companies, big or small, have a CRM. In this system, for every customer, there is an entry in a relational database with a primary key. If you do not want to expose this primary key, you can always hash it or generate a UUID per customer, which would become another column in the CRM database.</p>

<p>Next are other identities that you do not control but have a high degree of confidence they will be unique: an example could be a credit card number. While they can be recycled, combined with the expiration date, the resulting value is unique. As a side note, never use clear-text credit cards in AEP; always hash them first before sending them to AEP.</p>

<h3 id="the-bad">The Bad</h3>

<p>At the other end of the spectrum, we have the bad identifiers. Let me start with the first on the list: email address. I am well aware that this is bad news for many who have relied on this identifier. If you are reading this blog, you are fairly tech-savvy and consider your email address as part of your personal identity. Unfortunately, the reality is that email addresses are shared:</p>

<ul>
  <li>It was a surprise to me when I started hearing about spouses sharing the same email address. I have a close relative who does that and I still do not understand it.</li>
  <li>Parents create online accounts for their children, using the parent’s email address for convenience.</li>
  <li>Grandchildren manage their grandparents’ online accounts, and just like the parents above, they do not want the hassle of having separate email addresses.</li>
  <li>The most extreme case I heard was a football (soccer if you are in the US) club, where they had many fan associations. It was common that the leader of the association would manage the members’ accounts and, again, to avoid multiple email addresses, they used one for all accounts.</li>
</ul>

<p>If you were thinking of phone numbers as a better alternative, the situation is even worse. Mobile operators recycle decommissioned numbers. I even have personal experience with this case.</p>

<p>In summary, any identifier that you cannot control or cannot guarantee will be unique should be avoided; here be dragons.</p>

<h3 id="the-ugly">The Ugly</h3>

<p>More often than I would like, I have had customers who did not want to come up with a good identifier. And I say “did not want” because there were options to get to a good identifier, which they refused for various reasons. The typical excuse is that they expected AEP to take care of their identities. The reality is that AEP is not an identity provider nor an <a href="https://www.pedromonjo.com/2024/02/cdp-vs-mdm.html">MDM tool</a>.</p>

<p>In this case, there are some ugly solutions you can try:</p>

<ul>
  <li><em>Combination of parameters</em>. Theoretically, it could be possible to concatenate two or more parameters to get a unique value. I have suggested it multiple times but I have yet to find a situation where this has worked.</li>
  <li><em>Accept the limitations</em>. Some customers, especially in retail, may accept some <a href="https://www.pedromonjo.com/2022/10/profile-collapse.html">profile collapses</a>, as long as the number is manageable.</li>
  <li><em>Exclude conflicting profiles</em>. In some cases, you could remove all those profiles that you know have shared identities or only load one. As long as you do not use Adobe Journey Optimizer, that may be a good solution.</li>
</ul>

<p>Pick your poison.</p>

<h2 id="configuring-aep">Configuring AEP</h2>

<p>So, now that you have come up with a robust identity strategy and have documented it, you can turn to AEP and start configuring it.</p>

<p>The first step is to set up the namespaces. Think of an identity namespace as a separate database for a specific type of identifier.</p>

<ol>
  <li>Navigate to the Namespaces page. You will see that there are already a bunch of namespaces created, including the ECID.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-21-aep-identity-strategy/aep-namespaces.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-namespaces-300-6b61b1925.png" alt="AEP Namespaces" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-namespaces-300-6b61b1925.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-namespaces-450.0-6b61b1925.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-namespaces-600-6b61b1925.png 2.0x"></a></li>
  <li>For each namespace that you need, create a new one. Give it a name, an identity symbol (no spaces or special characters), and select “Individual cross-device ID”.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-21-aep-identity-strategy/aep-new-namespace.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-new-namespace-300-864f356e3.png" alt="New AEP namespace" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-new-namespace-300-864f356e3.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-new-namespace-450.0-864f356e3.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/aep-new-namespace-600-864f356e3.png 2.0x"></a></li>
</ol>

<p>Now that you have the namespaces set up, you can configure your schemas. Each schema should have:</p>

<ul>
  <li>One or more identifiers. If you have many, I suggest that you create a field group for them. Otherwise, find a sensible place in the XDM hierarchy.</li>
  <li>One identifier must be set as primary, which means that it will be mandatory in every record. AEP will throw an error if a record does not have the primary identity. The rest of the identities will be optional.</li>
</ul>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-21-aep-identity-strategy/xdm-schema-identity.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/xdm-schema-identity-300-07a10e50f.png" alt="XDM schema with identities" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/xdm-schema-identity-300-07a10e50f.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/xdm-schema-identity-450.0-07a10e50f.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-09-21-aep-identity-strategy/xdm-schema-identity-600-07a10e50f.png 2.0x"></a></p>

<h2 id="identitymap">IdentityMap</h2>

<p>There is one exception to the previous step: the schema for the event dataset coming from web or app. While you can still set a field as an identity, it is recommended that you use the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/xdm/field-groups/profile/identitymap"><code class="language-plaintext highlighter-rouge">identityMap</code> field group</a>. As its name implies, it is a map, so you can pass multiple identities in it.</p>

<p>While browsing anonymously, you will only have the ECID, so this field will look like:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"identityMap"</span><span class="p">:{</span><span class="w">
    </span><span class="nl">"ECID"</span><span class="p">:[</span><span class="w">
      </span><span class="p">{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"83238819066235616291057085344313877718"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"authenticatedState"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ambiguous"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"primary"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>After logging in, it will look something similar to:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"identityMap"</span><span class="p">:{</span><span class="w">
    </span><span class="nl">"ECID"</span><span class="p">:[</span><span class="w">
      </span><span class="p">{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"83238819066235616291057085344313877718"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"authenticatedState"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ambiguous"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"primary"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"personID"</span><span class="p">:[</span><span class="w">
      </span><span class="p">{</span><span class="w">
        </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"cd578d2c-12bd-47e8-9fdc-5f9bf31aaab0"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"authenticatedState"</span><span class="p">:</span><span class="w"> </span><span class="s2">"authenticated"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"primary"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Let me explain what you see above:</p>

<ul>
  <li>The fields under the <code class="language-plaintext highlighter-rouge">identityMap</code> object are namespace identity symbols.</li>
  <li>The namespace identity symbols are arrays. In other words, you can have multiple identifiers for each namespace. I have yet to see a use case where more than one identifier is really needed.</li>
  <li>The <code class="language-plaintext highlighter-rouge">id</code> field is the identity for that namespace.</li>
  <li>There must only be one identity with <code class="language-plaintext highlighter-rouge">"primary": true</code>. Typically, it will be the ECID while browsing anonymously, and then switch to your person identifier after logging in.</li>
</ul>

<p>I hope I have answered most of your questions. I know I have not covered everything, but if I did, this post would take forever.</p>

<p>Let me know in the comments what you would want me to address in future posts.</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@thebarlemy?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Barthelemy de Mazenod</a> on <a href="https://unsplash.com/photos/people-walking-inside-building-during-daytime-uogMShrLlhU?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[It has been more than three years since I wrote my first post on AEP identities. I think it is time to revisit this topic. Not only have I learned a lot about AEP since then, but there were many questions in that post which clearly indicated that it is a complex topic not well understood.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-21-aep-identity-strategy/identities.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-21-aep-identity-strategy/identities.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">From SEO To GEO</title><link href="https://www.pedromonjo.com/2025/09/from-seo-to-geo.html" rel="alternate" type="text/html" title="From SEO To GEO" /><published>2025-09-07T00:00:00-04:00</published><updated>2025-09-07T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/09/from-seo-to-geo</id><content type="html" xml:base="https://www.pedromonjo.com/2025/09/from-seo-to-geo.html"><![CDATA[<p>Almost 20 years ago, I started learning about Search Engine Optimization (SEO). I even attended a conference on the topic, where one of the most reputable SEO agencies was presenting. I soon realized that it was not easy and it required a lot of effort. I just scratched the surface, although I understood it well enough. A classmate from my primary school is a real expert in this area. Well, there is a new kid on the block: Generative Engine Optimization (GEO).</p>

<!--more-->

<h2 id="recap-of-seo">Recap of SEO</h2>

<p>Before I talk about the main topic, I want to make sure we are all on the same page. If you have never heard of SEO or Search Engine Optimization, Wikipedia defines it as:</p>

<blockquote>
  <p>Search engine optimization (SEO) is the process of improving the quality and quantity of website traffic to a website or a web page from search engines.</p>
</blockquote>

<p>When you type something into a search engine, its algorithm selects, from all the web pages it has indexed, those that are most likely to provide the information you are looking for. For example, if you type “apple”, what should the results show?</p>

<ul>
  <li>The tech company</li>
  <li>The record label</li>
  <li>The fruit</li>
  <li>A combination of the above</li>
</ul>

<p>Google claims that it uses <a href="https://www.linkedin.com/pulse/googles-200-ranking-factors-complete-list-md-foysol-ahmed-chowdhury--y5kme/">more than 200 ranking factors</a> to decide what results to show.</p>

<p>The goal of SEO is to make sure that the combination of those 200 factors scores the highest number possible for your website, so that pages in your website show up in the first few places of the search engine results page for searches that are relevant to your company. I am sure that you can now see why it is complex and expensive.</p>

<h2 id="generative-ai">Generative AI</h2>

<p>Using search engines requires that you click on a few links on the results page until you find what you were looking for. Most of the time, the first three to five results will get you exactly what you want. However, sometimes none of the results gets you the information that you are looking for. This often happens to me when my search phrase is long and very specific.</p>

<p>With the advent of generative AI and, more specifically, conversational AI tools like ChatGPT, Copilot, or Gemini, you can now ask complex questions, and the engine will reason and provide you with a full response, all of it without having to leave the same UI. It will also provide the most important references it has used to provide the response, but there is no need to visit those references. No wonder that people are switching from search engines to these new tools. The first consequence, which can already be seen by many companies, is that traffic from search engines has started to decline.</p>

<p>I highly recommend this <a href="https://www.forbes.com/sites/torconstantino/2025/04/14/the-60-problem---how-ai-search-is-draining-your-traffic/">Forbes article</a> if you want to dig deeper.</p>

<p>As a side note, I agree with <a href="https://www.ynharari.com/">Yuval Noah Harari</a> that this new set of tools can be very dangerous for our freedom. With search engines, you got ten results per page and you had to process the results. With generative AI tools, you get only one response with everything you asked for. Whoever controls that response controls the narrative.</p>

<h2 id="the-birth-of-geo">The Birth of GEO</h2>

<p>I am sure you are now seeing where I am going. If SEO was needed to keep your website at the top of search engine results pages, now that generative AI is with us, you need to make sure that your information is what these tools use to compose the response. This is what we call GEO.</p>

<p>I have tried to find a clear definition, and <a href="https://en.wikiversity.org/wiki/Generative_Engine_Optimization_(GEO)">the one that I like the most</a> states:</p>

<blockquote>
  <p>Generative Engine Optimization (GEO) is a developing discipline focused on increasing the likelihood that individuals, brands, services, or resources are cited organically in responses generated by large language models (LLMs) such as ChatGPT, Gemini, Claude, and Copilot.</p>
</blockquote>

<p>To me, the most important word in the previous definition is <em>developing</em>. It is very early on and there is not enough research and information about it. However, it starts to be clear that a new discipline and area of expertise will emerge. Everybody will want to have their website as a reference in a generative AI response. Since these responses often include links to the references, visitors can go to the website for more details or to transact. Otherwise, if your website is not picked up by generative AI tools, your website will become invisible.</p>

<h2 id="part-of-marketing-strategies">Part of Marketing Strategies</h2>

<p>I usually start my posts with the <em>why</em>. In this post, I will end with it because I thought it was more important that I first provided the context.</p>

<p>The reason why I wrote this post is to make you all aware of this emerging trend and the impact it will have on digital marketing.</p>

<p>First, companies will likely have to allocate marketing budget to GEO, just like they have been investing in SEO. I am not saying that SEO will go away, at least not in the short term. Investment in SEO will still be needed; it is not free. What I am saying is that digital marketing budgets will now have to include a part for GEO. Companies may need to purchase tools like <a href="https://business.adobe.com/products/llm-optimizer.html">Adobe LLM Optimizer</a> and pay GEO experts.</p>

<p>Second, companies will want to track the results of their GEO efforts, just like we have been tracking the results of traditional marketing activities (paid media, social, SEO, email, etc.) for the past 20 years. <a href="https://www.pedromonjo.com/category/analytics-tips/">Adobe Analytics</a> excels at it thanks to the <a href="https://www.pedromonjo.com/2016/09/marketing-channels-fundamentals.html">Marketing Channels</a> reports. In case you did not make the connection, the “Natural Search” value in the reports is the most approximate way to track SEO efforts. Very soon we will all have to reconfigure these reports to start tracking GEO results.</p>

<p>I know it is still too early to see where GEO will go, but I recommend that you keep an eye on it.</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/an-artist-s-illustration-of-artificial-intelligence-ai-this-piece-explores-the-prediction-method-used-in-large-language-models-it-was-created-by-artist-wes-cockx-as-part-of-the-visuali-18069814/">Photo by Google DeepMind</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[Almost 20 years ago, I started learning about Search Engine Optimization (SEO). I even attended a conference on the topic, where one of the most reputable SEO agencies was presenting. I soon realized that it was not easy and it required a lot of effort. I just scratched the surface, although I understood it well enough. A classmate from my primary school is a real expert in this area. Well, there is a new kid on the block: Generative Engine Optimization (GEO).]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-07-from-seo-to-geo/deepmind.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-09-07-from-seo-to-geo/deepmind.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Non-Profile-Enabled Datasets</title><link href="https://www.pedromonjo.com/2025/08/non-profile-enabled-datasets.html" rel="alternate" type="text/html" title="Non-Profile-Enabled Datasets" /><published>2025-08-24T00:00:00-04:00</published><updated>2025-08-24T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/08/non-profile-enabled-datasets</id><content type="html" xml:base="https://www.pedromonjo.com/2025/08/non-profile-enabled-datasets.html"><![CDATA[<p>When working with Adobe Experience Platform (AEP), sooner or later you will need to decide which datasets should be enabled for profile. It is not a good practice to enable <em>all</em> datasets for profile. In fact, doing so will likely get you into trouble. In this post, I will explain what non‑profile-enabled datasets are, why they are essential in a healthy AEP implementation, and some practical patterns.</p>

<!--more-->

<h2 id="what-is-a-nonprofile-enabled-dataset">What is a Non‑Profile-Enabled Dataset?</h2>

<p>In AEP, data lands in the <a href="https://www.pedromonjo.com/2023/05/data-lake.html">Data Lake</a> after being ingested or generated. From there, you <em>may</em> choose to project certain datasets into the <a href="https://www.pedromonjo.com/2023/05/real-time-customer-profile.html">Real‑Time Customer Profile</a> (RTCP) by enabling both the schema and the dataset for profile.</p>

<p>Any dataset not projected to RTCP is a non‑profile-enabled dataset. It still lives in the Data Lake and can be fully leveraged by many other tools, such as:</p>

<ul>
  <li>Customer Journey Analytics (CJA)</li>
  <li>Data Distiller</li>
  <li>External BI tools via the Postgres/BI connector</li>
</ul>

<p>To clarify, most datasets—including those that are profile-enabled—reside in the Data Lake.</p>

<h2 id="why-keep-some-datasets-out-of-rtcp">Why Keep Some Datasets <em>Out</em> of RTCP?</h2>

<p>You know how much I like to start with the <em>why</em>. Here are several reasons to keep certain datasets only in the Data Lake:</p>

<ul>
  <li><em>Cost control</em>. The profile store and identity graph are expensive. Enabling large datasets for profile will increase your license cost.</li>
  <li><em>Performance</em>. Loading data into RTCP is resource-intensive. The fewer datasets you enable for profile, the faster ingestion will be.</li>
  <li><em>Data not used for activation</em>. If the data will not be used in segmentation or personalization, it does not belong in RTCP.</li>
  <li><em>Development and testing</em>. You should <strong>never</strong> enable a schema or dataset for profile without thorough testing in the Data Lake.</li>
  <li><em>Raw datasets</em>. Sometimes a dataset contains too much information, when only part of it is needed for profile. In such cases, the raw dataset should remain outside RTCP and can later be refined into a smaller, profile-enabled dataset.</li>
</ul>

<h2 id="core-use-cases">Core Use Cases</h2>

<h3 id="use-in-customer-journey-analytics">Use in Customer Journey Analytics</h3>

<p><a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-connections/overview">CJA data connections</a> are established directly with the Data Lake, not RTCP.</p>

<p>It is common to duplicate data from a single upstream data source: one version, with only the attributes required for activation, is sent to a profile-enabled dataset; another version, with the attributes needed for reporting in CJA, is sent to a non-profile-enabled dataset.</p>

<h3 id="use-in-data-distiller">Use in Data Distiller</h3>

<p>A full post would be required to explain everything Data Distiller can do. If you have a license, you are probably already putting it to good use. Query Service (the service behind Data Distiller) works exclusively with the Data Lake.</p>

<p>This means that whenever data is intended for Data Distiller but not needed in RTCP, the source datasets should remain non-profile-enabled.</p>

<p>Typical scenarios include:</p>

<ul>
  <li><em>Derived datasets for profile</em>. A large dataset is ingested into the Data Lake, but only certain attributes are needed in RTCP. A SQL query can extract those attributes and <a href="https://experienceleague.adobe.com/en/docs/experience-platform/query/data-distiller/derived-datasets/create-derived-datasets-with-sql">write them into a new dataset</a> that is profile-enabled.</li>
  <li><em>Derived datasets for export</em>. Sometimes a custom dataset is required for export. By using the same procedure, you can then <a href="https://experienceleague.adobe.com/en/docs/experience-platform/destinations/ui/activate/export-datasets">map the output dataset to a cloud destination</a>. In this case, the output dataset will generally not be enabled for profile.</li>
  <li><em>Audience creation</em>. You can also <a href="https://experienceleague.adobe.com/en/docs/experience-platform/query/data-distiller-audiences/overview">create audiences with Data Distiller</a>. This works similarly to the above examples, where a SQL query selects identities which are then used to build an audience.</li>
</ul>

<p>For more insights, see the Adobe Summit 2025 session <a href="https://experienceleague.adobe.com/en/docs/experience-platform/query/data-distiller/top-tips-to-maximize-value">S656 - Top Tips to Maximize Value with Adobe Experience Platform Data Distiller</a>.</p>

<h3 id="profile-snapshot">Profile Snapshot</h3>

<p>Every day, the contents of RTCP are copied into a dataset. You can identify this dataset by its name:</p>

<p><code class="language-plaintext highlighter-rouge">Profile-Snapshot-Export-&lt;UUID&gt;</code></p>

<p>Naturally, this dataset is not profile-enabled. Its common uses include:</p>

<ul>
  <li>serving as input to Data Distiller, or</li>
  <li>exporting to a cloud destination.</li>
</ul>

<p> </p>

<p>Non-profile-enabled datasets are just as important as profile-enabled ones for keeping your AEP implementation balanced, cost-efficient, and high-performing.</p>

<p>Let me know in the comments if you have seen other interesting use cases for non-profile-enabled datasets.</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/empty-gray-canoe-boat-near-shore-during-golden-hour-2132008/">Photo by Quang Nguyen Vinh</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[When working with Adobe Experience Platform (AEP), sooner or later you will need to decide which datasets should be enabled for profile. It is not a good practice to enable all datasets for profile. In fact, doing so will likely get you into trouble. In this post, I will explain what non‑profile-enabled datasets are, why they are essential in a healthy AEP implementation, and some practical patterns.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-24-non-profile-enabled-datasets/lake.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-24-non-profile-enabled-datasets/lake.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Identity Graph Linking Rules</title><link href="https://www.pedromonjo.com/2025/08/identity-graph-linking-rules.html" rel="alternate" type="text/html" title="Identity Graph Linking Rules" /><published>2025-08-10T00:00:00-04:00</published><updated>2025-08-10T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/08/identity-graph-linking-rules</id><content type="html" xml:base="https://www.pedromonjo.com/2025/08/identity-graph-linking-rules.html"><![CDATA[<p>One of the most painful issues that all our Adobe Experience Platform (AEP) customers have faced is the <a href="https://www.pedromonjo.com/2022/10/profile-collapse.html">profile collapse</a>. The only comment I received on that post started with: <em>“This is a giant problem.”</em> Well, the wait is over — a solution has been implemented and is now generally available: <strong>Identity Graph Linking Rules</strong>. If you have suffered from this issue, keep reading.</p>

<!--more-->

<h2 id="pre-requisites">Pre-Requisites</h2>

<p>To understand the solution, you first need to understand how AEP works internally. There are two main concepts that are prerequisites to the explanation in this post. I recommend you review them if you are not familiar with these concepts before continuing.</p>

<ul>
  <li><a href="https://www.pedromonjo.com/2022/05/understanding-aep-identities.html">AEP Identities</a>, in particular the concept of namespaces.</li>
  <li><a href="https://www.pedromonjo.com/2025/04/profile-projection.html">Profile Projection</a>, especially how the identity graph is used.</li>
</ul>

<h2 id="how-identity-graph-linking-rules-work">How Identity Graph Linking Rules Work</h2>

<p>The concept behind this feature is very simple: break links within the identity graph if <strong>more than one identity from a given namespace is present in that graph</strong>.</p>

<p>Let me explain with a simple scenario, where Alice and Bob share the same device. I will use the email address as an identity for illustration purposes; in general, it is not recommended to use it in real scenarios.</p>

<ol>
  <li>
    <p>Alice uses the shared device and logs in to your website. An <a href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html">ECID</a> is generated on the landing page and, after logging in, AEP links Alice and the ECID.<br />
<img src="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/step1.svg" alt="Step 1 - Alice logs in" width="500" /></p>
  </li>
  <li>
    <p>Now Bob wants to access the same website using the shared device. After he logs in, AEP links Bob to the same ECID from the previous step, resulting in a profile collapse — there is now a single graph containing both Alice and Bob.<br />
<img src="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/step2.svg" alt="Step 2 - Bob logs in" width="500" /></p>
  </li>
  <li>
    <p>With identity graph linking rules enabled and configured, the oldest email address is removed from the graph, as it violates the rule of having only one email address per graph.<br />
<img src="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/step3.svg" alt="Step 3 - Graph is uncollapsed" width="500" /></p>
  </li>
</ol>

<p>The end result is that we now have two identity graphs:</p>

<ul>
  <li>Alice has only her email address.</li>
  <li>Bob has his email address and the ECID.</li>
</ul>

<p><img src="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/final.svg" alt="Final graph" width="500" /></p>

<h2 id="the-ecid-trade-off">The ECID Trade-Off</h2>

<p>You may have noticed there is a catch with the ECID. Since the ECID is now always linked to only one profile, all anonymous events are tied to that profile. In the previous example, anything Alice did before logging in will be attributed to Bob.</p>

<p>Some may argue this is an issue, but I would counter that there is no guarantee that anonymous events belong to the next person who logs in. While it could be an educated guess, it could just as well be the case that Bob used the shared device anonymously, and then Alice logged in afterward. There is no reliable way to determine who was behind the device before a login.</p>

<p>One way to address this issue is to create a merge policy that does not stitch identities (<a href="https://experienceleague.adobe.com/en/docs/experience-platform/profile/merge-policies/overview#id-stitching">ID stitching</a> set to “None”) and use it as the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/profile/merge-policies/ui-guide#configure">Active-On-Edge Merge Policy</a>. With this configuration, anonymous events will not be combined with events after login. As always, do not immediately apply such configuration changes without fully understanding their implications and testing them in a development environment.</p>

<h2 id="beyond-the-basics">Beyond The Basics</h2>

<p>I strongly recommend spending time reviewing the full documentation on <a href="https://experienceleague.adobe.com/en/docs/experience-platform/identity/features/identity-graph-linking-rules/overview">Identity Graph Linking Rules</a>, including the accompanying videos. I have explained only the simplest case, with two identity namespaces. If you have more than two, and a collapse could occur in different parts of the hierarchy, you must clearly understand what happens in each scenario. The possibilities grow exponentially with each namespace and each potential identity combination, making it impossible to document every case here.</p>

<p>To help visualize the behavior of this functionality, Adobe provides a <a href="https://experienceleague.adobe.com/en/docs/experience-platform/identity/features/identity-graph-linking-rules/graph-simulation">Graph Simulation</a> tool. I find this tool incredibly useful — you can load different scenarios and see exactly how the graphs will behave. Use it extensively in a development sandbox, testing all options and configurations until you find the optimal setup. Only then you should replicate it in your production environment. Client feedback on this tool has been very positive.</p>

<p>A customer recently asked if there was a rollback mechanism to restore the state from before enabling linking rules. The short answer is no. This is another reason why the simulation tool is so important.</p>

<h2 id="exceptions">Exceptions</h2>

<p>While this solution works very well for many of Adobe’s clients, it is not <em>the</em> solution for all cases. I have worked with customers who are hesitant to enable Identity Graph Linking Rules because of the consequences for their identity strategies. As mentioned above, my recommendation is to use the simulation tool to analyze your specific use cases before making a decision. If it creates more problems than it solves, do not use it.</p>

<p> </p>

<p>I want to thank <a href="https://www.linkedin.com/in/shotaido/">Shota Ido</a>, the Adobe product manager responsible of leading the efforts in making this solution a reality.</p>

<p><small><a href="https://www.pexels.com/photo/women-wearing-denim-pants-linking-their-arms-8297388/">Photo by Rizky Sabriansyah</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[One of the most painful issues that all our Adobe Experience Platform (AEP) customers have faced is the profile collapse. The only comment I received on that post started with: “This is a giant problem.” Well, the wait is over — a solution has been implemented and is now generally available: Identity Graph Linking Rules. If you have suffered from this issue, keep reading.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/women-linking-arms.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-08-10-identity-graph-linking-rules/women-linking-arms.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Virtuous Circle of Marketing</title><link href="https://www.pedromonjo.com/2025/07/virtuous-circle-marketing.html" rel="alternate" type="text/html" title="The Virtuous Circle of Marketing" /><published>2025-07-27T00:00:00-04:00</published><updated>2025-07-27T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/07/virtuous-circle-marketing</id><content type="html" xml:base="https://www.pedromonjo.com/2025/07/virtuous-circle-marketing.html"><![CDATA[<p>I came up with this name while I was preparing for my Summit 2025 session. Perhaps I was simply having a good day and my neurons made the right connection. Since then, I have engaged in conversations where the same concept has emerged and resonated with others. Let me explain.</p>

<!--more-->

<h2 id="definitions">Definitions</h2>

<p>Most people are familiar with the concept of a <em>vicious circle</em>. I picture this as a downward spiral, with each iteration making the situation worse than before.</p>

<p>The opposite of a vicious circle is a <em>virtuous circle</em>, where the spiral moves upwards and, with every iteration, results improve.</p>

<h2 id="campaigns-are-linear">Campaigns are Linear</h2>

<p>Traditionally, marketing campaigns are linear. Regardless of whether it involves an email, website personalization, display advertising, or social advertising, the approach usually follows a sequence from start to finish.</p>

<p>It typically begins with a brief: an outline describing what the campaign should achieve. In technical terms, this is often called the requirements document.</p>

<p>From the brief, the creative team begins working on the campaign’s components:</p>

<ul>
  <li>Images must be created.</li>
  <li>Text must be written.</li>
  <li>Occasionally, a video will be included.</li>
  <li>A call to action is defined.</li>
  <li>The landing page URL is determined.</li>
</ul>

<p>Once the creative process is complete, the marketing operations team prepares the campaign:</p>

<ul>
  <li>Images need to be stored in a digital asset management tool.</li>
  <li>The HTML for the email must be created.</li>
  <li>Segments are created in RTCDP.</li>
  <li>Activities and experiences are configured in Adobe Target.</li>
  <li>Campaigns are set up in the relevant tools provided by social network platforms.</li>
  <li>Landing pages are published.</li>
</ul>

<p>When you finally have everything ready, you publish the campaign, hold your breath and cross your fingers. Some adjustments may have to be made if issues show up.</p>

<p>And, last but not least, reports are generated to assess the success (or otherwise) of the campaign.</p>

<p>Of course, this is a simplified process. If you are part of any of the teams mentioned above, you know the work involved is much greater than what is described here. My intention was to provide an overview.</p>

<p>For reference, most of the above can be managed through Adobe Workfront. This is a tool I have not yet written about, but I am seeing increasing potential for it.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-27-virtuous-circle-marketing/linear-campaign.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/linear-campaign-300-5e47f9b14.png" alt="Linear Campaign" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/linear-campaign-300-5e47f9b14.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/linear-campaign-450.0-5e47f9b14.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/linear-campaign-600-5e47f9b14.png 2.0x"></a></p>

<h2 id="closing-the-loop">Closing the Loop</h2>

<p>Although the above steps have made sense for many years, something crucial is missing: a feedback loop.</p>

<p>With a linear approach, once a campaign concludes, it is typically shelved. This practice leaves behind a wealth of valuable information—insights about what worked well, what did not, and what could have been done differently.</p>

<p>The idea behind the virtuous circle applied to digital marketing is to capture all learnings from previous campaigns and apply them to future ones. The main objective is to avoid repeating past mistakes and to continually enhance marketing results.</p>

<p>A word of caution: avoid the trap of repeating the same campaign with only minor changes. Instead, identify and replicate the key elements that made previous campaigns successful.</p>

<p><a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-27-virtuous-circle-marketing/virtuous-circle.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/virtuous-circle-300-89568d8bc.png" alt="Virtuous Circle" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/virtuous-circle-300-89568d8bc.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/virtuous-circle-450.0-89568d8bc.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-07-27-virtuous-circle-marketing/virtuous-circle-600-89568d8bc.png 2.0x"></a></p>]]></content><author><name>Pedro Monjo</name></author><category term="Opinion" /><summary type="html"><![CDATA[I came up with this name while I was preparing for my Summit 2025 session. Perhaps I was simply having a good day and my neurons made the right connection. Since then, I have engaged in conversations where the same concept has emerged and resonated with others. Let me explain.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-27-virtuous-circle-marketing/circles-arrows.png" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-27-virtuous-circle-marketing/circles-arrows.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Understanding CJA Sessions</title><link href="https://www.pedromonjo.com/2025/07/understanding-cja-sessions.html" rel="alternate" type="text/html" title="Understanding CJA Sessions" /><published>2025-07-13T00:00:00-04:00</published><updated>2025-07-13T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/07/understanding-cja-sessions</id><content type="html" xml:base="https://www.pedromonjo.com/2025/07/understanding-cja-sessions.html"><![CDATA[<p>One of the <a href="https://www.pedromonjo.com/2025/06/aa-vs-cja-basic-metrics.html#isso-731">comments I received in my last blog post</a> asked for more details about CJA sessions: tips, tricks, and pitfalls. That was a very good question and, since I have it fresh in my memory, I decided to write about it immediately.</p>

<!--more-->

<h2 id="your-definition">Your Definition</h2>

<p>With Adobe Analytics (AA), the definition of a visit is set in stone by the industry. Remember that AA was designed to measure web traffic, so adopting a <em>de facto</em> standard makes a lot of sense. This has a few consequences:</p>

<ul>
  <li>You can compare the reports from multiple web analytics tools, as all should render similar results.</li>
  <li>Unless you use Virtual Report Suites, you have no control over the visit metric.</li>
  <li>If you shoehorn non-web and non-app events into AA, your visit metric may become totally useless.</li>
</ul>

<p>Now, with CJA and as I explained in my previous post, <em>you</em> define a session, so you should know what it is and how it behaves. You have some freedom to define when a visit starts and when it ends, so it aligns with your needs. However, this also means that you have to always remember your definition of session. As the saying goes, with great power comes great responsibility. Choose wisely!</p>

<p>It is also worth reminding that this definition can vary by <a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-dataviews/session-settings">data view</a>.</p>

<h2 id="know-your-data">Know Your Data</h2>

<p>In AA, the data sources are always very well known: web and app. We have been tracking page views for more than two decades, and we are pretty confident we understand them.</p>

<p>With CJA, there can be many data sources, and very different. Before you combine all the events in a single CJA connection, and before you define the session, you need to understand these events. Let’s see a few examples:</p>

<ul>
  <li><em>Web + app clickstream</em>. As I have explained, we are all very familiar with them.</li>
  <li><em>Phone calls</em>. You could get only one event per call, one event at the beginning and one at the end, one event every second the call lasts, one event per topic discussed, one event every time someone speaks… In general, these events will have only a few attributes. However, seeing what AI can do, you could extract some metadata from the conversation and include it in the events. I am thinking information like the topic and the tone.</li>
  <li><em>Email interactions</em>. These events are also fairly standard: sends, bounces, opens, clicks, unsubscribes, and a few others. However, some of these events are very unreliable. For example, many email providers do not report bounces or opens.</li>
  <li><em>Purchases</em>. This data source will be very common in retail, with purchases coming from brick-and-mortar stores, app, web, 3<sup>rd</sup> parties, call center, and maybe other places. With purchases, you can also get other additional events like returns or failed purchases (e.g., declined credit card).</li>
  <li><em>B2B interactions</em>. Now that <a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-overview/cja-b2b/cja-b2b-edition">CJA B2B</a> has been released, a whole new set of events could flow to CJA: meetings, webinars, LinkedIn messages, and many more.</li>
</ul>

<p>It is obvious that each of these sources has different patterns. Some could have multiple events in a short period of time, whereas others will only be single events. We can all agree that the concept of <em>session</em> is different for each source. However, since you will likely combine these data sources in a single connection, you may need multiple data views, each of which with its own definition of session to satisfy your needs. There are two broad options:</p>

<ul>
  <li>If the sessions have a short expiration, you will get many sessions. Every website visit, purchase, email sent, and phone call will generate one session, which will have a low number of events.</li>
  <li>With long expirations, sessions will include events that are very far apart, losing granularity. The total number of sessions will go down.</li>
</ul>

<p>It is important to clarify that there is no right or wrong. It is all about you, and how you want the data to be processed. This also means that you cannot say “I’m not technical, I don’t need to understand the data.” You must know well how your data looks.</p>

<h2 id="more-than-a-visit">More Than a Visit</h2>

<p>Consider the following potential scenario:</p>

<ol>
  <li>A user is using your app.</li>
  <li>A certain interaction with the app triggers an AJO journey.</li>
  <li>In the journey, an email is sent to the user’s email address.</li>
  <li>The user opens, reads, and clicks on an email link.</li>
  <li>The user lands on the website and tries to do a transaction.</li>
  <li>An issue prevents her from finalizing the transaction and she starts a chat with your customer support team.</li>
  <li>The issue is resolved.</li>
  <li>The user finalizes the transaction online.</li>
</ol>

<p>How many data sources do we have here?</p>

<ul>
  <li>App clickstream</li>
  <li>Email interactions</li>
  <li>Web clickstream</li>
  <li>Chat interactions</li>
</ul>

<p>With CJA, all the touchpoints of the user with your company can become part of the session. The important word from the previous sentence is <em>can</em>, as it is up to you to decide which data sources you include in CJA and when a session starts. Not only that, you can decide when a session ends. Do you want to wait for all 8 steps and make them one session, or do you want to split the session into two or three, if the user takes a few minutes/hours/days to read the email or if the user finalizes the transaction some time later?</p>

<p>Keep in mind that a session can be triggered for a wide variety of reasons: an email send, landing on a website, placing a call… It is definitely more than a website visit.</p>

<h2 id="does-session-make-sense">Does Session Make Sense?</h2>

<p>I have two uncomfortable questions for you:</p>

<ul>
  <li>What do you need the session metric for?</li>
  <li>What value is this metric bringing to you?</li>
</ul>

<p>Again, there are no right or wrong answers, just your answers. It may well be that a session is totally meaningless to you or, even if it has a physical meaning, you are not going to do anything with this metric. In this case, just stop using it.</p>

<p>I would argue that there are some cases where this metric is objectively useless. For example, if you are generating an Adobe Journey Optimizer (AJO) report in CJA using the journey step dataset, even if you can generate a session metric, it has nothing to do with customer interactions. At best, it will show how AJO is working internally.</p>

<p>However, before you throw away the session metric or before you settle on one definition, you may want to try out a few options. A data analyst should be able to help you. Remember to delete the data view that you are not going to use, so that nobody uses it.</p>

<h2 id="do-not-compare-with-adobe-analytics">Do Not Compare with Adobe Analytics</h2>

<p>Last, but not least, even if you think that you have re-created the AA visit definition in CJA, do not expect to get the same results in both tools, especially during the transition. There will always be a discrepancy, no matter what you do. Believe me, I have worked in the past trying to marry metrics coming from different ways of processing the data and it is impossible to get to 100% alignment.</p>

<p>I am not saying that you should not even look at these metrics side by side. AA will give you a ballpark number that you should expect in CJA. However, other than that, any other similarity will be pure coincidence.</p>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@almapapi?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Krisztina Papp</a> on <a href="https://unsplash.com/photos/group-of-people-inside-structure-_wkrWd5o8sA?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[One of the comments I received in my last blog post asked for more details about CJA sessions: tips, tricks, and pitfalls. That was a very good question and, since I have it fresh in my memory, I decided to write about it immediately.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-13-understanding-cja-sessions/shopping-mall.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-07-13-understanding-cja-sessions/shopping-mall.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AA vs CJA: Basic Metrics</title><link href="https://www.pedromonjo.com/2025/06/aa-vs-cja-basic-metrics.html" rel="alternate" type="text/html" title="AA vs CJA: Basic Metrics" /><published>2025-06-29T00:00:00-04:00</published><updated>2025-06-29T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/06/aa-vs-cja-basic-metrics</id><content type="html" xml:base="https://www.pedromonjo.com/2025/06/aa-vs-cja-basic-metrics.html"><![CDATA[<p>I am currently working on a project where my client is in the process of transitioning from <a href="https://www.pedromonjo.com/category/analytics-tips/">Adobe Analytics</a> (AA) to Customer Journey Analytics (CJA). A few months ago, I helped another customer with their CJA implementation. While AA and CJA are <em>similar</em>, they are definitely not the same beast. Of the many differences that they have, I will start today with the basic metrics.</p>

<!--more-->
<!-- markdownlint-disable MD024 -->

<h2 id="why-metric-definitions-matter">Why Metric Definitions Matter</h2>

<p>If you are migrating to CJA, you may notice that your numbers do not match exactly with what you saw in AA. This is not a bug, it is a reflection of how the platforms are designed. You also need to make sure this knowledge is propagated, you do not want an executive calling you in alarm because the numbers do not match.</p>

<p>Let us examine the details.</p>

<h2 id="page-view-vs-event">Page View vs Event</h2>

<p><em>[UPDATE] I have updated this section and replace the word “hit” with “event”, which is in line with CJA’s documentation. Thanks Rob for pointing out this error.</em></p>

<p>Do you remember those old website counters from the early days of the web? Tracking user activity has evolved considerably since then.</p>

<h3 id="adobe-analytics">Adobe Analytics</h3>

<p>The basic metric in web is <em>page view</em>. In a traditional website, every time a page (HTML) is rendered by a browser, we count it as a page view. With single-page applications (SPA), there is no page load, but the rule of thumb is that if the content changes by more than 50%, we count it as a page view.</p>

<p>Although AA was designed for the web, when mobile apps disrupted the market, it was not too far-fetched to equate app screens to web pages. I know that mobile implementations are very different from web applications, but we could continue to apply the same 50% rule as with SPAs. This meant that AA could also be used to track mobile apps.</p>

<p>Technically, either <code class="language-plaintext highlighter-rouge">s.t()</code> or <code class="language-plaintext highlighter-rouge">MobileCore.trackState()</code> needs to be invoked for a page view to be recorded in AA.</p>

<p>The other option that we have with AA are clicks (or any other interaction), which are tracked with <code class="language-plaintext highlighter-rouge">s.tl()</code> or <code class="language-plaintext highlighter-rouge">MobileCore.trackAction()</code>. These calls are also recorded but do not increment the page view counter.</p>

<h3 id="customer-journey-analytics">Customer Journey Analytics</h3>

<p>CJA, on the other hand, was created to process any type of event: page views, web clicks, phone calls, email opens, journey steps… So, while page views will be one case that we will often see, it is not the only one. The decision was then made that any event processed by CJA will be called a <em>event</em>. In other words, events just count the number of rows in an ExperienceEvent dataset. All page views are evebts, but not all events are page views.</p>

<p>If you still want to count page views, you can create a custom metric for events with <code class="language-plaintext highlighter-rouge">eventType == web.webpagedetails.pageViews</code>. However, this relies on the Web SDK and Mobile SDK implementations to use the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/xdm/classes/experienceevent#eventType">recommended <code class="language-plaintext highlighter-rouge">eventType</code> values</a>.</p>

<h2 id="visit-vs-session">Visit vs Session</h2>

<p>Marketers want to know how many times a user has interacted with their brand. Things get blurry with this ask: while we can detect when a user starts interacting with a brand (lands on the home page, opens the app…), we can never be sure when they stop. We have all seen friends and coworkers with dozens of tabs open. Or maybe you are one of them 😉. Does this mean that they are interacting with all tabs simultaneously? In other words, is keeping a browser tab open enough to count as “interaction”? If a user is browsing a website, attends a phone call for 45 minutes, and resumes browsing, should this count as one or two interactions?</p>

<h3 id="adobe-analytics-1">Adobe Analytics</h3>

<p>Given this uncertainty and to unify criteria, the industry came up with a standard definition: temporary interactions with a website were called <em>visits</em>. A visit starts with the first page view and ends after 30 minutes of inactivity (i.e., no tracking calls from the browser for 30 minutes).</p>

<p>To account for some edge cases, Adobe Analytics also imposes some <a href="https://experienceleague.adobe.com/en/docs/analytics/components/metrics/visits#how-this-metric-is-calculated">additional restrictions to visits</a>.</p>

<p>Virtual Report Suites (VRS) provided some flexibility to the rigidity of this definition, where you could <a href="https://experienceleague.adobe.com/en/docs/analytics/components/virtual-report-suites/vrs-workflow/vrs-create#define-visit-definition">define the visit</a> according to your needs.</p>

<h3 id="customer-journey-analytics-1">Customer Journey Analytics</h3>

<p>CJA follows the same approach as VRS and allows you to <a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-dataviews/session-settings">configure the start and end of a <em>session</em></a>, which is the new name for this metric.</p>

<p>Do not get confused with the concept of a browser session, which is different from this CJA session. You have more details in my old post <a href="https://www.pedromonjo.com/2019/02/visits-sessions.html">Of Visits and Sessions</a>.</p>

<h2 id="visitor-vs-people">Visitor vs People</h2>

<p>Finally, we want to know how many real people are behind those visits and page views.</p>

<h3 id="adobe-analytics-2">Adobe Analytics</h3>

<p>As with most digital marketing tools, AA identifies users through cookies. In order to calculate <em>unique visitors</em> over a period of time, AA just counts the total number of distinct <a href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html">ECID</a> cookies it has seen during that period.</p>

<p>As I explained in the linked post, ECID cookies are unique per browser and can be deleted. The consequence is that a single user will end up having multiple ECIDs. Therefore, the visitor metric is always going to be inflated.</p>

<p>I would like to add a couple of clarifications:</p>

<ul>
  <li>AA does not count the number of ECIDs generated, only those in the event calls received by its servers.</li>
  <li>The old ECID Service API has a method called <a href="https://experienceleague.adobe.com/en/docs/id-service/using/id-service-api/methods/setcustomerids"><code class="language-plaintext highlighter-rouge">setCustomerIDs()</code></a>, but it has no implication over the number of visitors.</li>
</ul>

<h3 id="customer-journey-analytics-2">Customer Journey Analytics</h3>

<p>When you <a href="https://experienceleague.adobe.com/en/docs/analytics-platform/using/cja-connections/create-connection">create a CJA connection</a>, one of the parameters that you have to select is the Person ID. CJA uses this parameter to deduplicate visitors that are actually the same person. If there is no Person ID associated with an ECID, the ECID will be counted as a person, but when it can be linked to a Person ID, all ECIDs belonging to the same Person ID will be collapsed into one.</p>

<p>CJA calls the number of Person IDs <em>people</em>, which is the new metric that you will see in your reports.</p>

<p>This has two important consequences:</p>

<ul>
  <li>The people count will always be lower than the number of visitors. In an AA to CJA transition, there will be no like-for-like comparison of these two metrics.</li>
  <li>The people count of past dates will decrease over time, as CJA gets more links between ECIDs and Person IDs. Multiple ECIDs will become just one person.</li>
</ul>

<h2 id="key-differences-at-a-glance">Key Differences at a Glance</h2>

<p>Let me finish with a summary of these metrics in table format, for your convenience:</p>

<style type="text/css">
    #cmp-aa-cja {
        width: auto;
    }
</style>

<table id="cmp-aa-cja" class="table table-bordered">
  <thead>
    <tr>
      <th>AA</th>
      <th>CJA</th>
      <th>What is different?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Page view</td>
      <td>Event</td>
      <td>CJA counts all events</td>
    </tr>
    <tr>
      <td>Visit</td>
      <td>Session</td>
      <td>CJA sessions are flexible</td>
    </tr>
    <tr>
      <td>Visitor</td>
      <td>Person</td>
      <td>CJA deduplicates users</td>
    </tr>
  </tbody>
</table>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@valeon?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Mitchel Boot</a> on <a href="https://unsplash.com/photos/selective-photography-of-controllers-hOf9BaYUN88?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><category term="Analytics Tips" /><summary type="html"><![CDATA[I am currently working on a project where my client is in the process of transitioning from Adobe Analytics (AA) to Customer Journey Analytics (CJA). A few months ago, I helped another customer with their CJA implementation. While AA and CJA are similar, they are definitely not the same beast. Of the many differences that they have, I will start today with the basic metrics.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-29-aa-vs-cja-basic-metrics/gauges.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-29-aa-vs-cja-basic-metrics/gauges.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">First Party ID</title><link href="https://www.pedromonjo.com/2025/06/fpid.html" rel="alternate" type="text/html" title="First Party ID" /><published>2025-06-15T00:00:00-04:00</published><updated>2025-06-15T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/06/fpid</id><content type="html" xml:base="https://www.pedromonjo.com/2025/06/fpid.html"><![CDATA[<p>Now that I have addressed the <a href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html">Experience Cloud ID</a> (ECID) from a 2025 perspective, I can proceed to write a post on the <strong>First Party ID</strong> (FPID). It has remained on my list of future posts for some time, but until recently, I had not encountered it in a client scenario. Now that I have sufficient context, I can provide an explanation of this feature, how to use it, and the typical use cases for it.</p>

<!--more-->

<h2 id="what-is-this-fpid">What is this FPID?</h2>

<p>As you very well know, all Adobe tools share a unique identifier for anonymous visitors: the ECID. It has played a pivotal role since we began integrating tools, starting with <a href="https://www.pedromonjo.com/category/analytics-tips/">Adobe Analytics</a> and Adobe Target in A4T. However, what if you cannot store the ECID client-side or have a better identifier? Would it not be preferable if you could supply an equivalent identifier that you control?</p>

<p>This is where the FPID becomes relevant. If you are using <a href="https://www.pedromonjo.com/2025/03/aep-edge-network.html">AEP’s Edge Network</a>, you can supply your own durable identifier instead of the ECID. In other words, the FPID is a unique identifier generated and managed by you, the Adobe client.</p>

<h2 id="how-it-works-internally">How It Works Internally</h2>

<p>In case you are wondering how the FPID is treated, the process is quite simple. The AEP Edge Network uses it to create an ECID and then uses this ECID internally. The most important detail is that this conversion from FPID to ECID is deterministic. This means that for a given FPID, AEP will always generate the same ECID.</p>

<h2 id="how-to-use-it">How to Use It</h2>

<p>To enable and use the FPID in your implementation, follow these steps.</p>

<h3 id="1-generate-the-fpid">1. Generate the FPID</h3>

<p>The first step is to generate this durable ID. This must occur outside of the Adobe stack. Remember, if you are choosing to use the FPID, it is because you believe it will work better than the ECID for your use case. You are responsible for its full lifecycle: creation, retrieval, and storage.</p>

<p>One important detail is that Adobe only supports the <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_%28random%29">UUIDv4</a> format for the FPID.</p>

<h3 id="2-edge-configuration">2. Edge Configuration</h3>

<p>If you are going to send the FPID using the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/xdm/field-groups/profile/identitymap"><code class="language-plaintext highlighter-rouge">identityMap</code></a> XDM parameter, you are all set in terms of configuration.</p>

<p>The alternative is to send it in a cookie. To do this, you need to:</p>

<ol>
  <li>Store the <a href="#1-generate-the-fpid">generated FPID</a>  in a first-party cookie.</li>
  <li>Set up a CNAME for the Edge Network so that the calls to it are made in a first-party context.</li>
  <li>Configure the datastream to read this cookie from the HTTP request.
<a data-toggle="lightbox" href="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-15-fpid/new-datastream-fpid.png"><img loading="lazy" src="https://www.pedromonjo.com/assets/images/responsive/2025/2025-06-15-fpid/new-datastream-fpid-300-8bc5b9bd3.png" alt="New Datastream FPID configuration" srcset="https://www.pedromonjo.com/assets/images/responsive/2025/2025-06-15-fpid/new-datastream-fpid-300-8bc5b9bd3.png 1.0x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-06-15-fpid/new-datastream-fpid-450.0-8bc5b9bd3.png 1.5x, https://www.pedromonjo.com/assets/images/responsive/2025/2025-06-15-fpid/new-datastream-fpid-600-8bc5b9bd3.png 2.0x"></a></li>
</ol>

<h3 id="3-send-the-fpid">3. Send the FPID</h3>

<p>As described in the previous step, there are two ways to send the FPID.</p>

<p>If you send it in the <code class="language-plaintext highlighter-rouge">identityMap</code>, you must use the out-of-the-box identity namespace <code class="language-plaintext highlighter-rouge">FPID</code>. For example:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err"> </span><span class="w"> </span><span class="nl">"identityMap"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="err">   </span><span class="w"> </span><span class="nl">"FPID"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="err">     </span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="err">       </span><span class="w"> </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"123e4567-e89b-12d3-a456-426614174000"</span><span class="p">,</span><span class="w">
</span><span class="err">       </span><span class="w"> </span><span class="nl">"authenticatedState"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ambiguous"</span><span class="p">,</span><span class="w">
</span><span class="err">       </span><span class="w"> </span><span class="nl">"primary"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span><span class="err">     </span><span class="w"> </span><span class="p">}</span><span class="w">
</span><span class="err">   </span><span class="w"> </span><span class="p">],</span><span class="w">
</span><span class="err">   </span><span class="w"> </span><span class="nl">"EMAIL"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="err">     </span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="err">       </span><span class="w"> </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"email@mail.com"</span><span class="p">,</span><span class="w">
</span><span class="err">       </span><span class="w"> </span><span class="nl">"authenticatedState"</span><span class="p">:</span><span class="w"> </span><span class="s2">"authenticated"</span><span class="w">
</span><span class="err">     </span><span class="w"> </span><span class="p">}</span><span class="w">
</span><span class="err">   </span><span class="w"> </span><span class="p">]</span><span class="w">
</span><span class="err"> </span><span class="w"> </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>I will not explain here how and when to use <code class="language-plaintext highlighter-rouge">authenticatedState</code> and <code class="language-plaintext highlighter-rouge">primary</code>.</p>

<p>If you are using a cookie, then there are two scenarios:</p>

<ul>
  <li>If you are using WebSDK, then no additional action is required. If everything is configured correctly, the browser will append the cookie to the call to the Edge Network, and the datastream will read it from there.</li>
  <li>If you are in a server-to-server scenario, or on a device for which there is no SDK, you must manually attach the cookie to the HTTP call. However, in these cases, I strongly recommend using the <code class="language-plaintext highlighter-rouge">identityMap</code>.</li>
</ul>

<h2 id="use-cases">Use Cases</h2>

<p>I can think of two main use cases for using the FPID. Let me know in the comments if you can think of other scenarios or are already using the FPID in a different context.</p>

<h3 id="beating-itp">Beating ITP</h3>

<p>Safari’s Intelligent Tracking Prevention (ITP) aggressively limits the lifespan of client-side cookies that it believes are used for tracking, especially third-party cookies. However, by using the FPID:</p>

<ul>
  <li>You store the FPID in a first-party context, which is less likely to be purged.</li>
  <li>You maintain a custom device identifier, which is more likely to go unnoticed.</li>
</ul>

<p>To clarify, this does not <em>beat</em> ITP in the sense of bypassing it, but it maximizes the longevity of your identifiers within the browser’s rules.</p>

<h3 id="server-side-implementation">Server-Side Implementation</h3>

<p>In server-side or hybrid implementations, maintaining identity continuity can be challenging. With the FPID:</p>

<ul>
  <li>You control the identifier, rather than relying on the ECID, which is generated outside of your systems.</li>
  <li>You do not need to manage the ECID: receiving it, storing it, retrieving it, and attaching it to all subsequent calls. Since you own the FPID, you likely have a method for maintaining it.</li>
</ul>

<h2 id="more-information">More Information</h2>

<p>There are many more details beyond this brief introduction. If you want more information, there are several resources you can consult:</p>

<ul>
  <li>Experience League documentation:
    <ul>
      <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/collection/visitor-identification/visitor-identification-fpid">Visitor identification via FPID</a></li>
      <li><a href="https://experienceleague.adobe.com/en/docs/experience-platform/web-sdk/identity/first-party-device-ids">Use first-party device IDs in Web SDK</a></li>
      <li><a href="https://experienceleague-stage.adobe.com/en/docs/experience-manager-learn/sites/integrations/experience-platform/fpid">Generate Experience Platform FPIDs with AEM Sites</a></li>
    </ul>
  </li>
  <li>A blog post from my coworkers Prachi and Luc: <a href="https://experienceleaguecommunities.adobe.com/t5/adobe-analytics-blogs/improved-visitor-identification-using-adobe-s-first-party-device/ba-p/671144">Improved Visitor Identification using Adobe’s First-Party Device ID</a></li>
</ul>

<p> </p>

<p><small>Photo by <a href="https://unsplash.com/@georgeprentzas?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">George Prentzas</a> on <a href="https://unsplash.com/photos/round-black-and-white-light-SRFG7iwktDk?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[Now that I have addressed the Experience Cloud ID (ECID) from a 2025 perspective, I can proceed to write a post on the First Party ID (FPID). It has remained on my list of future posts for some time, but until recently, I had not encountered it in a client scenario. Now that I have sufficient context, I can provide an explanation of this feature, how to use it, and the typical use cases for it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-15-fpid/fingerprint.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-15-fpid/fingerprint.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Revisiting the Experience Cloud ID Service</title><link href="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html" rel="alternate" type="text/html" title="Revisiting the Experience Cloud ID Service" /><published>2025-06-01T00:00:00-04:00</published><updated>2025-06-01T00:00:00-04:00</updated><id>https://www.pedromonjo.com/2025/06/revisiting-ecid-service</id><content type="html" xml:base="https://www.pedromonjo.com/2025/06/revisiting-ecid-service.html"><![CDATA[<p>I was in the process of writing a blog post on the FPID and I realized that my <a href="https://www.pedromonjo.com/2017/05/marketing-cloud-id-service.html">post on the Marketing Cloud ID</a> was very outdated. Even that name has not been used in many years. So I decided that I needed an update to this feature. If you are familiar with it, I do not think I will explain anything new to you. However, if you are just starting with the Adobe ecosystem, this post is for you.</p>

<!--more-->

<h2 id="visitor-vs-person">Visitor vs Person</h2>

<p>Before diving into the details of the <strong>Experience Cloud ID</strong> (ECID) service, it is important to explain a key concept, one of <em>the rules of the Internet</em>.</p>

<p>Marketers always want to know who is interacting with the company’s property. However, this is impossible. As long as the law permits, technology will allow you to remain anonymous. Only when you provide your credentials does a company know who you are.</p>

<p>With this premise in mind, I can attempt a basic definition for visitor and person:</p>

<ul>
  <li>A visitor is an individual who is interacting with a website or mobile app without providing any information that can uniquely identify him or her. As we will see later, this definition is just a starting point.</li>
  <li>A person is an individual, often a customer of the company, who has identified him/herself while interacting with a website or mobile app.</li>
</ul>

<p>For the rest of this post, I will only refer to visitors.</p>

<h2 id="the-era-of-independence">The Era of Independence</h2>

<p>Online tracking tools need a way to identify visitors and link all events from the same individual. Before the Adobe Experience Cloud (AEC), each tool had its own identifier, which were completely disconnected:</p>

<ul>
  <li>Adobe Analytics (AA) had the <code class="language-plaintext highlighter-rouge">s_vi</code> cookie, although it supported other identifiers.</li>
  <li>Adobe Target (AT) had the <code class="language-plaintext highlighter-rouge">mbox</code> cookie.</li>
  <li>Adobe Audience Manager (AAM) had the <code class="language-plaintext highlighter-rouge">demdex</code> cookie.</li>
</ul>

<p>These identifiers are still used today, although they are only relevant for isolated implementations.</p>

<h2 id="an-id-to-rule-them-all">An ID to Rule Them All</h2>

<p>As Adobe tools became more integrated, a common identifier was needed. This led to the creation of the ECID service.</p>

<p>The ECID is a <strong>random</strong>, <strong>unique value</strong> that identifies a visitor, and is shared across all Adobe tools:</p>

<ul>
  <li><a href="https://www.pedromonjo.com/category/analytics-tips/">Adobe Analytics</a></li>
  <li>Adobe Target</li>
  <li><a href="https://www.pedromonjo.com/category/aam/">Adobe Audience Manager</a></li>
  <li><a href="https://www.pedromonjo.com/category/platform/">Adobe Experience Platform</a></li>
  <li>Customer Journey Analytics</li>
</ul>

<p>Other tools like Adobe Campaign also support the ECID. This makes it possible for all tools to share visitor data among them, as there is a common key.</p>

<h2 id="the-lifecycle-of-the-ecid">The Lifecycle of the ECID</h2>

<p>Managing ECIDs involves four steps: generation, storage, access, and deletion.</p>

<h3 id="generation">Generation</h3>

<p>A new ECID is generated when a visitor interacts with a web or mobile app and no ECID is available. This occurs for first-time visitors or if the ECID has been <a href="#deletion">deleted</a>.</p>

<p>Let’s explore now the two ways to generate the ECID.</p>

<p>The first option is usually for the case when you are not using AEP, where you can use the legacy <a href="https://experienceleague.adobe.com/en/docs/id-service/using/id-service-api/library">ID Service API</a>. This approach relies on AAM to generate the ECID via a call to <code class="language-plaintext highlighter-rouge">dpm.demdex.net</code>. Here is an example response:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"d_mid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"90118992779512484750418347061211614812"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"id_sync_ttl"</span><span class="p">:</span><span class="w"> </span><span class="mi">604800</span><span class="p">,</span><span class="w">
    </span><span class="nl">"d_blob"</span><span class="p">:</span><span class="w"> </span><span class="s2">"6G1ynYcLPuiQxYZrsz_pkqfLG9yMXBpb2zX5dvJdYQJzPXImdj0y"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"dcs_region"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
    </span><span class="nl">"d_ottl"</span><span class="p">:</span><span class="w"> </span><span class="mi">7200</span><span class="p">,</span><span class="w">
    </span><span class="nl">"ibs"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"411"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"ttl"</span><span class="p">:</span><span class="w"> </span><span class="mi">10080</span><span class="p">,</span><span class="w">
            </span><span class="nl">"tag"</span><span class="p">:</span><span class="w"> </span><span class="s2">"img"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"fireURLSync"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
            </span><span class="nl">"syncOnPage"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
            </span><span class="nl">"url"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                </span><span class="s2">"//cm.everesttech.net/cm/dd?d_uuid=90491266071992917220381119861073162061"</span><span class="w">
            </span><span class="p">]</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="nl">"subdomain"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ags059"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"tid"</span><span class="p">:</span><span class="w"> </span><span class="s2">"9C89AwmqTBo="</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Notice the <code class="language-plaintext highlighter-rouge">d_mid</code> parameter: this is the ECID. For the curious minds, MID comes from the days when it was called Marketing Cloud ID.</p>

<p>the second option is recommended if you have AEP or want the features offered by AEP’s Edge Network. In this scenario, you should use the <a href="https://experienceleague.adobe.com/en/docs/experience-platform/web-sdk/home">Web SDK</a> or the <a href="https://developer.adobe.com/client-sdks/home/">Mobile SDK</a>. These libraries call AEP’s Edge Network, which generates and returns a new ECID if the call does not include one. Note that the ECID is generated during the invocation, not before. Since Web and Mobile SDKs are very <em>chatty</em>, for the example I will only show the relevant part of the response (ignore the CORE namespace):</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"requestId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"a688e4ae-b764-42f5-953c-ccfc9cdaf9f8-8ee2eabe8d3c4c80"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"handle"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"payload"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                </span><span class="p">{</span><span class="w">
                    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"85876247190619965311149449127327118836"</span><span class="p">,</span><span class="w">
                    </span><span class="nl">"namespace"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                        </span><span class="nl">"code"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ECID"</span><span class="w">
                    </span><span class="p">}</span><span class="w">
                </span><span class="p">},</span><span class="w">
                </span><span class="p">{</span><span class="w">
                    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"90491266071992917220381119861073162061"</span><span class="p">,</span><span class="w">
                    </span><span class="nl">"namespace"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                        </span><span class="nl">"code"</span><span class="p">:</span><span class="w"> </span><span class="s2">"CORE"</span><span class="w">
                    </span><span class="p">}</span><span class="w">
                </span><span class="p">}</span><span class="w">
            </span><span class="p">],</span><span class="w">
            </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"identity:result"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h3 id="storage">Storage</h3>

<p>Once an ECID is generated, it must be stored for subsequent calls. The Mobile SDK stores it in the application’s storage space. I do not have much more information about this.</p>

<p>The Web SDK and ID Service API store the ECID in a cookie. In the case of the ID Service, the cookie name follows the format <code class="language-plaintext highlighter-rouge">AMCV_&lt;ORG ID&gt;%40AdobeOrg</code>, commonly referred to as the AMCV cookie. Its value includes the ECID, along with other parameters. Here is an example of how this cookie value looks like:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>359503849%7CMCMID%7C90118992779512484750418347061211614812%7CMCAAMLH-1749396731%7C7%7CMCAAMB-1749396731%7C6G1ynYcLPuiQxYZrsz_pkqfLG9yMXBpb2zX5dvJdYQJzPXImdj0y%7CMCOPTOUT-1748799132s%7CNONE%7CMCAID%7CNONE%7CvVersion%7C5.0.1
</code></pre></div></div>

<p>If you URL-decode this string, split it using the pipe (<code class="language-plaintext highlighter-rouge">|</code>) as a separator, and find the <code class="language-plaintext highlighter-rouge">MCMID</code> string, the next string is the ECID: <code class="language-plaintext highlighter-rouge">90118992779512484750418347061211614812</code>.</p>

<p>The Web SDK will use the AMCV cookie if you tell it to do so through the <code class="language-plaintext highlighter-rouge">idMigrationEnabled</code> configuration parameter. However, natively, Web SDK stores the ECID in the <code class="language-plaintext highlighter-rouge">kndctr_&lt;ORG ID&gt;_AdobeOrg_identity</code> cookie, although I do not know its encoding:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CiY0MjM5NzczOTU1OTQ4NjkxMjU0MDY0ODk5MjcyNjYyNTc1Njk1N1IQCMCLjfT2MhgBKgNWQTYwA%5FABwIuN9PYy
</code></pre></div></div>

<p>Before continuing, let’s clarify a few things about storage:</p>

<ul>
  <li>Browsers do not share cookies. For example, Google Chrome and Microsoft Edge keep their own cookie storage (I like to call them <em>cookie jars</em>). This means that if you use the same computer to browse the same website through different browsers, you will get one ECID per browser.</li>
  <li>Each mobile application in your device has its own storage, which is not shared with other applications. Consequently, two applications with Mobile SDK installed will get two different ECIDs.</li>
  <li>Many browsers allow the creation of profiles and private browsing or incognito mode, which effectively creates new cookie jars within the same browser. A new ECID will be generated for each cookie jar.</li>
</ul>

<h3 id="access">Access</h3>

<p>You should not need to manually retrieve the ECID from the cookie. The ID Service API library, Web SDK, or Mobile SDK provide methods to get it. However, unless you have a specific use case, you do not really need to retrieve it. All modern Adobe client-side libraries will automatically read the ECID from the cookie/storage and include it in all calls.</p>

<h3 id="deletion">Deletion</h3>

<p>Generally, you do not want to delete an ECID. It should be a durable identifier. However, it will be deleted under the following circumstances:</p>

<ul>
  <li>The user actively deletes cookies</li>
  <li>The user actively deletes the mobile app storage or the app itself</li>
  <li>The AMCV cookie expires</li>
  <li>The browser deletes tracking cookies, like Safari with its ITP rules</li>
  <li>The OS automatically deletes the mobile app storage after a long period of inactivity</li>
  <li>The user browses in private mode or incognito window</li>
</ul>

<h2 id="visitor-metric">Visitor Metric</h2>

<p>So far, I have explained the basics of the ECID service. There are nuances and edge cases, but those are for another day.</p>

<p>However, there is one problem you need to know. If you have been paying attention, you may have noticed that the definition of visitor is inaccurate. There are many cases where a single person behind a computer generates multiple ECIDs. As a result, counting visitors by ECIDs will always yield an inflated number.</p>

<p>Adobe is replacing the concept of unique visitors with <a href="https://experienceleague.adobe.com/en/docs/analytics/components/metrics/unique-devices">unique devices</a>. While this is still not a perfect name, as you may have multiple apps or browsers on the same device, it is a step towards moving away from the visitor metric.</p>

<h2 id="server-side">Server-Side</h2>

<p>Having written many posts on <a href="https://www.pedromonjo.com/category/server-side/">server-side</a> digital marketing, I want to conclude with a comment on this case. If you plan to use the <a href="https://www.pedromonjo.com/2022/04/edge-network-server-api.html">Edge Network Server API</a>, you will need to replicate most of what the Web SDK does regarding the ECID lifecycle. You must store the ECID after it is generated for the first time and send it again with subsequent calls. If you are making calls on behalf of multiple individuals, you will need to manage one ECID per individual.</p>

<p> </p>

<p><small><a href="https://www.pexels.com/photo/people-wearing-white-clothes-lying-on-the-floor-10211660/">Photo by cottonbro studio</a></small></p>]]></content><author><name>Pedro Monjo</name></author><category term="Platform" /><summary type="html"><![CDATA[I was in the process of writing a blog post on the FPID and I realized that my post on the Marketing Cloud ID was very outdated. Even that name has not been used in many years. So I decided that I needed an update to this feature. If you are familiar with it, I do not think I will explain anything new to you. However, if you are just starting with the Adobe ecosystem, this post is for you.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-01-revisiting-ecid-service/identities.jpg" /><media:content medium="image" url="https://www.pedromonjo.com/assets/images/originals/2025/2025-06-01-revisiting-ecid-service/identities.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>