Adobe Articles / Blogs / Perficient https://blogs.perficient.com/category/partners/adobe/ Expert Digital Insights Wed, 11 Feb 2026 16:23:43 +0000 en-US hourly 1 https://blogs.perficient.com/files/favicon-194x194-1-150x150.png Adobe Articles / Blogs / Perficient https://blogs.perficient.com/category/partners/adobe/ 32 32 30508587 EDS Adventures – Integrating External Data and Building Custom Feature Blocks https://blogs.perficient.com/2026/02/11/eds-adventures-integrating-external-data-and-building-custom-feature-blocks/ https://blogs.perficient.com/2026/02/11/eds-adventures-integrating-external-data-and-building-custom-feature-blocks/#respond Wed, 11 Feb 2026 16:23:43 +0000 https://blogs.perficient.com/?p=390252

In Edge Delivery Services, you have good options for putting together engaging content. Adobe’s block collection has a considerable number of content shapes, providing a good base or starting point for your project. This is similar in purpose to the Sling + HTL-driven components provided by WCM Core Components. While similar in purpose, they are very different in design. EDS provides a more simplified process for creating authorable content, backed by an architecture that always executes optimally. EDS blocks can enable similar features to what a Sling-driven component might deliver. In this post, I’ll walk through how to build a custom block with unique capabilities and integrate third-party APIs, while keeping everything at the edge!

What We Will Build

Defining the Block

We’ll develop a block that represents a process for retrieving data and using it to directly change rendered output. We’re using a simple use case for demonstration, but this technique could be used for API data retrieval from any database, data warehouse, or repository.

The block we’re developing is for a fictional paint company’s color previewer. It allows users to preview different paint colors in a fictional coffee shop. This type of content would be useful for customers wanting to visualize how the paint colors might look in their real-life home or business.

The paint colors will be provided from an API, internally managed by our fictional paint company. The block consumes this data and uses it to render swatches. Upon click or tap of a swatch color, the walls in the image will update to render the selected color.

 

Most of this can be contained in a single GitHub repository, based on Adobe’s EDS boilerplate repo. The API will be provided as a Cloudflare worker (as I said, keeping everything at the edge).

 

It’s to be assumed that you already have an established AEM EDS project, with a provisioned cloud service tenant, programs, environments, and deploy pipelines. Please find details on setting up an EDS site and the Universal Editor here: https://www.aem.live/developer/ue-tutorial.

Architecture Quick Summary

We’re leveraging the pattern of authoring EDS pages in the AEM as a cloud service author tier, and publishing to EDS preview and publish tiers. All third-party API requests happen client-side.

API EDS Author Tier Architecture

Block Definition and Model

For an EDS project, particularly one based on Adobe’s EDS boilerplate, 3 key files are needed for defining a block and where it may be authored.

The component-definition.json file defines a block’s display name, id, resource type, and the name of its data model. For our block, we need to add the following object to the array in this file:

{
  "title": "Paint Room Preview",
  "id": "paint-room-preview",
  "plugins": {
    "xwalk": {
      "page": {
        "resourceType": "core/franklin/components/block/v1/block",
        "template": {
          "name": "Paint Room Preview",
          "model": "paint-room-preview"
        }
      }
    }
  }
}

The component-models.json file describes the block’s data model and authorable field types. For our block, we need to add the following to the array in this file:

{
  "id": "paint-room-preview",
  "fields": [
    {
      "component": "reference",
      "valueType": "url",
      "name": "baseImage",
      "label": "Paint Preview Base Image",
      "description": "The base image to recolor.",
      "multi": false
    },
    {
      "component": "reference",
      "valueType": "url",
      "name": "maskImage",
      "label": "Paint Preview Mask Image",
      "description": "Black/white mask defining which areas to recolor.",
      "multi": false
    },
    {
      "component": "reference",
      "valueType": "url",
      "name": "shadingImage",
      "label": "Paint Preview Shading Image",
      "description": "Shading image defining where to apply lights and shadows.",
      "multi": false
    }
  ]
 }

This configuration defines 3 image selection fields, allowing authors to pick one image as the base image, a layer mask version of that base image, and a shading version of that base image. This base image is changed by the color selection, with the colors applied in the specific areas defined by the mask, namely, the room’s walls. The shading image ensures the existing shadows and highlights are retained, so nothing is flattened or washed out. These 3 images are used by our block script to build a composite image based on the color selection. To the user, the paint color changes as if the walls were always the selected color.

Relating this to Sling, the component-filters.json is akin to a responsivegrid/layout-container allowed components policy. Our block id is “paint-room-preview”. In the file, we can add this into any block’s array list of components to allow our block to be added to that section of a page. This is sensible for blocks designed to contain other blocks, such as sections, lists, embeds, carousels, etc. We’ll add “paint-room-preview” to the section block’s filter list:

{
  "id": "section",
  "components": [
    "text",
    "image",
    "button",
    "title",
    "hero",
    "cards",
    "columns",
    "fragment",
    "paint-room-preview"
  ]
},

Block Functionality

Ok, now for the block itself, we need to create a JavaScript and CSS file. We’ll also create a helper method in the scripts/aem.js file to abstract API calls and allow for better re-use. In the project’s blocks folder, create a new folder named paint-room-preview. Then, in this folder, create a new file called paint-room-preview.js with the following contents:

import { fetchFromApi } from '../../scripts/aem.js';

