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.
Adobe Edge Delivery Services (EDS) provides a fast, document-based web stack. Adobe Target offers A/B testing and personalization capabilities. Integrating these two systems requires understanding some specific architectural considerations. This guide covers the complete integration, from the AEP schema setup all the way to rendering personalized content in EDS blocks, explaining the reasoning behind each technical decision.
The actors in the system
Four components form the integration architecture:
Browser (EDS) ←→ AEP Edge Network ←→ Adobe Target
↑
Datastream
The browser runs Alloy (Adobe Web SDK) within your EDS project. Alloy communicates with the AEP Edge Network through a Datastream, which routes events to the enabled services — including Adobe Target.
1. The XDM Schema — your data contract
Configure an XDM Schema in AEP as a formal data structure definition. This functions as a contract: declared fields can be transmitted; undeclared fields are rejected.
Class selection: use the Experience Event class, since Alloy transmits events (time-based occurrences: page views, clicks, interactions) rather than static profile data.
The schema defines structure only — it doesn't process data by itself. Runtime data flows through Alloy.
A minimal schema includes the standard XDM fields (eventType, web.URL, web.name, timestamp) plus the custom fields your implementation needs — such as userCountry for geographic personalization.
2. The Datastream — the central router
The Datastream is the most critical configuration object in this architecture. It serves as the AEP entry point and determines which Adobe services receive 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 transmits an event that includes a datastreamId, the Edge Network locates that datastream, confirms Target is enabled, and forwards the event to Target for activity evaluation.
This routing layer enables modularity: you can add AEP Profile, Analytics, or Audience Manager to the same datastream later without modifying any frontend code.
3. The Target activity — personalization rules
Create an Experience Targeting (XT) activity in Adobe Target 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.
Why this matters: EDS constructs the DOM programmatically, which makes VEC-style DOM manipulation unreliable. Form-based composition returning JSON offers is the correct pattern.
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 the rules sequentially and returns the first match. The location value (hero-background) is what 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 bridging the browser and the Edge Network. Initialize it in your EDS project's alloy-init.js:
await window.alloy('configure', {
datastreamId: 'your-datastreamId',
orgId: 'your-orgId@AdobeOrg',
edgeDomain: 'edge.adobedc.net',
});After configuration, Alloy can transmit events via sendEvent. The configuration step specifies which datastream to use. Since EDS loads scripts asynchronously, you'll need a readiness flag (window.alloy_configured = true) that blocks can wait on before firing events.
5. The complete request flow
Here's the exact sequence when a user lands on the page:
- User opens
/landing-pagein their browser. scripts.jsrunsinitAlloy()— loads Alloy from the CDN, configures it with thedatastreamId, setswindow.alloy_configured = true.- EDS decorates the Hero block.
hero.jscallssendPageViewEvent(['hero-background'])and waits for Alloy readiness viawaitForAlloy(). - Alloy sends a POST to
edge.adobedc.net/ee/v2/interactwith the XDM event payload and thedecisionScopes: ['hero-background']query. - The Edge Network identifies the datastream, confirms 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 returns.
- 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 records the impression and populates the activity reports.
6. Why decisionScopes is non-negotiable
This is the most frequent mistake in EDS + Target integrations. Without explicitly requesting a scope, Target evaluates only the global __view__ scope — which corresponds to VEC activities. Form-based activities remain invisible to Target unless requested 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 through two methods:
renderDecisions: true— Target modifies the DOM directly. Designed for VEC activities where Target injects CSS or HTML. This breaks in EDS because EDS controls the DOM construction process.renderDecisions: false— Target returns decisions as JSON. Your JavaScript determines what to do with them. This is the correct approach for EDS: you maintain control over how and when personalization is applied.
8. Closing the reporting loop with notifyDisplay()
The notifyDisplay() call is frequently overlooked, but it's essential for meaningful Target activity reports.
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
Conclusion
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.