Geo-Based Product Recommendations with Adobe Experience Cloud: Bridging the Gap Between Target and Real Purchase Behaviour
By Asha Lee | Adobe Experience Cloud | Personalization Architecture
The Business Context
Geography is one of the most commercially powerful signals an eCommerce business can act on — yet it remains one of the most underutilized. Product preferences, brand affinity, price sensitivity, and even seasonal demand patterns vary significantly between origin markets. For retailers operating across multiple regions — or serving internationally diverse customer bases from a single storefront — this variability represents both a challenge and an opportunity.
This is particularly acute for businesses where customer nationality or country of origin is a stronger purchase signal than their physical location at time of browsing. Think travel retail, cross-border marketplaces, global duty-free platforms, or any multi-regional brand with a single unified storefront. The analytics data to prove these differences almost certainly already exists. The gap is translating that insight into a live, personalized product experience.
Adobe Target is the natural tool to deliver that experience. But it has a meaningful limitation: its native Recommendations engine cannot surface products ranked by purchase popularity within a specific geo-segment. It can personalize where content appears based on location — but it cannot determine what to recommend based on region-specific behavioural history.
This post describes a practical, scalable architecture to close that gap using tools already available within the Adobe Experience Cloud stack.
Why Adobe Target Alone Falls Short
Adobe Target Recommendations supports criteria like Most Viewed, Top Sellers, and Recently Purchased — but these are global aggregates. There is no native dimension within AT Recommendations to filter or rank products by the geo-origin of the visitors who drove those signals.
You can use AT’s audience targeting to deliver different experiences to users from different locations. But the underlying recommendation pool remains undifferentiated. The result: you can say “show this content block to users from Japan,” but you cannot say “show the products that Japanese users most frequently purchased.”
That missing link requires pulling from Adobe Analytics, where geo-segmented purchase behaviour is captured in full — and building a pipeline to translate that insight into structured content that AT can serve.
Why This Matters Commercially
The revenue case for geo-based recommendations is straightforward: relevance drives conversion, and nothing drives relevance faster than showing a shopper products that people like them actually buy.
Consider a few common scenarios where this matters most:
- A travel retail or duty-free platform serving shoppers from dozens of nationalities on the same storefront. A Korean traveler and a Brazilian traveler browsing the same cosmetics category have demonstrably different brand preferences — preferences visible in your Analytics data.
- A cross-border marketplace where domestic customers and international buyers behave very differently. Surfacing globally popular products to a visitor from a market where those products are already widely available misses the point entirely.
- A multi-regional brand running a unified global site, where seasonal peaks, promotional cadences, and product affinities differ enough by region that a single bestseller list is meaningfully suboptimal.
In all of these cases, the data to personalize already exists. The problem is the pipeline to activate it.
The Architecture
The solution integrates four components that most Adobe Experience Cloud customers already have deployed:
Adobe Analytics → AEM (Scheduled Job) → eCommerce Platform → Adobe Target
↑ ↓
[Purchase & view [Geo-targeted Experience
data by geo-segment] Fragments served to user]Data Flow:
- Adobe Analytics continuously captures product-level events (views, add-to-cart, purchases) tagged with geographic dimensions.
- AEM runs a scheduled job that calls the Analytics Reporting API to extract top-performing SKUs per geo-segment on a defined cadence.
- AEM enriches those SKUs by calling the eCommerce platform API to retrieve current product data — name, imagery, pricing, and live stock availability.
- AEM structures the output as Experience Fragments (XF), one per geo-segment, each containing the current top-N products for that market.
- Adobe Target serves the appropriate Experience Fragment based on the visitor’s detected geo-location, replacing the default recommendations placement on the page.
Implementation Guide
Step 0: Authentication — Adobe Developer Console
All API calls to Adobe Analytics require an OAuth 2.0 access token via the Client Credentials flow. Set this up once in Adobe Developer Console.
Steps:
- Create or use an existing project in Adobe Developer Console.
- Add the Adobe Analytics API and select OAuth Server-to-Server authentication.
- Note your
Client IDandClient Secret. - Ensure the associated product profile in Admin Console grants access to the relevant report suite and the geo dimensions you intend to use (
geocountry,geocity, or custom classifications).
Token Request:
curl -X POST https://ims-na1.adobelogin.com/ims/token/v3 \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=openid,AdobeID,read_analytics"Store the returned bearer token securely — in AEM’s OSGi Secret configuration, a vault integration, or equivalent credential store. Build automatic token refresh logic into the scheduled job to handle expiry gracefully.
Step 1: Validate Your Report Structure Using Workspace + Network Inspection
Before writing integration code, validate your intended Analytics query structure by running the equivalent report in Analysis Workspace and inspecting the network request it generates.
How:
- Open Adobe Analytics > Analysis Workspace.
- Build a freeform table: Dimension =
Country(or your equivalent geo dimension), Metric =RevenueorOrders, Breakdown =Product SKU. - Open browser DevTools → Network tab → filter for
/reporting. - Run the report and inspect the request payload — this is the exact JSON structure you will replicate in your AEM job.
This removes guesswork about dimension IDs, metric IDs, and segment syntax before you build anything.
Get Asha Lee’s stories in your inbox
Join Medium for free to get updates from this writer.
Example Payload (Analytics 2.0 Reporting API):
{
"rsid": "your-report-suite-id",
"globalFilters": [
{ "type": "dateRange", "dateRange": "2025-04-01T00:00:00/2025-04-30T23:59:59" }
],
"metricContainer": {
"metrics": [
{ "columnId": "0", "id": "metrics/revenue" },
{ "columnId": "1", "id": "metrics/orders" }
]
},
"dimension": "variables/geocountry",
"settings": { "countRepeatInstances": true, "limit": 20, "page": 0 }
}For SKU-level data, add a second breakdown dimension call per country result. Paginate where your product catalogue requires it.
Step 2: Build the AEM Scheduled Job
Create a Sling Scheduler service in AEM to run this pipeline on a defined cadence. Weekly is a reasonable starting point for most retail contexts; businesses with high purchase velocity or strong seasonal peaks may benefit from more frequent refreshes.
The job should:
- Request or refresh an OAuth token.
- Query the Analytics Reporting API for the top 10 SKUs by revenue (or orders, depending on your preferred ranking signal) per target geo-segment.
- Parse the response and extract ordered SKU lists per segment.
- Store the results in the AEM JCR (e.g.,
/var/recommendations/geo/{segment}) as structured nodes or JSON.
Segment design is a strategic decision. Mapping directly to geocountry gives you granularity but can produce sparse, statistically unreliable data for smaller origin markets. For most implementations, consolidating to regional clusters (e.g., Greater China, South Asia, ANZ, Northeast Asia, Western Europe, Americas) produces more robust recommendation pools without sacrificing meaningful differentiation.
Step 3: Enrich SKUs with Live Product Data
For each SKU retrieved from Analytics, call your eCommerce platform API (Hybris OCC, Adobe Commerce REST, Salesforce Commerce Cloud, or equivalent) to fetch current product information:
- Product name and description
- Product image URL
- Current price (including any active promotional pricing)
- Live stock availability — this is the step most implementations skip, and it’s the one most likely to damage user trust if ignored
Filter out any SKUs with zero available stock at this stage. Replace them with the next-ranked SKU from the Analytics result set automatically. Do not surface out-of-stock products regardless of their historical geo-popularity.
Store enriched product data in AEM as Content Fragments under a structured model (e.g., a GeoRecommendation model with fields for segment, rank, SKU, product name, image URL, price, and product page URL).
Step 4: Build and Publish Experience Fragments in AEM
Create one Experience Fragment (XF) per geo-segment. Each XF references the corresponding Content Fragments and renders them using a shared product recommendation component.
Example XF structure:
/content/experience-fragments/recommendations/
├── geo-cn (Greater China segment)
├── geo-jp (Japan segment)
├── geo-kr (Korea segment)
├── geo-sea (Southeast Asia segment)
├── geo-anz (Australia & New Zealand segment)
└── geo-default (Fallback for unresolved segments)The scheduled job should trigger an automatic XF publish after each data refresh. Target should always be serving content built from the latest completed job run — not a cached version from the previous cycle.
Step 5: Configure Adobe Target Activities
In Adobe Target:
- Create an Experience Targeting (XT) activity for the recommendations placement (homepage rail, category page insertion, or wherever your primary recommendations slot lives).
- Define audiences by Geo > Country, or reference pre-built audiences from RT-CDP if geo-segment enrichment is already being handled there.
- Map each audience to the corresponding Experience Fragment exported from AEM.
- Set the default experience to your global bestseller XF to handle unresolvable geo cases, bot traffic, or VPN users who don’t resolve to a known segment cleanly.
If you want Target to optimise allocation across geo-experiences over time, Auto-Allocate is an option — though it adds complexity to your reporting model and is best reserved for a Phase 2 iteration once baseline performance is established.
Operational Considerations
Getting the architecture right is the first challenge. Keeping it reliable in production is the second. A few things worth building in from the start:
Concern Recommendation Data freshness Weekly refresh is a floor, not a ceiling. Build job failure alerting so stale data doesn’t silently persist past its validity window. Stock synchronisation The enrichment step must call live stock endpoints, not cached data. A historically popular SKU may be out of stock today. Segment coverage Define your catch-all segment deliberately. Not every visitor will resolve to a primary geo-segment cleanly — this experience must still be good. Sparse data for new products Recently launched products lack geo-level purchase history. Apply a recency-weighted blend with global bestsellers as a fallback for these cases. Price and promotion accuracy Promotional pricing must be reflected in the XF at time of display. A product shown at full price that is actually on promotion — or vice versa — erodes trust. Refresh cadence alignment Co-ordinate the Analytics job cadence with your promotional calendar. A XF refresh that runs mid-promotion may pull in products whose geo-popularity reflects a sale that has since ended.
What This Architecture Enables Beyond Geo
Once this pipeline is running, the same pattern extends to other segmentation strategies with minimal additional build:
- New vs. Returning Visitors — Surface different product mixes based on visit frequency, using AT audiences already available in your implementation
- Device Type — Curate mobile-specific product sets where browse-to-buy behaviour differs materially from desktop
- Authenticated vs. Guest Users — Where login data is available, layer CRM-informed segments on top of geo for higher-fidelity personalisation
- Seasonal / Event-driven Segments — Overlay time-based logic (peak travel seasons, local holidays, sales events) on top of the geo base to add a temporal dimension to recommendations
- Category Affinity — Extend the same AEM pipeline to drive category-level recommendations, not just product-level, using browsing behaviour as the Analytics signal
Each of these is a natural extension of the same scheduled job → XF → Target pattern established here.
Summary
Adobe Target is a powerful personalisation engine, but its native Recommendations capability was not designed to incorporate geo-origin as a popularity signal. For businesses where customer nationality or regional origin is a meaningful purchase intent indicator — travel retail, cross-border commerce, multi-regional brands — this is a gap worth closing.
The architecture described here does that by combining:
- The analytical depth of Adobe Analytics for geo-segmented purchase signals
- The content management capabilities of AEM for structured, refreshable recommendation content
- Live eCommerce platform data to ensure stock accuracy and pricing integrity
- Adobe Target’s audience-driven delivery to serve the right experience to the right visitor
No custom ML models. No net-new tooling. Just the Adobe stack working as an integrated system — which is exactly what the investment in that stack should enable.
Questions or feedback? Connect on LinkedIn or reach out via the Adobe Experience League community.