export default async function decorate(block) {
  const COLORS_URL = 'https://devopsdrops.tech/colorapi/colors.json';
  const PAGE_SIZE = 30;
  const VISIBLE = 5;

  function ensureMarkup() {
    let root = block.querySelector('.paint-room-preview');
    if (!root) {
      root = document.createElement('div');
      root.className = 'paint-room-preview';
      block.appendChild(root);
    }

    let canvas = root.querySelector('#room-canvas');
    if (!canvas) {
      canvas = document.createElement('canvas');
      canvas.id = 'room-canvas';
      root.appendChild(canvas);
    }

    let nav = root.querySelector('.bm-nav');
    if (!nav) {
      nav = document.createElement('div');
      nav.className = 'bm-nav';
      nav.innerHTML = `
        <button id="bm-prev">Prev</button>
        <div id="bm-colors"></div>
        <button id="bm-next">Next</button>
      `;
      root.appendChild(nav);
    }
    return root;
  }

  const root = ensureMarkup();

  function findImageFromMarkup(prop) {
    const img = block.querySelector(`img[data-aue-prop="${prop}"]`);
    return img ? img.getAttribute('src') : '';
  }

  const baseImage = (block.dataset.baseImage?.trim())
    || (root.dataset.baseImage?.trim())
    || findImageFromMarkup('baseImage') || '';

  const maskImage = (block.dataset.maskImage?.trim())
    || (root.dataset.maskImage?.trim())
    || findImageFromMarkup('maskImage') || '';

  const shadingImage = (block.dataset.shadingImage?.trim())
    || (root.dataset.shadingImage?.trim())
    || findImageFromMarkup('shadingImage') || '';

  if (!baseImage || !maskImage || !shadingImage) {
    root.innerHTML = `
      <div style="border:1px dashed #ddd;padding:12px;border-radius:6px;color:#666;">
        Paint Room Preview requires Base Image, Mask Image, and Shading Image.
      </div>`;
    return;
  }

  const canvas = root.querySelector('#room-canvas');
  const ctx = canvas.getContext('2d');
  if (!ctx) return;

  const prevBtn = root.querySelector('#bm-prev');
  const nextBtn = root.querySelector('#bm-next');
  const colorsContainer = root.querySelector('#bm-colors');

  canvas.style.width = '100%';
  colorsContainer.style.display = 'flex';
  colorsContainer.style.gap = '10px';
  colorsContainer.style.flexWrap = 'wrap';
  colorsContainer.style.justifyContent = 'center';

  function loadImage(src) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.crossOrigin = 'anonymous';
      img.onload = () => resolve(img);
      img.onerror = () => reject(new Error(`Failed loading image ${src}`));
      img.src = src;
    });
  }

  let imgBase;
  let imgMask;
  let imgShade;
  try {
    [imgBase, imgMask, imgShade] = await Promise.all([
      loadImage(baseImage),
      loadImage(maskImage),
      loadImage(shadingImage),
    ]);

    block.querySelectorAll('img[data-aue-prop]').forEach((img) => {
      const wrap = img.closest('picture,div') || img;
      wrap.style.display = 'none';
    });
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error(e);
    root.innerHTML = '<div style="color:#b00">Error loading images.</div>';
    return;
  }

  canvas.width = imgBase.width;
  canvas.height = imgBase.height;
  ctx.drawImage(imgBase, 0, 0);

  function getMaskData() {
    const temp = document.createElement('canvas');
    temp.width = canvas.width;
    temp.height = canvas.height;
    const tctx = temp.getContext('2d');
    tctx.drawImage(imgMask, 0, 0, temp.width, temp.height);
    return tctx.getImageData(0, 0, temp.width, temp.height).data;
  }
  const maskData = getMaskData();

  function getShadeData() {
    const temp = document.createElement('canvas');
    temp.width = canvas.width;
    temp.height = canvas.height;
    const tctx = temp.getContext('2d');
    tctx.drawImage(imgShade, 0, 0, temp.width, temp.height);
    return tctx.getImageData(0, 0, temp.width, temp.height).data;
  }
  const shadeData = getShadeData();

  function hexToRgb(hex) {
    const h = hex.replace('#', '');
    return {
      r: parseInt(h.substring(0, 2), 16),
      g: parseInt(h.substring(2, 4), 16),
      b: parseInt(h.substring(4, 6), 16),
    };
  }
  function blend(base, target, amt) {
    return Math.round(base * (1 - amt) + target * amt);
  }

  function applyPaintHex(hex) {
    const tgt = hexToRgb(hex.startsWith('#') ? hex : `#${hex}`);

    // Step 1: reset base
    ctx.drawImage(imgBase, 0, 0);
    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const { data } = imgData;

    // Step 2: apply flat paint using alpha mask
    for (let i = 0; i < data.length; i += 4) {
      const maskVal = maskData[i] / 255;
      if (maskVal > 0.03) {
        data[i] = blend(data[i], tgt.r, maskVal);
        data[i + 1] = blend(data[i + 1], tgt.g, maskVal);
        data[i + 2] = blend(data[i + 2], tgt.b, maskVal);
      }
    }

    // Step 3: multiply wall shading (lighting pass)
    for (let i = 0; i < data.length; i += 4) {
      const maskVal = maskData[i] / 255;
      if (maskVal > 0.03) {
        const shade = shadeData[i] / 255; // grayscale
        data[i] = Math.round(data[i] * shade);
        data[i + 1] = Math.round(data[i + 1] * shade);
        data[i + 2] = Math.round(data[i + 2] * shade);
      }
    }

    ctx.putImageData(imgData, 0, 0);
  }

  let apiPage = 1;
  let pageIndex = 0;
  let colors = [];

  async function loadApiPage(p = 1) {
    try {
      const json = await fetchFromApi(COLORS_URL, {
        page: p,
        pageSize: PAGE_SIZE,
      });
      colors = Array.isArray(json.data) ? json.data : [];
      apiPage = json.page || p;
      pageIndex = 0;
    } catch (e) {
      // eslint-disable-next-line no-console
      console.error(e);
      colors = [];
    }
  }

  function renderSwatches() {
    colorsContainer.innerHTML = '';
    const start = pageIndex * VISIBLE;
    const slice = colors.slice(start, start + VISIBLE);

    if (slice.length === 0) {
      colorsContainer.innerHTML = '<div>No colors</div>';
      return;
    }

    slice.forEach((c, idx) => {
      const hex = (c.hex || '').replace('#', '');
      const name = c.name || `Color ${idx + 1}`;
      const sw = document.createElement('button');
      sw.style.width = '48px';
      sw.style.height = '48px';
      sw.style.borderRadius = '6px';
      sw.style.border = '1px solid #ddd';
      sw.style.background = `#${hex}`;
      sw.addEventListener('click', () => applyPaintHex(hex));

      const wrap = document.createElement('div');
      wrap.style.display = 'flex';
      wrap.style.flexDirection = 'column';
      wrap.style.alignItems = 'center';
      wrap.style.fontSize = '12px';
      wrap.style.color = '#333';
      wrap.style.minWidth = '64px';
      wrap.style.gap = '4px';

      const lbl = document.createElement('div');
      lbl.textContent = name;
      lbl.style.maxWidth = '72px';
      lbl.style.textOverflow = 'ellipsis';
      lbl.style.overflow = 'hidden';

      wrap.appendChild(sw);
      wrap.appendChild(lbl);
      colorsContainer.appendChild(wrap);
    });
  }

  if (pageIndex < 1) {
    prevBtn.disabled = true;
  }

  prevBtn.addEventListener('click', async () => {
    const maxIndex = Math.floor((colors.length - 1) / VISIBLE);

    if (pageIndex > 0) {
      pageIndex -= 1;
      renderSwatches();
      if (pageIndex < 1) {
        prevBtn.disabled = true;
      }
      if (pageIndex < maxIndex) {
        nextBtn.disabled = false;
      }
      return;
    }
    if (apiPage > 1) {
      await loadApiPage(apiPage - 1);
      pageIndex = Math.floor((colors.length - 1) / VISIBLE);
      renderSwatches();
    }
  });

  nextBtn.addEventListener('click', async () => {
    const maxIndex = Math.floor((colors.length - 1) / VISIBLE);

    if (pageIndex < maxIndex) {
      pageIndex += 1;
      if (pageIndex >= 1) {
        prevBtn.disabled = false;
      }
      renderSwatches();
      if (pageIndex === (maxIndex - 1)) {
        nextBtn.disabled = true;
      }
      return;
    }
    await loadApiPage(apiPage + 1);
    if (colors.length > 0) renderSwatches();
  });

  await loadApiPage(apiPage);
  renderSwatches();
  if (colors.length > 0 && colors[0].hex) applyPaintHex(colors[0].hex);
}

This script provides a decorate function, which is used to initialize and define the HTML DOM structure of the block. Within decorate we have methods and fields unique to this block’s custom functionality.

The ensureMarkup() method guarantees that required HTML is created, namely a root container div, a canvas element for our image previews, and a navigation div for paging through color swatches and selecting colors.

Several constants are also defined to ensure the required images are available. These attempt to pull the image URI values from the block’s data attributes, ensureMarkup’s containing div, or from img elements containing a specific attribute with a value matching the image type. If any one of the base, mask, or shading images is missing, the block renders text indicating that all are required. This is like Sling/HTL default content that may be rendered if a component instance is not yet authored.

Then details of the canvas are defined based on the Canvas API, to set up our photo manipulation in a 2D context.

The images are rendered from the previously defined URIs via a loadImage() method, which asynchronously loads an image and returns a Promise that resolves with the loaded image element. The base, mask, and shading images are simultaneously loaded. The author-selected images are hidden, as the canvas will render them as a combined composite image. The canvas width and height are defined, and the base image is drawn to it.

The getMaskData() and getShadeData() methods extract the pixel data from the mask and shade images using the Canvas API context’s getImageData() method. This returns an array of RGBA formatted pixels for each of these images. These are drawn in off-screen canvases, and the pixel arrays are computed and cached once, then reused for every color change.

The hexToRgb() method converts hex color codes to RGB color values. The blend() method performs a smooth blending between a base and target value. These are each used in the applyPaintHex() method, which is where the key functionality takes place for painting! The base image is redrawn to obtain its pixel data (again as an array of RGBA pixels), and the mask data is used to determine which parts of the base image are “paintable”.

The blend() method is called to mix the original base image pixel data with the selected paint color, within the paintable areas derived from the mask data. Pixel data from the shading array is then applied to ensure the shadows and highlights of the base image are retained, so no depth is lost.

The loadApiPage() method is used to call for available colors from a third-party API service and uses a utility method from scripts/aem.js to make the request. The renderSwatches() method renders the colors as sets of swatches that the user can page through to select a color for painting. Buttons for this pagination are set up with click event handlers.

Third-party API requests

The previous section went over a substantial amount of the details for rendering the block.

While we could have contained everything there, it’s helpful in any modern project to modularize your code for reuse when possible. With that mindset, a utility method has been added to the aem.js file in the scripts directory:

async function fetchFromApi(url, { page, pageSize, params = {} } = {}) {
  const query = new URLSearchParams();

  if (page !== undefined) query.set('page', page);
  if (pageSize !== undefined) query.set('pageSize', pageSize);

  Object.entries(params).forEach(([k, v]) => {
    if (v !== undefined && v !== null) {
      query.set(k, v);
    }
  });

  const fullUrl = query.toString()
    ? `${url}?${query.toString()}`
    : url;

  const res = await fetch(fullUrl, {
    headers: { Accept: 'application/json' },
  });

  if (!res.ok) {
    throw new Error(`fetchAPI failed: ${res.status} ${res.statusText}`);
  }

  return res.json();
}

This fetchFromApi() method was also added to the aem.js export object so that we can call it in our blocks (like we did in the import statement of paint-room-preview.js).

This method makes paginated API requests, though the pagination is optional when calling it. This takes a provided URL, page, page size (the number of items per page), and any additional parameters. For our block, we use this to call our third-party API on page 1. The API offers 30 colors in total. We make a single request for all of them and then page between sets of 5 when the user clicks the next or previous buttons.

You’ll notice in the decorate() method of our block script, we defined the API URL via:

const COLORS_URL = 'https://yourdomain.com/colorapi/colors.json';
  

This should be updated to match the domain and path of your API, based on your implementation. As for that API, we’ll cover it in the next section.

Third Party Colors API

