How to Integrate Adobe Target with Edge Delivery Services Using Web SDK
A step-by-step technical breakdown of how EDS, AEP Edge Network, and Adobe Target work together to deliver real-time personalization —…
How to Integrate Adobe Target with Edge Delivery Services Using Web SDK
A step-by-step technical breakdown of how EDS, AEP Edge Network, and Adobe Target work together to deliver real-time personalization — without touching the DOM.

Image generated with AI
Adobe Edge Delivery Services (EDS) gives you a blazing-fast, document-based web stack. Adobe Target gives you robust A/B testing and experience personalization. Getting them to talk to each other, however, requires understanding a few non-obvious architectural decisions.
This guide walks through the full integration — from schema setup in AEP to rendering personalized content in an EDS block — and explains the why behind each technical choice.
“EDS builds the DOM in a controlled, programmatic way. That means Target can’t just inject HTML — you need to bring the decisions into your JavaScript and apply them yourself.”
The actors in the system
Before diving into the flow, here are the four components involved:
Browser (EDS) ←→ AEP Edge Network ←→ Adobe Target ↑ Datastream
The browser runs Alloy (Adobe Web SDK) inside your EDS project. Alloy communicates with the AEP Edge Network via a Datastream, which routes events to the services you’ve enabled — in this case, Adobe Target.
1. The XDM Schema — your data contract
The first thing to configure in AEP is an XDM Schema. This is a formal definition of what data your site will send. Think of it as a contract: if you declare a field in the schema, you can send it; if you don’t, it won’t be accepted.
Create the schema with class Experience Event, because Alloy sends events — things that happen over time (page views, clicks, interactions) — not static profile data.
Key concept:
The schema doesn’t process anything on its own. It only defines the structure. The actual data flows through Alloy at runtime.
A minimal schema for this use case includes standard XDM fields (eventType, web.URL, web.name, timestamp) plus any custom fields your implementation needs — such as a userCountry attribute for geo-based personalization.
2. The Datastream — the central router
The Datastream is the most important configuration object in this architecture. It’s the entry point to AEP and it decides which Adobe services receive your event data.
Datastream: “name-of-your-datastream” │
├── Receives events from Alloy (Web SDK)
├── Validates against your XDM Schema
└── Forwards to configured services:
└── Adobe Target ✅ Enabled
When Alloy sends an event, it includes a datastreamId in the request. The Edge Network looks up that datastream, sees that Target is enabled, and forwards the event to Target for activity evaluation.
This routing layer is what makes the architecture modular: you can add AEP Profile, Analytics, or Audience Manager to the same datastream without changing your frontend code.
3. The Target Activity — personalization rules
In Adobe Target, create an Experience Targeting (XT) activity using the Form-based Experience Composer. Unlike the Visual Experience Composer (VEC), the form-based composer works with named locations — called mboxes — instead of CSS selectors on the page.
This distinction matters: EDS constructs the DOM programmatically, so VEC-style DOM manipulation is unreliable. Form-based + JSON offers is the correct pattern here.
Activity: “Hero Background Personalization” Location: hero-background │ ├── Rule 1: Spain (ES) │
└── Returns Experience B: │ {“hero”: {“backgroundImage”: “/images/hero-bg-es.jpg”}} │
└── Rule 2: All Visitors (fallback)
└── Returns Experience A: {“hero”: {“backgroundImage”: “/images/hero-bg-default.jpg”}}
Target evaluates rules top to bottom and returns the first match. The location value (hero-background) is the identifier that connects the activity to your JavaScript. Target returns raw JSON — no HTML, no CSS. Your EDS block decides how to apply it.
4. Alloy (Web SDK) — the messenger
Alloy is Adobe’s JavaScript library that bridges the browser and the Edge Network. Initialize it in your EDS project’s alloy-init.js:
alloy-init.js
await window.alloy('configure', {
datastreamId: 'your-datastreamId',
orgId: 'your-orgId@AdobeOrg',
edgeDomain: 'edge.adobedc.net',
});
Once configured, Alloy can send events via sendEvent. The configuration step sets which datastream to use — and since EDS loads scripts asynchronously, you'll need a readiness flag (window.alloy_configured = true) that your blocks can wait on before firing events.
5. The complete request flow
Here’s exactly what happens when a user lands on the page:
- User opens
/landing-pagein their browser. scripts.jsrunsinitAlloy()— loads Alloy from CDN, configures it with thedatastreamId, setswindow.alloy_configured = true.- EDS decorates the Hero block.
hero.jscallssendPageViewEvent(['hero-background'])and waits for Alloy to be ready viawaitForAlloy(). - Alloy sends a POST to
edge.adobedc.net/ee/v2/interactwith the XDM event payload and adecisionScopes: ['hero-background']query. - The Edge Network identifies the datastream, sees Target is enabled, and forwards the request to Target with the requested scope.
- Target evaluates the activity. The user’s IP resolves to Spain → Rule 1 matches → Experience B is returned.
- The Edge Network returns the response to Alloy as a
propositionsarray. hero.jsparses the proposition content, extracts thebackgroundImagevalue, and renders the hero block with that image.notifyDisplay()sends adecisioning.propositionDisplayevent back to AEP so Target can record the impression and populate activity reports.
6. Why decisionScopes is non-negotiable
This is the most common mistake in EDS + Target integrations. Without explicitly requesting a scope, Target only evaluates the global __view__ scope — which corresponds to VEC activities. Form-based activities like ours are invisible to Target unless you ask for them by name.
Without scope — Target returns nothing
window.alloy('sendEvent', {
renderDecisions: false,
xdm: { ... }
})
// → propositions: []
With scope — Target returns your activity
window.alloy('sendEvent', {
renderDecisions: false,
decisionScopes: ['hero-background'],
xdm: { ... }
})
// → propositions: [{ scope: 'hero-background', items: [...] }]
7. Why renderDecisions: false
Target can apply decisions in two ways:
renderDecisions: true
Target modifies the DOM directly. Designed for VEC activities where Target injects CSS or HTML. This breaks in EDS because EDS owns the DOM construction process.
renderDecisions: false
Target returns decisions as JSON. Your JavaScript decides what to do with them. This is the correct approach for EDS — you stay in control of how and when personalization is applied.
8. Closing the reporting loop with notifyDisplay()
The notifyDisplay() call is often overlooked, but it's what makes Target's activity reports meaningful.
sendEvent (request) → Target knows someone asked for hero-background notifyDisplay (impression) → Target knows the experience was actually rendered (future) sendEvent click → Target knows if the user converted
Without the display notification, Target won’t count impressions. Your activity will appear to be running — the personalization works — but the reports will show zero activity. Always close the loop.
This integration pattern — Datastream → Form-based activity → decisionScopes → JSON propositions → manual DOM application — is the foundation for any serious personalization work in EDS. Once you understand the flow, adding more blocks, more activities, and more targeting rules becomes straightforward.
Please, feel free to share this post and comment any doubt you may have. I hope you find it useful!
메타데이터
- post_id
- 4d0daf6d42bf
- slug
- how-to-integrate-adobe-target-with-edge-delivery-services-using-web-sdk-4d0daf6d42bf
- url
- https://medium.com/@blasruizraul/how-to-integrate-adobe-target-with-edge-delivery-services-using-web-sdk-4d0daf6d42bf
- canonical_url
- https://medium.com/@blasruizraul/how-to-integrate-adobe-target-with-edge-delivery-services-using-web-sdk-4d0daf6d42bf
- author_url
- https://medium.com/@blasruizraul
- status
- ok
- fetched_at
- 2026-07-09 09:29:37