For my EDS site, I’m using the bring your own CDN approach via a Cloudflare worker. Adobe documentation provides a worker script that you can use for requests to your configured EDS domain. To enable our colors API, we just need to make a few minor updates to the script.

In the handleRequests() method, we first define constants for pages and colors returned in API requests, then we define a JSON object containing the page, page size, total number of pages, and most importantly, the array of colors!

const page = parseInt(url.searchParams.get("page") || "1", 10);
const pageSize = parseInt(url.searchParams.get("pageSize") || "30", 10);

const colors = [
  { name: "White", hex: "FFFFFF" },
  { name: "Black", hex: "000000" },
  { name: "Red", hex: "FF0000" },
  { name: "Green", hex: "00FF00" },
  { name: "Blue", hex: "0000FF" },
  { name: "Cyan", hex: "00FFFF" },
  { name: "Magenta", hex: "FF00FF" },
  { name: "Yellow", hex: "FFFF00" },
  { name: "Gray", hex: "808080" },
  { name: "Orange", hex: "FFA500" },
  { name: "Purple", hex: "800080" },
  { name: "Brown", hex: "A52A2A" },
  { name: "Pink", hex: "FFC0CB" },
  { name: "Lime", hex: "32CD32" },
  { name: "Teal", hex: "008080" },
  { name: "Navy", hex: "000080" },
  { name: "Olive", hex: "808000" },
  { name: "Maroon", hex: "800000" },
  { name: "Silver", hex: "C0C0C0" },
  { name: "Gold", hex: "FFD700" },
  { name: "Coral", hex: "FF7F50" },
  { name: "Indigo", hex: "4B0082" },
  { name: "Turquoise", hex: "40E0D0" },
  { name: "Lavender", hex: "E6E6FA" },
  { name: "Beige", hex: "F5F5DC" },
  { name: "Mint", hex: "98FF98" },
  { name: "Peach", hex: "FFDAB9" },
  { name: "Sky Blue", hex: "87CEEB" },
  { name: "Chocolate", hex: "D2691E" },
  { name: "Crimson", hex: "DC143C" }
];

const total = colors.length;
const start = (page - 1) * pageSize;
const end = start + pageSize;
const pageColors = colors.slice(start, end);

const json = JSON.stringify({
  page,
  pageSize,
  total,
  totalPages: Math.ceil(total / pageSize),
  data: pageColors,
});

Lastly, above the condition checking if the path starts with /drafts/, add the following:

if (url.pathname.startsWith('/colorapi/')) {
  return new Response(json, {
    headers: {
      "Content-Type": "application/json",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type"
    },
  });
}

This sets up our API as path-based, supporting requests to /colorsapi/colors.json. Once we deploy our worker changes, the JSON response to API requests will resemble the following:

JSON Response to API Requests

I will mention that while this works, our API does leave some things to be desired. In a true, production-ready implementation, the worker should only act as a proxy to a separate data service (with its own dedicated redundancy and fault tolerance). The colors data could be enriched with details such as product codes, applications where each color is supported (works on drywall vs wood), and split into different sets of color palettes based on the paint quality (economy, super, deluxe, etc.). There might even be a review process where certain colors are filtered out based on inventory or other factors. The primary goal of this post is to demonstrate block building and, secondly, to keep the entire implementation at the edge, not to provide a best practice API implementation.

Block Design

With the functional aspects of our block complete, we need to add some styles to make our image previewer, color options and paging work cohesively on varying client devices. So, in the /blocks/paint-room-preview folder, create a file called paint-room-preview.css and add the following contents:

.paint-room-preview {
  max-width: 800px;
  margin: auto;
  text-align: center;
}

#room-canvas {
  width: 100%;
  border-radius: 8px;
  margin-bottom: 20px;
}

.bm-controls {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.bm-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-bottom: 20px;
}

#bm-colors {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: nowrap;
  margin: 0 10%;
}

.bm-color {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.bm-swatch {
  width: 60px;
  height: 60px;
  border-radius: 6px;
  border: 1px solid #ccc;
  cursor: pointer;
  margin-bottom: 8px;
  transition: transform .2s;
}

.bm-swatch:hover {
  transform: scale(1.1);
}

@media (width <= 900px) {    
  .bm-nav {
    flex-wrap: wrap;
  }

  #bm-colors {
    order: 3;
    width: 100%;
    justify-content: center;
    margin: 12px 0 0;
    flex-wrap: wrap;
  }

  #bm-prev {
    order: 1;
  }

  #bm-next {
    order: 2;
  }
}

With that, we should merge or commit our changes. Then we can author our block on a page, via the universal editor:

Editing in the Universal Editor

If you want to test drive this using the coffee shop example above, please find the base image, mask, and shading image at the links below. Upload these images to AEM Assets to select them in your block’s authorable fields.

https://blogs.perficient.com/files/coffee-shop-shading.png

https://blogs.perficient.com/files/coffee-shop-mask.png

https://blogs.perficient.com/files/coffee-shop.png

With all 3 images authored, you can publish the page and see your changes in action.

Closing Thoughts

As you can see, EDS blocks can be as specific as you need them to be. All the block and utility code is contained in JavaScript and CSS. Authoring fields are easily enabled in component-models.json. The block is easily enabled for use in pages via component-filters.json. Using just browser APIs, event handlers, and DOM selectors, we built a compelling experience for our fictional paint company. Using just ES6+ modular code, we built a serverless API to provide simple color options. The best part of this is that it’s all delivered at the edge, for an optimally fast application. There are many possibilities for block customization. The speed and flexibility of Edge Delivery Services should be considered for your project.

]]>
https://blogs.perficient.com/2026/02/11/eds-adventures-integrating-external-data-and-building-custom-feature-blocks/feed/ 0 390252
Moving to CJA? Sunset Adobe Analytics Without Causing Chaos https://blogs.perficient.com/2026/01/27/moving-to-cja-sunset-adobe-analytics-without-causing-chaos/ https://blogs.perficient.com/2026/01/27/moving-to-cja-sunset-adobe-analytics-without-causing-chaos/#comments Tue, 27 Jan 2026 13:51:10 +0000 https://blogs.perficient.com/?p=389876

Adobe Experience Platform (AEP) and Customer Journey Analytics (CJA) continue to emerge as the preferred solutions for organizations seeking a unified, 360‑degree view of customer behavior.  For organizations requiring HIPAA compliance, AEP and CJA is a necessity.  Many organizations are now having discussions about whether they should retool or retire their legacy Adobe Analytics implementations.  The transition from Adobe Analytics to CJA is far more complex than simply disabling an old tool. Teams must carefully plan, perform detailed analysis, and develop a structured approach to ensure that reporting continuity, data integrity, and downstream dependencies remain intact.

Adobe Analytics remains a strong platform for organizations focused exclusively on web and mobile app measurement; however, enterprises that are prioritizing cross‑channel data activation, real‑time profiles, and detailed journey analysis should embrace AEP as the future. Of course, you won’t be maintaining two platforms after building out CJA so you must think about how to move on from Adobe Analytics.

Decommissioning Options and Key Considerations

You can approach decommissioning Adobe Analytics in several ways. Your options include: 1) disabling the extension; 2) adding an s.abort at the top of the AppMeasurement custom‑code block to prevent data from being sent to Adobe Analytics; 3) deleting all legacy rules; or 4) discarding Adobe Analytics entirely and creating a new Launch property for CJA. Although multiple paths exist, the best approach almost always involves preserving your data‑collection methods and keeping the historical Adobe Analytics data. You have likely collected that data for years, and you want it to remain meaningful after migration. Instead of wiping everything out, you can update Launch by removing rules you no longer need or by eliminating references to Adobe Analytics.

Recognizing the challenges involved in going through the data to make the right decisions during this process, I have developed a specialized tool – Analytics Decommissioner (AD) — designed to support organizations as they decommission Adobe Analytics and transition fully to AEP and CJA. The tool programmatically evaluates Adobe Platform Launch implementations using several Adobe API endpoints, enabling teams to quickly identify dependencies, references, and potential risks associated with disabling Adobe Analytics components.

Why Decommissioning Requires More Than a Simple Shutdown

One of the most significant obstacles in decommissioning Adobe Analytics is identifying where legacy tracking still exists and where removing Adobe Analytics could potentially break the website or cause errors. Over the years, many organizations accumulate layers of custom code, extensions, and tracking logic that reference Adobe Analytics variables—often in places that are not immediately obvious. These references may include s. object calls, hard‑coded AppMeasurement logic, or conditional rules created over the course of several years. Without a systematic way to surface dependencies, teams risk breaking critical data flows that feed CJA or AEP datasets.

Missing or outdated documentation makes the problem even harder. Many organizations fail to maintain complete or current solution design references (SDRs), especially for older implementations. As a result, teams rely on tribal knowledge, attempts to recall discussions from years ago, or a manual inspection of data collected to understand how the system collects data. This approach moves slowly, introduces errors, and cannot support large‑scale environments. When documentation lacks clarity, teams struggle to identify which rules, data elements, or custom scripts still matter and which they can safely remove. Now imagine repeating this process for every one of your Launch properties.

This is where Perficient and the AD tool provide significant value.
The AD tool programmatically scans Launch properties and uncovers dependencies that teams may have forgotten or never documented. A manual analysis might easily overlook these dependencies. AD also pinpoints where custom code still references Adobe Analytics variables, highlights rules that have been modified or disabled since deployment, and surfaces AppMeasurement usage that could inadvertently feed into CJA or AEP data ingestion. This level of visibility is essential for ensuring that the decommissioning process does not disrupt data collection or reporting.

How Analytics Decommissioner (AD) Works

The tool begins by scanning all Launch properties across your organization and asking the user to select a property. This is necessary because the decommissioning process must be done on each property individually.  This is the same way data is set for Adobe Analytics, one Launch property at a time.  Once a property is selected, the tool retrieves all production‑level data elements, rules, and rule components, including their revision histories.  The tool ignores rules and data element revisions that developers disabled or never published (placed in production).  The tool then performs a comprehensive search for AppMeasurement references and Adobe Analytics‑specific code patterns. These findings show teams exactly where legacy tracking persists and see what needs to be updated or modified and which items can be safely removed.  If no dependencies exist, AD can disable the rules and create a development library for testing.  When AD cannot confirm that a dependency exists, it reports the rule names and components where potential issues exist and depend on development experts to make the decision about the existence of a dependency.  The user always makes the final decisions.

This tool is especially valuable for large or complex implementations. In one recent engagement, a team used it to scan nearly 100 Launch properties. Some of those properties included more than 300 data elements and 125 active rules.  Attempting to review this level of complexity manually would have taken weeks and the risk would remain that critical dependencies are missed. Programmatic scanning ensures accuracy, completeness, and efficiency.  This allows teams to move forward with confidence.

A Key Component of a Recommended Decommissioning Approach

The AD tool and a comprehensive review are essential parts of a broader, recommended decommissioning framework. A structured approach typically includes:

  • Inventory and Assessment – Identifying all Adobe Analytics dependencies across Launch, custom code, and environments.
  • Mapping to AEP/CJA – Ensuring all required data is flowing into the appropriate schemas and datasets.
  • Gap Analysis – Determining where additional configuration or migration work needs to be done.
  • Remediation and Migration – Updating Launch rules, removing legacy code, and addressing undocumented dependencies.
  • Validation and QA – Confirming that reporting remains accurate in CJA after removal of Launch rules and data elements created for Adobe Analytics.
  • Sunset and Monitoring – Disabling AppMeasurement, removing Adobe Analytics extensions, and monitoring for errors.

Conclusion

Decommissioning Adobe Analytics is a strategic milestone in modernizing the digital data ecosystem. Using the right tools and having the right processes are essential.  The Analytics Decommissioner tool allows organizations to confidently transition to AEP and CJA. This approach to migration preserves data quality, reduces operational costs, and strengthens governance when teams execute it properly. By using the APIs and allowing the AD tool to handle the heavy lifting, teams ensure that they don’t overlook any dependencies.  This will enable a smooth and risk‑free transition with robust customer experience analytics.

]]>
https://blogs.perficient.com/2026/01/27/moving-to-cja-sunset-adobe-analytics-without-causing-chaos/feed/ 2 389876
Why Migrating to AEM as a Cloud Service Beats Starting from Scratch https://blogs.perficient.com/2025/12/09/why-migrating-to-aem-as-a-cloud-service-beats-starting-from-scratch/ https://blogs.perficient.com/2025/12/09/why-migrating-to-aem-as-a-cloud-service-beats-starting-from-scratch/#respond Tue, 09 Dec 2025 11:55:19 +0000 https://blogs.perficient.com/?p=388802

For organizations still running Adobe Experience Manager (AEM) on premises, the decision to modernize your digital experience platform is no longer a question of if, but how. As digital expectations accelerate and MarTech stacks evolve, staying on legacy infrastructure can limit your ability to innovate, scale, and compete. While replatforming to a new CMS may seem tempting, migrating to Adobe’s cloud-native AEM as a Cloud Service (AEMaaCS) offers a smarter, future-proof path forward.

Cloud Isn’t Just a Cost, It’s a Multiplier

At first glance, cloud migration may appear to be a significant investment. But when you factor in the total cost of ownership of on-prem infrastructure—hardware, maintenance, upgrades, security, and downtime—the economics shift. AEMaaCS eliminates the need for costly version upgrades and reduces operational overhead through auto-scaling, automated updates, and built-in security.

Replatforming to a new CMS may seem like a fresh start, but it often comes with hidden costs: retraining teams, rebuilding integrations, and losing years of content and customization. Adobe’s cloud offering allows you to preserve your investment in AEM while unlocking new efficiencies.

Architecture That Scales With You

AEMaaCS is built on a modern, containerized, microservices-based architecture that supports continuous delivery and scalability. Unlike monolithic on-prem deployments, Adobe’s cloud service is designed for agility, enabling faster deployments, real-time updates, and seamless integration with Adobe’s broader Experience Cloud ecosystem.

This architecture also supports global delivery with built-in CDN capabilities, ensuring performance and reliability across regions. For enterprises with complex digital footprints, this is a game-changer.

Innovate Without Rebuilding

One of the biggest risks of replatforming is the time it takes to regain momentum. With AEMaaCS, you can innovate faster by leveraging Adobe’s AI-powered features like Smart Tags, Content Automation, and personalization tools, all without waiting for the next upgrade cycle.

Adobe’s roadmap is tightly aligned with the future of digital experience: composable architecture, headless content delivery, and AI-driven insights. Migrating to AEM as a Cloud Service ensures you’re not just keeping up, you’re staying ahead.

Future-Proofing Your MarTech Stack

Adobe’s cloud-native platform is designed to integrate seamlessly with other Adobe Experience Cloud solutions like Adobe Analytics, Target, and Journey Optimizer. This alignment enables unified data, consistent customer journeys, and faster time-to-value across your marketing stack.

Choosing a different CMS could introduce integration challenges, data silos, and a fragmented customer experience. AEMaaCS offers a cohesive foundation that supports your long-term digital strategy.

Perficient Named as a Major Player for Worldwide Adobe Experience Cloud Professional Services |Learn More

The Cost of Charting a New Course

Replatforming to a non-Adobe CMS may seem like a clean break, but it often leads to unexpected complexity. You’ll need to rebuild your content models, rewire your integrations, and retrain your teams. Worse, you risk losing the deep Adobe expertise and ecosystem advantages you’ve built over time.

In contrast, migrating to AEMaaCS allows you to evolve without disruption. You retain your content, components, and workflows while gaining the benefits of a modern, cloud-native platform.

Evolve, Don’t Abandon

The future of digital experience is agile, intelligent, and cloud native. Adobe has made it clear that AEMaaCS is the strategic direction for the platform, with continuous innovation and support focused there. For existing AEM customers, the smartest move isn’t to start over; it’s to evolve.

By migrating to Adobe’s cloud, you’re not just upgrading your infrastructure; you’re unlocking a platform that’s built for what’s next.

Your map to smoothly migrating to AEM as a Cloud Service | Learn More

Ready to Evolve Your AEM Platform?

We’ve seen it all. With years of experience implementing Adobe solutions across industries, our team knows what it takes to migrate from AEM on-prem, Adobe Managed Services, or even a different platform entirely. In fact, we led the first large-scale customer deployment to AEM as a Cloud Service.

Whether you’re looking to modernize your infrastructure, reduce technical debt, or unlock new capabilities, we can help you make the move with confidence. Talk to our Adobe experts to get started.

]]>
https://blogs.perficient.com/2025/12/09/why-migrating-to-aem-as-a-cloud-service-beats-starting-from-scratch/feed/ 0 388802
5 Imperatives Financial Leaders Must Act on Now to Win in the Age of AI-Powered Experience https://blogs.perficient.com/2025/12/02/5-imperatives-financial-leaders-must-act-on-now-to-win-in-the-age-of-ai-powered-experience/ https://blogs.perficient.com/2025/12/02/5-imperatives-financial-leaders-must-act-on-now-to-win-in-the-age-of-ai-powered-experience/#respond Tue, 02 Dec 2025 12:29:07 +0000 https://blogs.perficient.com/?p=388106

Financial institutions are at a pivotal moment. As customer expectations evolve and AI reshapes digital engagement, leaders in marketing, CX, and IT must rethink how they deliver value.

Adobe’s report, State of Customer Experience in Financial Services in an AI-Driven World,” reveals that only 36% of the customer journey is currently personalized, despite 74% of executives acknowledging rising customer expectations. With transformation already underway, financial leaders face five imperatives that demand immediate action to drive relevance, trust, and growth.

1. Make Personalization More Meaningful

Personalization has long been a strategic focus, but today’s consumers expect more than basic segmentation or name-based greetings. They want real-time, omnichannel interactions that align with their financial goals, life stages, and behaviors.

To meet this demand, financial institutions must evolve from reactive personalization to predictive, intent-driven engagement. This means leveraging AI to anticipate needs, orchestrate journeys, and deliver content that resonates with individual context.

Perficient Adobe-consulting principal Ross Monaghan explains, “We are still dealing with disparate data and slow progression into a customer 360 source of truth view to provide effective personalization at scale. What many firms are overlooking is that this isn’t just a data issue. We’re dealing with both a people and process issue where teams need to adjust their operational process of typical campaign waterfall execution to trigger-based and journey personalization.”

His point underscores that personalization challenges go beyond technology. They require cultural and operational shifts to enable real-time, AI-driven engagement.

2. Redesign the Operating Model Around the Customer

Legacy structures often silo marketing, IT, and operations, creating friction in delivering cohesive customer experiences. To compete in a digital-first world, financial institutions must reorient their operating models around the customer, not the org chart.

This shift requires cross-functional collaboration, agile workflows, and shared KPIs that align teams around customer outcomes. It also demands a culture that embraces experimentation and continuous improvement.

Only 3% of financial services firms are structured around the customer journey, though 19% say it should be the ideal.

3. Build Content for AI-Powered Search

As AI-powered search becomes a primary interface for information discovery, the way content is created and structured must change. Traditional SEO strategies are no longer enough.

Customers now expect intelligent, personalized answers over static search results. To stay visible and trusted, financial institutions must create structured, metadata-rich content that performs in AI-powered environments. Content must reflect experience-expertise-authoritativeness-trustworthiness principles and be both machine-readable and human-relevant. Success depends on building discovery journeys that work across AI interfaces while earning customer confidence in moments that matter.

4. Unify Data and Platforms for Scalable Intelligence

Disconnected data and fragmented platforms limit the ability to generate insights and act on them at scale. To unlock the full potential of AI and automation, financial institutions must unify their data ecosystems.

This means integrating customer, behavioral, transactional, and operational data into a single source of truth that’s accessible across teams and systems. It also involves modernizing MarTech and CX platforms to support real-time decisioning and personalization.

But Ross points out, “Many digital experience and marketing platforms still want to own all data, which is just not realistic, both in reality and cost. The firms that develop their customer source of truth (typically cloud-based data platforms) and signal to other experience or service platforms will be the quickest to marketing execution maturity and success.”

His insight emphasizes that success depends not only on technology integration but also on adopting a federated approach that accelerates marketing execution and operational maturity.

5. Embed Guardrails Into GenAI Execution

As financial institutions explore GenAI use cases, from content generation to customer service automation, governance must be built in from the start. Trust is non-negotiable in financial services, and GenAI introduces new risks around accuracy, bias, and compliance.

Embedding guardrails means establishing clear policies, human-in-the-loop review processes, and robust monitoring systems. It also requires collaboration between legal, compliance, marketing, and IT to ensure responsible innovation.

At Perficient, we use our PACE (Policies, Advocacy, Controls, Enablement) Framework to holistically design tailored operational AI programs that empower business and technical stakeholders to innovate with confidence while mitigating risks and upholding ethical standards.

The Time to Lead is Now

The future of financial services will be defined by how intelligently and responsibly institutions engage in real time. These five imperatives offer a blueprint for action, each one grounded in data, urgency, and opportunity. Leaders who move now will be best positioned to earn trust, drive growth, and lead in the AI-powered era.

Learn About Perficient and Adobe’s Partnership

Are you looking for a partner to help you transform and modernize your technology strategy? Perficient and Adobe bring together deep industry expertise and powerful experience technologies to help financial institutions unify data, orchestrate journeys, and deliver customer-centric experiences that build trust and drive growth.

Get in Touch With Our Experts

]]>
https://blogs.perficient.com/2025/12/02/5-imperatives-financial-leaders-must-act-on-now-to-win-in-the-age-of-ai-powered-experience/feed/ 0 388106
Financial Services Marketing New Mandate: Driving Revenue, Not Just Reach https://blogs.perficient.com/2025/11/18/financial-services-marketing-new-mandate-driving-revenue-not-just-reach/ https://blogs.perficient.com/2025/11/18/financial-services-marketing-new-mandate-driving-revenue-not-just-reach/#respond Tue, 18 Nov 2025 12:41:24 +0000 https://blogs.perficient.com/?p=388167

The days of measuring marketing success by impressions and engagement are over, especially in financial services. Today, marketing leaders are being asked to do more than build brand awareness. They’re expected to drive top-line growth. 

According to Adobe’s report, “State of Customer Experience in Financial Services in an AI-Driven World,” 90% of financial services marketing leaders say they’re now expected to directly contribute to revenue. And 96% are being asked to become more efficient while doing so. 

This new mandate requires not only a change in metrics but a mindset transformation as well. 

Marketing is Now a Growth Engine

Modern financial institutions are retooling their marketing functions to prioritize: 

  • Pipeline creation 
  • Product adoption 
  • Customer lifetime value

Campaigns are no longer judged by vanity KPIs. Success is measured by conversion lift, wallet share, and ROI. That means marketing must operate with the same precision and accountability as sales and finance. 

Performance-Driven Marketing Requires New Infrastructure

To meet these expectations, marketing teams need: 

  • Attribution models that tie spend to outcomes 
  • Automation platforms that enable real-time optimization 
  • Journey tracking that connects every touchpoint to business impact 

Along with the right tools, financial services marketers will also need to build a culture of continuous improvement and commercial fluency. 

Business Fluency is the New Financial Services Marketing Skillset

To lead in this environment, marketers must speak the language of finance. That means understanding: 

  • Unit economics 
  • Acquisition cost 
  • Profitability metrics 

Winning teams are breaking down silos between marketing, sales, and product to drive aligned, data-informed execution. Financial services marketing is moving beyond a support function to a strategic partner in growth. 

Precision, Accountability, and Impact

By embracing data-driven strategies, building the right infrastructure, and fostering commercial fluency, marketing teams can move from a support function to a strategic driver of revenue. The organizations that succeed will be those that align marketing with business outcomes and lead with precision, accountability, and agility. 

Download the full Adobe report to learn more about the top insights shaping financial services marketing and the industry as a whole. 

How Perficient and Adobe Help Financial Services Marketers Lead

We help financial services firms modernize their marketing operations from journey orchestration to performance measurement. Together with Adobe, we’re enabling marketing teams to become growth architects, not just brand custodians. 

Let’s connect and uncover new ways to drive measurable impact together.

]]>
https://blogs.perficient.com/2025/11/18/financial-services-marketing-new-mandate-driving-revenue-not-just-reach/feed/ 0 388167
Trust Is the New Currency in Financial Services and Customers Are Setting the Terms https://blogs.perficient.com/2025/11/05/trust-is-the-new-currency-in-financial-services-and-customers-are-setting-the-terms/ https://blogs.perficient.com/2025/11/05/trust-is-the-new-currency-in-financial-services-and-customers-are-setting-the-terms/#respond Wed, 05 Nov 2025 11:16:09 +0000 https://blogs.perficient.com/?p=387890

In financial services, trust has always been foundational. But today, it’s being redefined, not by brand reputation or policy language, but by how customers experience speed, control, and transparency in real time. 

According to Adobe’s report, “State of Customer Experience in Financial Services in an AI-Driven World,” 96% of financial services executives say customers value privacy and data protection, and 63% say they expect transparent pricing. These have become operational expectations, and they’re shaping how trust is built moment by moment.

Trust Is Built in the Details Customers Can See

A face-ID login. A real-time transaction alert. A personalized financial nudge. These micro-moments now carry more weight than any static privacy policy. Customers judge trustworthiness by how responsive and secure their digital experiences feel—especially when managing sensitive tasks like wire transfers, credit approvals, or investment decisions. 

In this new landscape, trust is engineered, not assumed. 

Designing for Trust Means Designing for the Customer

Customers today expect more than digital convenience. They want to feel in control of their money, identity, and digital footprint and engage with institutions that respect their time, values, and privacy. Trust is no longer built solely through face-to-face interactions or legacy brand reputation. Trust is earned through every digital touchpoint.

To meet these expectations, financial institutions must deliver on three critical fronts:

1. Mobile-First Journeys With Instant Authentication

Customers expect secure access anytime, anywhere. A mobile-first design can enable frictionless, secure interactions that reinforce a sense of control and safety. Biometric authentication, real-time alerts, and intuitive navigation all contribute to a trustworthy experience.

2. Personalized Recommendations That Reflect Their Financial Goals

Trust grows when customers feel understood. Using AI and data responsibly to deliver tailored insights, whether it’s budgeting tips, investment opportunities, or credit alerts, shows that the institution is aligned with the customer’s financial well-being. Transparency in how data is used is key to maintaining that trust.

3. Seamless, Omnichannel Experiences That Feel Consistent and Secure

Whether a customer is engaging via app, website, call center, or in-branch, the experience should feel unified and secure. Consistency in branding, messaging, and service quality reinforces reliability, while secure data handling across channels ensures peace of mind.

Institutions that fail to deliver these experiences risk losing not just attention but loyalty. In a competitive landscape where switching providers is easier than ever, trust becomes a differentiator and a strategic imperative.

Build Trust In Financial Services

From Compliance Output to Design Input

Trust has become a core design principle. Instead of treating it as the outcome of compliance, financial institutions are embedding it into the very fabric of the customer experience. This shift reflects a broader understanding: trust is emotional, experiential, and earned in moments, not just mandated in policies.

That means:

Aligning products, security, and experience teams.

Trustworthy experiences require collaboration across silos. When product managers, cybersecurity experts, and UX designers work together, they can create solutions that are not only secure but also intuitive and empathetic. This alignment ensures that security features enhance, not hinder, the user experience.

Ensuring Personalization respects boundaries and data use is clearly communicated.

Customers want tailored experiences, but also want to know their data is safe. Leading institutions are adopting privacy-by-design principles, making it easy for users to understand how their data is used and giving them control over personalization settings. Transparency builds confidence; ambiguity erodes it.

Embedding transparency and predictability into every screen and interaction.

From clear language in disclosures to consistent UI patterns, every detail matters. Predictable flows, upfront information, and visible security cues (like encryption badges or session timers) help users feel safe and informed. These micro-moments of clarity add up to a macro-impact on trust.

This evolution requires cross-functional collaboration and a deep understanding of customer expectations.

Ready to Build Trust Through Experience Design?

Download the full Adobe report to explore the top 10 insights shaping the future of financial services, and discover how your organization can lead with intelligence, responsibility, and trust.

Learn About Perficient and Adobe’s Partnership

Perficient and Adobe bring together deep industry expertise and powerful experience technologies to help financial services organizations unify data, orchestrate journeys, and deliver customer-centric experiences that build trust and drive growth.

Get in Touch With Our Experts

]]>
https://blogs.perficient.com/2025/11/05/trust-is-the-new-currency-in-financial-services-and-customers-are-setting-the-terms/feed/ 0 387890
The Personalization Gap Is Hurting Financial Services, Here’s How to Close It https://blogs.perficient.com/2025/10/15/the-personalization-gap-is-hurting-financial-services-heres-how-to-close-it/ https://blogs.perficient.com/2025/10/15/the-personalization-gap-is-hurting-financial-services-heres-how-to-close-it/#respond Wed, 15 Oct 2025 15:22:25 +0000 https://blogs.perficient.com/?p=387848

In today’s financial landscape, personalization is no longer a luxury; it’s a customer expectation. Yet, according to Adobe’s latest State of Customer Experience in Financial Services in an AI-Driven World report, only 36% of the customer journey is currently personalized, despite 74% of financial services executives acknowledging that their customers expect tailored interactions.

This gap isn’t just a missed opportunity; it’s a trust breaker.

Why Personalization Matters More Than Ever

Financial decisions are deeply personal. Whether a customer is exploring mortgage options, planning for retirement, or managing small business finances, they expect advice and experiences that reflect their unique goals and life stage. Generic nudges and one-size-fits-all messaging simply don’t cut it anymore.

Early-stage interactions—like product discovery or financial education—are especially critical. These are high-value moments where relevance builds trust and guides decision-making. Yet many institutions fall short, lacking the orchestration needed to deliver personalized engagement across these initial touchpoints.

What’s Holding Institutions Back?

The report highlights several barriers:

  • Fragmented data systems that prevent a unified view of the customer
  • Legacy operating models that prioritize product silos over customer journeys
  • Compliance concerns that limit personalization efforts, even when customers expect it

These challenges are compounded by the rise of AI-powered experiences, which demand real-time, context-aware personalization across channels.

Adobe State of CX In Fs in an AI-Driven World Report Stat 2025

The Path Forward: Adaptive, Lifecycle Personalization

To close the gap, financial institutions must evolve from episodic personalization to adaptive, full-lifecycle engagement. That means:

  • Investing in unified customer profiles and behavioral insights
  • Building real-time content engines that respond to customer signals
  • Designing personalization strategies that grow with the relationship and not just the transaction

Download the full Adobe report to explore the top 10 insights shaping the future of financial services, and discover how your organization can lead with intelligence, responsibility, and trust.

Learn About Perficient and Adobe’s Partnership

Are you looking for a partner to help you transform and modernize your technology strategy? Perficient and Adobe bring together deep industry expertise and powerful experience technologies to help financial services organizations unify data, orchestrate journeys, and deliver customer-centric experiences that build trust and drive growth.

Get in Touch With Our Experts

]]>
https://blogs.perficient.com/2025/10/15/the-personalization-gap-is-hurting-financial-services-heres-how-to-close-it/feed/ 0 387848
When AI Becomes the Gatekeeper of Your Brand Message https://blogs.perficient.com/2025/10/14/when-ai-becomes-the-gatekeeper-of-your-brand-message/ https://blogs.perficient.com/2025/10/14/when-ai-becomes-the-gatekeeper-of-your-brand-message/#comments Tue, 14 Oct 2025 19:17:17 +0000 https://blogs.perficient.com/?p=387854

Search is no longer just about blue links and ten results per page. With the rapid adoption of Generative AI, consumers are increasingly turning to AI-written summaries to get quick, contextual answers without ever clicking through to a website. According to Bain & Company, 80% of consumers now rely on AI-generated summaries for at least 40% of their searches. This shift is fundamentally changing how people discover and interact with brands online.

However, the implications extend beyond search behavior alone. AI is now shaping the very pathways through which digital traffic flows, often bypassing traditional entry points, such as homepages and product pages. Instead, consumers engage with AI-generated content that summarizes, interprets, and even recommends on behalf of brands.

U.S. retail sites saw a 4,700% year-over-year increase in traffic from Generative AI sources in July 2025. Source: Adobe Analytics

The Zero-Click Challenge for Brands

This new behavior has given rise to what’s known as the “zero-click search” phenomenon, where users get the information they need directly from search results or an AI interface, without visiting the source site. For brands, this presents a major challenge: how do you measure engagement when the click never happens?

Traditional metrics like pageviews and bounce rates are losing relevance. Gartner projects a 50% decline in organic traffic by 2028, driven largely by the rise of AI-powered search and zero-click experiences. As a result, marketers are grappling with a visibility paradox: their content may be powering AI summaries and influencing decisions, but without direct engagement, it’s harder to attribute value or optimize the experience.

This leads to a critical concern…what happens when AI misrepresents your brand?

When AI Gets Your Brand Wrong

As large language models (LLMs) become the default interface for search and content discovery, brands are increasingly at the mercy of how these models interpret and summarize their content. And the truth is, LLMs don’t always get it right.

AI-generated summaries often strip away nuance, flatten brand voice, and even misrepresent key messages. This is especially risky for brands in regulated industries or those with complex value propositions. When your content is reduced to a few lines in a zero-click search result, you lose control over how your brand is perceived and whether your audience even visits your site.

These risks raise urgent questions for marketers:

  • How do you ensure your brand is accurately represented in AI-generated content?
  • How do you maintain differentiation when LLMs are trained on the same public data as your competitors?
  • And how do you optimize for visibility when traditional SEO signals are no longer enough?

To answer these questions, marketers need a new kind of toolkit that’s designed specifically for the AI era.

Adobe’s LLM Optimizer: A New Approach to Digital Experience

To help brands adapt to this new reality, Adobe has introduced the LLM Optimizer. This innovative solution is designed to ensure that brand content is not only discoverable by LLMs but also accurately represented in AI-generated summaries.

The LLM Optimizer works by analyzing how LLMs interpret and surface brand content, then providing actionable insights to improve visibility and accuracy. It helps marketers:

  • Optimize content structure and metadata for AI consumption
  • Ensure brand voice and messaging are preserved in AI summaries
  • Track AI-driven engagement across GenAI platforms
  • Identify content gaps where AI may be misrepresenting or omitting key brand information

In a world where AI is the new interface, Adobe’s LLM Optimizer empowers brands to take back control of their digital presence, even when the consumer never clicks.

Rethinking Digital Strategy for the AI Era

As AI continues to reshape how consumers search, discover, and decide, brands must evolve their digital strategies. It’s no longer enough to optimize for search engines alone; now, you must optimize for the AI models that interpret your content and deliver it to your audience.

Adobe’s LLM Optimizer offers a powerful way forward that helps brands stay visible, relevant, and measurable in a zero-click world. The digital front door may have moved, but with the right tools, brands can still welcome customers in.

Learn About Perficient and Adobe’s Partnership

Navigating the AI-driven digital landscape not only requires the right tools, but it also demands the right partner. Perficient and Adobe combine deep implementation and industry expertise with cutting-edge experience technology to help brands stay visible, relevant, and in control.

Let us help you rethink your digital front door and build experiences that connect, whether your customer clicks or not.

Get in Touch With Our Experts

]]>
https://blogs.perficient.com/2025/10/14/when-ai-becomes-the-gatekeeper-of-your-brand-message/feed/ 1 387854
Closing the Gap Between Expectations and Experience in Financial Services https://blogs.perficient.com/2025/10/06/closing-the-gap-between-expectations-and-experience-in-financial-services/ https://blogs.perficient.com/2025/10/06/closing-the-gap-between-expectations-and-experience-in-financial-services/#comments Mon, 06 Oct 2025 12:09:20 +0000 https://blogs.perficient.com/?p=387620

As customer expectations continue to rise, financial services organizations are under increasing pressure to deliver personalized, seamless, and secure digital experiences. Adobe’s latest report, The Total Economic Impact of Adobe’s Content Supply Chain Solution, reveals how Generative AI and connected data are reshaping the industry and why now is the time for financial institutions to evolve.

A Wake-Up Call for Financial Services

Consumers today expect more than just secure transactions. They want personalized recommendations, consistent omnichannel experiences, and transparency in how their data and AI-generated content are used. Yet, Adobe’s research shows a significant gap between these expectations and what financial services brands currently deliver:

  • 90% of consumers rate data privacy as critical, but only 58% feel their data is handled securely
  • 79% expect consistent experiences across channels, but just 47% say brands deliver
  • Only 33% feel brands anticipate their needs with relevant offers, despite 70% expecting it

This disconnect presents a clear opportunity for financial institutions to differentiate themselves by investing in AI-powered personalization and content delivery.

GenAI Moves From Concept to Competitive Advantage

Generative AI is no longer a futuristic concept; it is now a reality. It’s a strategic imperative. In 2025, 56% of financial services organizations are prioritizing GenAI to improve client interactions and employee productivity. Wealth and asset management firms lead the charge with 60% focusing on AI-driven client engagement compared to 52% in retail banking.

Use cases are expanding rapidly:

  • Chatbots are the most mature application, with 49% of organizations already using them
  • Journey optimization and data analysis are gaining traction, with over 40% of firms piloting or deploying solutions
  • AI is also being used to automate workflows, generate creative content, and personalize customer experiences across channels

Efficiency, Engagement, and Growth

Executives are already seeing tangible benefits from AI adoption:

  • 51% report major gains in content production speed
  • 50% see improved team productivity
  • 47% note freed-up resources for strategic initiatives

These improvements are driving better customer engagement and laying the foundation for scalable, personalized marketing.

Overcoming Compliance, Data Silos, and Culture

Despite the momentum, scaling AI in financial services isn’t without challenges. Governance, compliance, and privacy concerns top the list, especially in retail banking, where 59% of executives cite compliance as the biggest hurdle. Siloed data is another major issue, particularly in wealth and asset management, where 51% struggle to unify customer insights.

To move forward, organizations must:

  • Establish cross-functional AI governance committees
  • Invest in real-time data platforms
  • Prioritize ethical AI practices to protect brand reputation

The Road Ahead

The Adobe report paints a clear picture: financial services organizations must embrace AI and digital transformation to stay competitive. Key trends shaping the future include:

  • Hyper-Personalization | Real-time, one-to-one interactions are the goal, but only 33% of firms can update offers based on browsing history.
  • Omnichannel Consistency | Practitioners feel pressure to deliver more content across more channels, with 43% citing increased volume demands.
  • Sustainable Innovation | Wealth managers are leading the way in sustainable investing, responding to growing consumer demand.

To succeed, financial institutions must take a methodical, compliant approach to AI adoption, balancing innovation with trust. The winners will be those who connect data, content, and customer insights to deliver meaningful, personalized experiences at scale.

Ready to Transform Your Digital Experience Strategy?

Navigating the complexities of AI adoption, data governance, and digital transformation requires more than just technology. It demands deep industry expertise and a strategic partner who understands the nuances of financial services.

Our experts bring together Adobe solutions, generative AI innovation, and financial services experience to help you:

  • Deliver personalized, compliant, and scalable digital experiences
  • Break down data silos and activate real-time insights
  • Accelerate content creation and journey optimization with AI
  • Build trust through secure, transparent, and consistent customer interactions

Whether you’re modernizing for next-gen customers, launching new digital offerings, or scaling AI across your organization, we’re here to help you move forward with confidence.

Let’s connect and explore how we can elevate your customer experience together.

]]>
https://blogs.perficient.com/2025/10/06/closing-the-gap-between-expectations-and-experience-in-financial-services/feed/ 1 387620
AEM and Cloudflare Workers: The Ultimate Duo for Blazing Fast Pages https://blogs.perficient.com/2025/09/23/aem-and-cloudflare-workers-the-ultimate-duo-for-blazing-fast-pages/ https://blogs.perficient.com/2025/09/23/aem-and-cloudflare-workers-the-ultimate-duo-for-blazing-fast-pages/#respond Tue, 23 Sep 2025 10:30:23 +0000 https://blogs.perficient.com/?p=387173

If you’re using Adobe Experience Manager as a Cloud Service (AEMaaCS), you’ve likely wondered what to do with your existing CDN. AEMaaCS includes a fully managed CDN with caching, WAF, and DDoS protection. But it also supports a Bring Your Own CDN model.

This flexibility allows you to layer your CDN in front of Adobe’s, boosting page speed through edge caching.

The Challenge: Static vs. Dynamic Content

Many AEM pages combine static and dynamic components, and delivering both types of content through multiple layers of CDN can become a complex process.

Imagine a page filled with static components and just a few dynamic ones. For performance, the static content should be cached heavily. But dynamic components often require real-time rendering and can’t be cached. Since caching is typically controlled by page path—both in Dispatcher and the CDN—we end up disabling caching for the entire page. This workaround ensures dynamic components work as expected, but it undermines the purpose of caching and fast delivery.

Sling Dynamic Includes Provides a Partial Solution

AEM provides Sling Dynamic Includes (SDI) to partially cache the static content and dynamic content using placeholder tags. When a request comes in, it merges the static and dynamic content and then delivers it to the customer.

You can learn more about Sling Dynamic Include on the Adobe Experience League site.

However, SDI relies on the Dispatcher server for processing. This adds load and latency.

Imagine if this process is done on the CDN. This is where Edge Side Includes (ESI) comes into play.

Edge-Side Includes Enters the Chat

ESI does the same thing as SDI, but it uses ESI tags on the cached pages on the CDN.

ESI is powerful, but what if you want to do additional custom business logic apart from just fetching the content? That’s where Cloudflare Workers shines.

What is Cloudflare Workers?  

Cloudflare Workers is a serverless application that can be executed on the CDN Edge Network. Executing the code in edge locations closer to the user location reduces the latency and performance because the request does not have to reach the origin servers.  

Learn more about Cloudflare Workers on the Cloudflare Doc site.

ESI + Cloudflare Workers

In the following example, I’ll share how Cloudflare Workers intercepts ESI tags and fetches both original and translated content.

How to Enable ESI in AEM

  1. Enable SDI in AEM Publish: /system/console/configMgr/org.apache.sling.dynamicinclude.Configuration
  2. Add mod_include to your Dispatcher config.
  3. Set no-cache rules for SDI fragments using specific selectors.

Note: Set include-filter.config.include-type to “ESI” to enable Edge Side Includes.

Visit this article for more detailed steps on how to enable SDI, Dispatcher configuration.  

Writing the Cloudflare Worker Script

Next, write a custom script to intercept the ESI tag request and make a custom call to the origin to get the content, either from the original or translated content.

addEventListener('fetch', (event) => { 

  event.respondWith(handleRequest(event.request)); 

}); 

async function handleRequest(request){ 

//You can update the url and set it to your local aem url in case of local development 

const url = new URL(request.url); 

const origin = url.origin; 

// You can modify the headers based on your requirements and then create a new request with the new headers 

const originalHeaders = request.headers; 

            const newHeaders = new Headers(originalHeaders); 

//Append new headers here 

const aemRequest = new Request(url, { 

                    headers: newHeaders, 

                    redirect: 'manual', 

                }); 

// Get the response from the Origin 

try{ 

const aemresponse = await fetch(aemRequest); 

// Get the content type 

const contentType = aemresponse.headers.get("Content-Type") || ""; 

// If the content type is not “text/html”, return the response as usual or as per requirement, else check if the content has any “esi:include” tag 

If(!contentType.toLocaleLowerCase().includes("text/html")){ 

//return  

} 

//fetch the HTML response 

            const html = await aemresponse.text(); 

if(!html.includes("esi:include")){ 

//content doesn’t have esi tag, return the response 

} 

return fetchESIContent(aemresponse, html, origin) 

} 

} 

 

async function fetchESIContent(originResponse, html, origin) { 

    try{ 

   

      //RegEx expression to find all the esi:include tag in the page 

      const esiRegex = /<esi:include[^>]*\ssrc="([^"]+)"[^>]*\/?>/gi; 

   

      //fetch all fragments and replace those 

      const replaced = await replaceAsync(html, esiRegex, async (match, src) => { 

        try { 

          const absEsiUrl = resolveEsiSrc(src, origin); 

          const fragRes = await fetch(absEsiUrl, {headers: {"Cache-Control" : "no-store"}}); 

          console.log('Fragment response',fragRes.statusText) 

          return fragRes.ok ? await fragRes.text() : "Fragment Response didn't return anything"; 

        } catch (error) { 

          console.error("Error in fetching esi fragments: ",error.message); 

          return ""; 

        } 

      }) 

   

      const headers = appendResponseHeader(originResponse) 

      // Add this header to confirm that ESI has been injected successfully  

       headers.set("X-ESI-Injected", "true"); 

   

      return new Response(replaced, { 

        headers, 

        statusText: originResponse.statusText, 

        status: originResponse.status 

      }) 

    } 

    catch(err){ 

      new Response("Failed to fetch AEM page: "+ err.message, {status: 500}) 

    } 

  } 

 

// Function to fetch content asynchronously 

async function replaceAsync(str, regex, asycFn) { 

    const parts = []; 

    let lastIndex = 0; 

    for( const m of str.matchAll(regex)){ 

        //console.log("ESI Part of the page:: ",m) 

        parts.push(str.slice(lastIndex, m.index)); 

        parts.push(await asycFn(...m)); 

        lastIndex = m.index + m[0].length; 

    } 

    parts.push(str.slice(lastIndex)); 

    return parts.join(""); 

}

Bonus Tip: Local Testing With Miniflare

Want to test Cloudflare Workers locally? Use Miniflare, a simulator for Worker environments.

Check out the official Miniflare documentation.

You Don’t Need to Sacrifice Performance or Functionality

Implementing ESI through Cloudflare Workers is an excellent way to combine aggressive caching with dynamic content rendering—without compromising overall page performance or functionality. 

This approach helps teams deliver faster, smarter experiences at scale. As edge computing continues to evolve, we’re excited to explore even more ways to optimize performance and personalization.

]]>
https://blogs.perficient.com/2025/09/23/aem-and-cloudflare-workers-the-ultimate-duo-for-blazing-fast-pages/feed/ 0 387173
GenStudio for Performance Marketing: What’s New and What We’ve Learned https://blogs.perficient.com/2025/09/18/genstudio-for-performance-marketing-whats-new-and-what-weve-learned/ https://blogs.perficient.com/2025/09/18/genstudio-for-performance-marketing-whats-new-and-what-weve-learned/#comments Thu, 18 Sep 2025 11:08:51 +0000 https://blogs.perficient.com/?p=386969

This post builds on our original GenStudio for Performance Marketing in 5 Minutes overview. In that post, we explored what GenStudio is, how to get started, and where it fits in the content creation process.
Since then, we’ve continued testing GenStudio and tracking its evolution. Here’s what we’ve learned—and what’s new.

Real-World Use Cases for GenStudio

GenStudio helps marketers scale content creation and personalization. Here are a few high-impact use cases:

  • Reuse content from past campaigns across multiple channels
  • Personalize content by product, offer, or audience segment
  • Localize content for different languages and regions
  • Optimize content using performance insights

These use cases make GenStudio a powerful tool for performance marketing teams.

What’s New in GenStudio

Adobe continues to enhance GenStudio with new features and integrations. Since our initial review, here are some of the most notable updates:

  • Multilingual content creation in 12 languages
  • Video support for LinkedIn and Meta templates
  • Rich text formatting in content variants
  • Starter templates to accelerate creative production
  • Workfront Proof integration for streamlined reviews

You can find the full list of updates and fixes on Adobe’s release notes page.

What’s Working and What We’d Like to See

Development Considerations

GenStudio is primarily UI-based, which makes version control tricky. We recommend managing template versions outside the platform. Keeping multiple versions inside GenStudio can confuse users and clutter the workspace.

However, deleting templates can break experiences built from them. Proceed with caution.

Although rudimentary, it is possible to use the search tool to find a template and then create an experience from that template. It can be used while navigating templates, or when creating new content and prompted for a template, as in the example pictured below. 

Find Templates Via Search In Genstudio

Activation Channels Are Expanding

GenStudio now supports activation to Meta, Google Campaign Manager 360, and LinkedIn. Adobe has also announced upcoming support for:

  • Microsoft Advertising
  • Snap
  • TikTok

Integration with Adobe Journey Optimizer (AJO) is now available as well.

Managing Multiple Brands

We’ve added several brands to our GenStudio instance, including the one behind LumaX—our shopping experience site that demonstrates Edge Delivery Services, StreamX, Adobe Commerce, and Adobe Experience Platform integrations.

Adobe has previewed a Unified Branding Service in webinars, but we’re still waiting on official documentation and guidance on how to use it across applications.

Visualizing the Experience

The infographic below shows how we’ve structured GenStudio for performance marketing. Your experience may vary depending on your configuration and rollout stage.

Genstudio Experience Infographic

Click the image to enlarge the infographic.

Final Thoughts

We’re excited about GenStudio’s momentum and its growing list of features. As we continue building experiences that align with our clients’ needs, here are the things we’d love to see from Adobe in the future:

  • Best practices for image generation
  • Guidance on organizing assets
  • Faster performance and load times

As GenStudio evolves, so does the opportunity to reimagine how we create, personalize, and activate content at scale. We’re committed to exploring what’s possible—and sharing what we learn—so our clients can stay ahead in a fast-moving digital landscape.

]]>
https://blogs.perficient.com/2025/09/18/genstudio-for-performance-marketing-whats-new-and-what-weve-learned/feed/ 1 386969
How Adobe is Powering the Future of Digital Experiences With AI https://blogs.perficient.com/2025/09/16/how-adobe-is-powering-the-future-of-digital-experiences-with-ai/ https://blogs.perficient.com/2025/09/16/how-adobe-is-powering-the-future-of-digital-experiences-with-ai/#comments Tue, 16 Sep 2025 12:25:52 +0000 https://blogs.perficient.com/?p=386915

As digital experience platforms (DXPs) evolve, Adobe continues to lead the way in embedding artificial intelligence to help organizations deliver more personalized, efficient, and scalable customer experiences. Forrester’s report, The Impact of AI on Digital Experience Platforms, explores how vendors like Adobe are integrating agentic AI and generative AI (GenAI) to streamline experience operations and empower practitioners. 

Adobe is among the leaders in this space, offering tools that help teams simulate ideas, analyze impact, and activate personalized experiences across channels, all within a unified platform. 

Agentic AI Turns Insights Into Action

Adobe’s DXP ecosystem, including Adobe Experience Platform and Adobe Sensei, is increasingly powered by agentic AI — intelligent agents that support marketers and developers in orchestrating and optimizing customer journeys. These agents are designed to reduce manual effort, surface actionable insights, and automate tasks across the experience lifecycle. 

Perficient Adobe Consulting Principal Robert Sumner has seen firsthand how Adobe’s orchestration capabilities can be extended to deliver more seamless digital experiences across platforms. 

“Adobe’s suite enables orchestration to happen naturally across its tools, but we often help clients go further by integrating these capabilities across platforms to create a seamless journey,” said Sumner.  

Creativity Meets Efficiency With GenAI

Adobe is also at the forefront of GenAI innovation. From generating brand-consistent content to enabling marketers to build data-driven briefs and presentations within Microsoft 365 via Adobe’s copilot, GenAI is transforming how teams create and collaborate. 

Sumner mentioned that Adobe’s GenAI tools are already delivering measurable impact for clients. He said, “We’re seeing Adobe’s GenAI tools help clients scale content creation and experimentation. But success depends on aligning these capabilities with business goals and ensuring strong governance.”  

Perficient Named 2025 Gold Globee® Winner for Best Artificial Intelligence Service Provider | Learn More

Responsible AI Adoption

Adobe’s AI capabilities are powerful, but success depends on strong data foundations, human oversight, and change management. That’s why we work closely with clients to ensure these pillars are in place, enabling responsible and effective adoption of AI. 

We’re honored to have contributed to the research in an interview for Forrester’s report , The Impact of AI on Digital Experience Platforms. We believe it reflects our deep expertise in helping enterprise clients implement and optimize DXPs like Adobe. Whether it’s integrating predictive analytics, deploying cognitive copilots, or improving data governance, our teams are leading the way in enabling AI-powered transformation. 

If you’re exploring how to bring AI into your DXP strategy, we invite you to connect with us and keep the conversation going. 

Access the report here (available to Forrester subscribers or for purchase).  

Learn more about our Adobe expertise here 

Contact usto learn more. 

]]>
https://blogs.perficient.com/2025/09/16/how-adobe-is-powering-the-future-of-digital-experiences-with-ai/feed/ 3 386915