Overview
Adobe Analytics provides multiple deployment options depending on your infrastructure, technology stack, and requirements. The modern approach uses Adobe Experience Platform Web SDK with Experience Platform Launch (now called Adobe Tags), while legacy implementations may still rely on AppMeasurement.js. This guide covers all deployment methods, from tag manager implementations to native mobile SDKs and server-side collection.
The Web SDK is Adobe's strategic direction, offering better performance, unified data collection for multiple Adobe solutions, and improved privacy controls. However, many organizations continue to use AppMeasurement for stability and feature compatibility.
Prerequisites
Before installing Adobe Analytics, ensure you have:
- Adobe Analytics Account: Active license with appropriate access levels
- Report Suite ID(s): Unique identifiers for dev, staging, and production environments (format:
rsid-dev,rsid-prod) - Adobe Experience Platform Launch Property: Created through the Data Collection UI (tags.adobe.com)
- Tracking Server: First-party or third-party tracking server hostname (e.g.,
metrics.yourdomain.com) - SSL Certificate: Valid TLS certificate for tracking server (required for secure collection)
- Admin Access: Permissions to create and publish Launch libraries
- Datastream Configuration: For Web SDK implementations, configured through Experience Platform
- CNAME Setup: (Optional but recommended) First-party domain CNAME pointing to Adobe data collection servers
Finding Your Configuration Values
Report Suite ID: Navigate to Admin > Report Suites in Adobe Analytics. The RSID appears in the Report Suite ID column.
Tracking Server: Found in Admin > General > General Account Settings under "Tracking Server" or check existing implementation's s.trackingServer value.
Datastream ID: Created in Experience Platform > Data Collection > Datastreams. Each datastream maps to specific Adobe solutions.
Installation Methods
Method 1: Adobe Experience Platform Launch (Recommended)
Adobe Launch provides centralized tag management with version control, approval workflows, and environment-specific configurations.
Step 1: Create a Launch Property
- Navigate to https://experience.adobe.com/#/data-collection/tags
- Click "New Property"
- Enter property details:
- Name: Your website/app name
- Domains: Add all domains where tracking will occur
- Privacy: Select appropriate privacy settings
- Click "Save"
Step 2: Install Launch Embed Code
Copy the environment-specific embed codes from Environments section:
Production Embed Code (place in <head>):
<script src="//assets.adobedtm.com/{PROPERTY_ID}/launch-{ENVIRONMENT_ID}.min.js" async></script>
Development/Staging: Use environment-specific URLs to test before production deployment.
Step 3: Install Adobe Analytics Extension
- In your Launch property, navigate to Extensions > Catalog
- Search for "Adobe Analytics"
- Click "Install" on the Adobe Analytics extension
- Configure extension settings:
General Settings:
// Library Management
- Use AppMeasurement: Select version (latest recommended)
- Production Account: Enter production RSID
- Staging Account: Enter staging RSID
- Development Account: Enter dev RSID
// Tracking Server
- SSL Tracking Server: metrics.yourdomain.com
- Tracking Server: metrics.yourdomain.com
// Visitor Service
- Marketing Cloud Organization ID: {ORG_ID}@AdobeOrg
Configure using Custom Code:
// Custom code editor (optional advanced configuration)
s.linkInternalFilters = 'javascript:,yourdomain.com';
s.trackDownloadLinks = true;
s.trackExternalLinks = true;
s.trackingServer = 'metrics.yourdomain.com';
s.trackingServerSecure = 'metrics.yourdomain.com';
Step 4: Create Data Elements
Create reusable data elements for common values:
- Navigate to Data Elements > Add Data Element
- Create elements for:
- Page Name:
%Path%or custom JavaScript - User ID: Cookie or data layer variable
- eVars/Props: Map to data layer keys
- Page Name:
Example JavaScript data element for page name:
return _satellite.getVar('Page Name') || document.title;
Step 5: Create Rules
Pageview Rule:
- Rules > Add Rule > Name: "AA - Page Load"
- Events: Add > Core - Page Load (Window Loaded)
- Actions: Add > Adobe Analytics - Send Beacon
- Beacon Type: s.t() (page view)
- eVar1: %User ID%
- prop1: %Page Category%
Event Tracking Rule:
// Rules > Add Rule > Name: "AA - Track Downloads"
// Events: Core - Click, CSS Selector: a[href$='.pdf']
// Actions: Adobe Analytics - Set Variables
s.linkTrackVars = 'eVar10,events';
s.linkTrackEvents = 'event10';
s.eVar10 = '{{Download File Name}}';
s.events = 'event10';
// Actions: Adobe Analytics - Send Beacon
// Beacon Type: s.tl() (link tracking)
Step 6: Build and Publish
- Navigate to Publishing Flow
- Create Library: Add all changed resources
- Submit for approval
- Build for Development
- Test thoroughly
- Promote to Staging > Production
Method 2: Web SDK with Launch
The modern implementation using Adobe Experience Platform Web SDK:
Install Web SDK Extension
- Extensions > Catalog > Search "Web SDK"
- Install "Adobe Experience Platform Web SDK"
- Configure:
// Datastreams
Datastream: Select your configured datastream
// Edge Domain (optional for first-party)
First-party domain: edge.yourdomain.com
// Identity
Third-party ID Sync Enabled: Yes
Third-party ID Sync Container ID: {CONTAINER_ID}
Create XDM Data Elements
Map your data layer to XDM schema:
// Data Element: XDM Object
{
"web": {
"webPageDetails": {
"name": "%Page Name%",
"URL": "%Page URL%"
}
},
"commerce": {
"purchases": {
"value": 1
},
"order": {
"purchaseID": "%Order ID%",
"priceTotal": %Order Total%
}
}
}
Create Send Event Rule
// Rule: Web SDK - Page View
// Event: Core - Page Load
// Action: Web SDK - Send Event
Type: web.webpagedetails.pageViews
XDM: %XDM Object%
Data: {
"__adobe": {
"analytics": {
"eVar1": "%Custom Variable%"
}
}
}
Method 3: Direct AppMeasurement.js Embed
For implementations without tag management:
Download AppMeasurement
- Navigate to Admin > Code Manager in Adobe Analytics
- Download latest AppMeasurement for JavaScript
- Extract files:
AppMeasurement.jsandVisitorAPI.js
Basic Implementation
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Your Page</title>
<!-- Visitor ID Service -->
<script src="/path/to/VisitorAPI.js"></script>
<!-- AppMeasurement -->
<script src="/path/to/AppMeasurement.js"></script>
<script>
// Initialize Visitor ID Service
var visitor = Visitor.getInstance("{ORG_ID}@AdobeOrg", {
trackingServer: "metrics.yourdomain.com",
trackingServerSecure: "metrics.yourdomain.com",
marketingCloudServer: "metrics.yourdomain.com",
marketingCloudServerSecure: "metrics.yourdomain.com"
});
// Initialize AppMeasurement
var s_account = "rsid-prod";
var s = s_gi(s_account);
// Configuration
s.trackingServer = "metrics.yourdomain.com";
s.trackingServerSecure = "metrics.yourdomain.com";
s.visitor = visitor;
// Enable automatic tracking
s.trackDownloadLinks = true;
s.trackExternalLinks = true;
s.trackInlineStats = true;
s.linkDownloadFileTypes = "exe,zip,wav,mp3,mov,mpg,avi,wmv,pdf,doc,docx,xls,xlsx,ppt,pptx";
s.linkInternalFilters = "javascript:,yourdomain.com";
s.linkLeaveQueryString = false;
// Page-level variables
s.pageName = document.title;
s.channel = "Home";
s.prop1 = "Custom Property Value";
s.eVar1 = "Custom Variable Value";
// Send pageview
var s_code = s.t();
if (s_code) document.write(s_code);
</script>
</head>
<body>
<!-- Your content -->
</body>
</html>
Event Tracking Example
// Link tracking
function trackCustomLink(linkName, linkType) {
var s = s_gi(s_account);
s.linkTrackVars = 'eVar10,events';
s.linkTrackEvents = 'event10';
s.eVar10 = linkName;
s.events = 'event10';
s.tl(this, linkType, linkName);
}
// Usage in HTML
<a href="/download.pdf" PDF', 'd');">Download</a>
Method 4: Web SDK Direct Implementation
Modern Web SDK implementation without Launch:
<!DOCTYPE html>
<html>
<head>
<script>
!function(n,o){o.forEach(function(o){n[o]||((n.__alloyNS=n.__alloyNS||[]).push(o),n[o]=function(){var u=arguments;return new Promise(function(i,l){n[o].q.push([i,l,u])})},n[o].q=[])})}(window,["alloy"]);
</script>
<script src="https://cdn1.adoberesources.net/alloy/2.19.1/alloy.min.js" async></script>
<script>
alloy("configure", {
"edgeConfigId": "{DATASTREAM_ID}",
"orgId": "{ORG_ID}@AdobeOrg",
"debugEnabled": true, // Set to false in production
"edgeDomain": "edge.yourdomain.com", // Optional first-party domain
"defaultConsent": "pending", // or "in" / "out"
"context": ["web", "device", "environment"],
"clickCollectionEnabled": true,
"downloadLinkQualifier": "\\.(?:zip|pdf|docx?)$"
});
// Send page view
alloy("sendEvent", {
"xdm": {
"web": {
"webPageDetails": {
"name": document.title,
"URL": window.location.href
}
}
},
"data": {
"__adobe": {
"analytics": {
"eVar1": "Custom Value",
"prop1": "Property Value"
}
}
}
});
</script>
</head>
<body>
<!-- Your content -->
</body>
</html>
Method 5: Google Tag Manager Integration
If using GTM instead of Adobe Launch:
Custom HTML Tag - AppMeasurement
<script>
(function() {
// Load Visitor API if not already loaded
if (typeof Visitor === 'undefined') {
var visitorScript = document.createElement('script');
visitorScript.src = 'https://assets.adobedtm.com/extensions/VISITOR_API_URL/VisitorAPI.js';
document.head.appendChild(visitorScript);
}
// Load AppMeasurement
if (typeof s_gi === 'undefined') {
var appMeasScript = document.createElement('script');
appMeasScript.src = '/assets/AppMeasurement.js';
appMeasScript.onload = function() {
initializeAdobeAnalytics();
};
document.head.appendChild(appMeasScript);
} else {
initializeAdobeAnalytics();
}
function initializeAdobeAnalytics() {
var s = s_gi('{{Adobe RSID}}');
s.trackingServer = '{{Adobe Tracking Server}}';
s.trackingServerSecure = '{{Adobe Tracking Server}}';
s.visitor = Visitor.getInstance('{{Adobe Org ID}}@AdobeOrg');
// Set variables from data layer
s.pageName = {{Page Name}};
s.eVar1 = {{User ID}};
s.prop1 = {{Page Category}};
// Send pageview
s.t();
}
})();
</script>
Trigger: All Pages (or specific page view trigger)
Custom HTML Tag - Event Tracking
<script>
(function() {
var s = s_gi('{{Adobe RSID}}');
s.linkTrackVars = 'eVar10,events';
s.linkTrackEvents = 'event10';
s.eVar10 = {{Event Name}};
s.events = 'event10';
s.tl(true, 'o', {{Event Name}});
})();
</script>
Trigger: Custom Event (based on your tracking plan)
Framework-Specific Implementations
React Implementation
Installation
npm install @adobe/alloy
# or
yarn add @adobe/alloy
Create Analytics Service
// src/services/adobeAnalytics.js
class AdobeAnalyticsService {
constructor() {
this.configured = false;
}
configure(datastreamId, orgId) {
if (this.configured) return;
if (typeof window !== 'undefined' && window.alloy) {
window.alloy('configure', {
edgeConfigId: datastreamId,
orgId: `${orgId}@AdobeOrg`,
context: ['web', 'device', 'environment'],
defaultConsent: 'pending',
clickCollectionEnabled: true
});
this.configured = true;
}
}
trackPageView(pageData) {
if (typeof window !== 'undefined' && window.alloy) {
window.alloy('sendEvent', {
xdm: {
web: {
webPageDetails: {
name: pageData.name || document.title,
URL: window.location.href
}
}
},
data: {
__adobe: {
analytics: pageData.analytics || {}
}
}
});
}
}
trackEvent(eventName, eventData) {
if (typeof window !== 'undefined' && window.alloy) {
window.alloy('sendEvent', {
xdm: {
eventType: eventName,
...eventData.xdm
},
data: {
__adobe: {
analytics: eventData.analytics || {}
}
}
});
}
}
setConsent(consentValue) {
if (typeof window !== 'undefined' && window.alloy) {
window.alloy('setConsent', {
consent: [{
standard: 'Adobe',
version: '2.0',
value: {
collect: { val: consentValue }
}
}]
});
}
}
}
export default new AdobeAnalyticsService();
Load Web SDK Script
// src/utils/loadAdobeSDK.js
export const loadAdobeSDK = () => {
return new Promise((resolve, reject) => {
if (window.alloy) {
resolve(window.alloy);
return;
}
// Add base code
!function(n,o){o.forEach(function(o){n[o]||((n.__alloyNS=n.__alloyNS||[]).push(o),n[o]=function(){var u=arguments;return new Promise(function(i,l){n[o].q.push([i,l,u])})},n[o].q=[])})}(window,["alloy"]);
// Load script
const script = document.createElement('script');
script.src = 'https://cdn1.adoberesources.net/alloy/2.19.1/alloy.min.js';
script.async = true;
script.onload = () => resolve(window.alloy);
script.onerror = reject;
document.head.appendChild(script);
});
};
App Component Integration
// src/App.js
import { useEffect } from 'react';
import { loadAdobeSDK } from './utils/loadAdobeSDK';
import adobeAnalytics from './services/adobeAnalytics';
function App() {
useEffect(() => {
// Load and configure Adobe SDK
loadAdobeSDK().then(() => {
adobeAnalytics.configure(
process.env.REACT_APP_ADOBE_DATASTREAM_ID,
process.env.REACT_APP_ADOBE_ORG_ID
);
// Track initial page view
adobeAnalytics.trackPageView({
name: document.title,
analytics: {
eVar1: 'Home Page'
}
});
});
}, []);
return (
<div className="App">
{/* Your app content */}
</div>
);
}
export default App;
React Router Integration
// src/App.js
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import adobeAnalytics from './services/adobeAnalytics';
function App() {
const location = useLocation();
useEffect(() => {
// Track page view on route change
adobeAnalytics.trackPageView({
name: document.title,
analytics: {
eVar1: location.pathname,
prop1: 'SPA Navigation'
}
});
}, [location]);
return (
<Routes>
{/* Your routes */}
</Routes>
);
}
Custom Hook
// src/hooks/useAdobeAnalytics.js
import { useCallback } from 'react';
import adobeAnalytics from '../services/adobeAnalytics';
export const useAdobeAnalytics = () => {
const trackEvent = useCallback((eventName, eventData) => {
adobeAnalytics.trackEvent(eventName, eventData);
}, []);
const trackPageView = useCallback((pageData) => {
adobeAnalytics.trackPageView(pageData);
}, []);
return {
trackEvent,
trackPageView
};
};
// Usage in component
import { useAdobeAnalytics } from './hooks/useAdobeAnalytics';
function MyComponent() {
const { trackEvent } = useAdobeAnalytics();
const handleClick = () => {
trackEvent('button_click', {
analytics: {
eVar10: 'CTA Button',
events: 'event10'
}
});
};
return <button Me</button>;
}
Next.js Implementation
// pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { loadAdobeSDK } from '../utils/loadAdobeSDK';
import adobeAnalytics from '../services/adobeAnalytics';
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
// Initialize Adobe on client-side only
if (typeof window !== 'undefined') {
loadAdobeSDK().then(() => {
adobeAnalytics.configure(
process.env.NEXT_PUBLIC_ADOBE_DATASTREAM_ID,
process.env.NEXT_PUBLIC_ADOBE_ORG_ID
);
});
}
}, []);
useEffect(() => {
const handleRouteChange = (url) => {
adobeAnalytics.trackPageView({
name: document.title,
analytics: {
eVar1: url,
prop1: 'Next.js Route'
}
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
export default MyApp;
Vue.js Implementation
// src/plugins/adobeAnalytics.js
import { loadAdobeSDK } from '../utils/loadAdobeSDK';
export default {
install: (app, options) => {
loadAdobeSDK().then(() => {
window.alloy('configure', {
edgeConfigId: options.datastreamId,
orgId: `${options.orgId}@AdobeOrg`,
context: ['web', 'device', 'environment']
});
app.config.globalProperties.$adobe = {
trackPageView(pageData) {
window.alloy('sendEvent', {
xdm: {
web: {
webPageDetails: {
name: pageData.name || document.title,
URL: window.location.href
}
}
},
data: {
__adobe: {
analytics: pageData.analytics || {}
}
}
});
},
trackEvent(eventName, eventData) {
window.alloy('sendEvent', {
xdm: {
eventType: eventName,
...eventData
}
});
}
};
});
}
};
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import adobeAnalytics from './plugins/adobeAnalytics';
const app = createApp(App);
app.use(router);
app.use(adobeAnalytics, {
datastreamId: import.meta.env.VITE_ADOBE_DATASTREAM_ID,
orgId: import.meta.env.VITE_ADOBE_ORG_ID
});
// Track route changes
router.afterEach((to) => {
app.config.globalProperties.$adobe.trackPageView({
name: to.meta.title || document.title,
analytics: {
eVar1: to.path
}
});
});
app.mount('#app');
Angular Implementation
// src/app/services/adobe-analytics.service.ts
import { Injectable } from '@angular/core';
declare global {
interface Window {
alloy: any;
}
}
@Injectable({
providedIn: 'root'
})
export class AdobeAnalyticsService {
private configured = false;
async initialize(datastreamId: string, orgId: string): Promise<void> {
if (this.configured) return;
await this.loadSDK();
window.alloy('configure', {
edgeConfigId: datastreamId,
orgId: `${orgId}@AdobeOrg`,
context: ['web', 'device', 'environment'],
clickCollectionEnabled: true
});
this.configured = true;
}
private loadSDK(): Promise<void> {
return new Promise((resolve, reject) => {
if (window.alloy) {
resolve();
return;
}
// Add base code
const baseCode = document.createElement('script');
baseCode.innerHTML = `!function(n,o){o.forEach(function(o){n[o]||((n.__alloyNS=n.__alloyNS||[]).push(o),n[o]=function(){var u=arguments;return new Promise(function(i,l){n[o].q.push([i,l,u])})},n[o].q=[])})}(window,["alloy"]);`;
document.head.appendChild(baseCode);
// Load SDK
const script = document.createElement('script');
script.src = 'https://cdn1.adoberesources.net/alloy/2.19.1/alloy.min.js';
script.async = true;
script.onload = () => resolve();
script.onerror = reject;
document.head.appendChild(script);
});
}
trackPageView(pageData: any): void {
if (!window.alloy) return;
window.alloy('sendEvent', {
xdm: {
web: {
webPageDetails: {
name: pageData.name || document.title,
URL: window.location.href
}
}
},
data: {
__adobe: {
analytics: pageData.analytics || {}
}
}
});
}
trackEvent(eventName: string, eventData: any): void {
if (!window.alloy) return;
window.alloy('sendEvent', {
xdm: {
eventType: eventName,
...eventData
}
});
}
}
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
import { AdobeAnalyticsService } from './services/adobe-analytics.service';
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor(
private router: Router,
private analytics: AdobeAnalyticsService
) {}
ngOnInit(): void {
// Initialize Adobe Analytics
this.analytics.initialize(
environment.adobeDatastreamId,
environment.adobeOrgId
);
// Track route changes
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) => {
this.analytics.trackPageView({
name: document.title,
analytics: {
eVar1: event.url
}
});
});
}
}
Mobile & OTT SDKs
iOS Implementation (Swift)
// Install via CocoaPods
// Podfile
pod 'AEPCore'
pod 'AEPAnalytics'
pod 'AEPEdge'
pod 'AEPEdgeIdentity'
// AppDelegate.swift
import AEPCore
import AEPAnalytics
import AEPEdge
import AEPEdgeIdentity
import AEPServices
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Configure SDK
MobileCore.setLogLevel(.trace) // Use .error in production
let appState = application.applicationState
MobileCore.registerExtensions([
Analytics.self,
Edge.self,
Identity.self
]) {
MobileCore.configureWith(appId: "YOUR_LAUNCH_ENVIRONMENT_ID")
if appState != .background {
MobileCore.lifecycleStart(additionalContextData: nil)
}
}
return true
}
}
// Track Screen View
import AEPCore
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
MobileCore.track(state: "Home Screen", data: [
"category": "main",
"userType": "premium"
])
}
}
// Track Event
func trackPurchase(orderId: String, total: Double) {
let xdmData: [String: Any] = [
"eventType": "commerce.purchases",
"commerce": [
"purchases": ["value": 1],
"order": [
"purchaseID": orderId,
"priceTotal": total
]
]
]
let experienceEvent = ExperienceEvent(xdm: xdmData)
Edge.sendEvent(experienceEvent: experienceEvent)
}
Android Implementation (Kotlin)
// build.gradle (app level)
dependencies {
implementation 'com.adobe.marketing.mobile:core:2.+'
implementation 'com.adobe.marketing.mobile:analytics:2.+'
implementation 'com.adobe.marketing.mobile:edge:2.+'
implementation 'com.adobe.marketing.mobile:edgeidentity:2.+'
}
// MainApplication.kt
import com.adobe.marketing.mobile.*
import android.app.Application
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
MobileCore.setApplication(this)
MobileCore.setLogLevel(LoggingMode.VERBOSE) // Use ERROR in production
MobileCore.registerExtensions(
listOf(
Analytics.EXTENSION,
Edge.EXTENSION,
com.adobe.marketing.mobile.edge.identity.Identity.EXTENSION
)
) {
MobileCore.configureWithAppID("YOUR_LAUNCH_ENVIRONMENT_ID")
MobileCore.lifecycleStart(null)
}
}
}
// Track Screen View
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
MobileCore.trackState("Home Screen", mapOf(
"category" to "main",
"userType" to "premium"
))
}
}
// Track Event
fun trackPurchase(orderId: String, total: Double) {
val xdmData = mapOf(
"eventType" to "commerce.purchases",
"commerce" to mapOf(
"purchases" to mapOf("value" to 1),
"order" to mapOf(
"purchaseID" to orderId,
"priceTotal" to total
)
)
)
val experienceEvent = ExperienceEvent.Builder()
.setXdmSchema(xdmData)
.build()
Edge.sendEvent(experienceEvent) { handles ->
// Handle response if needed
}
}
React Native Implementation
npm install @adobe/react-native-aepcore
npm install @adobe/react-native-aepanalytics
npm install @adobe/react-native-aepedge
// App.js
import React, { useEffect } from 'react';
import { AEPCore, AEPLifecycle, AEPSignal } from '@adobe/react-native-aepcore';
import { AEPAnalytics } from '@adobe/react-native-aepanalytics';
import { AEPEdge } from '@adobe/react-native-aepedge';
function App() {
useEffect(() => {
AEPCore.setLogLevel(AEPCore.LogLevel.VERBOSE);
AEPCore.configureWithAppId('YOUR_LAUNCH_ENVIRONMENT_ID');
AEPCore.registerExtensions([
AEPAnalytics,
AEPEdge,
AEPLifecycle,
AEPSignal
], () => {
console.log('Adobe Experience Platform SDK initialized');
});
}, []);
const trackScreen = (screenName, data) => {
AEPCore.trackState(screenName, data);
};
const trackEvent = (eventName, data) => {
AEPCore.trackAction(eventName, data);
};
return (
// Your app components
);
}
Server-Side Collection
Measurement Protocol API
Adobe Analytics doesn't have a direct Measurement Protocol like Google Analytics. Server-side events should use the Data Insertion API or Edge Network API.
Edge Network Server API
// Node.js Example
const https = require('https');
async function sendEvent(eventData) {
const payload = {
events: [{
xdm: {
eventType: eventData.eventType,
web: {
webPageDetails: {
name: eventData.pageName
}
},
commerce: eventData.commerce
},
data: {
__adobe: {
analytics: eventData.analytics
}
}
}]
};
const options = {
hostname: 'edge.adobedc.net',
path: `/ee/v2/interact?datastreamId=${process.env.DATASTREAM_ID}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.ADOBE_API_TOKEN}`
}
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(JSON.parse(data)));
});
req.on('error', reject);
req.write(JSON.stringify(payload));
req.end();
});
}
// Usage
sendEvent({
eventType: 'commerce.purchases',
pageName: 'Checkout Complete',
commerce: {
purchases: { value: 1 },
order: {
purchaseID: 'ORD-12345',
priceTotal: 99.99,
currencyCode: 'USD'
}
},
analytics: {
eVar1: 'Server-Side Order',
events: 'purchase,event1'
}
});
Data Insertion API (Legacy)
const https = require('https');
const querystring = require('querystring');
function sendDataInsertion(trackingData) {
const params = {
vid: trackingData.visitorId, // Required: Visitor ID
pageName: trackingData.pageName,
c1: trackingData.eVar1, // Custom eVar
events: trackingData.events,
products: trackingData.products,
purchaseID: trackingData.purchaseID
};
const path = `/b/ss/${process.env.RSID}/0?${querystring.stringify(params)}`;
const options = {
hostname: process.env.TRACKING_SERVER,
path: path,
method: 'GET'
};
const req = https.request(options);
req.end();
}
// Usage
sendDataInsertion({
visitorId: 'USER-123',
pageName: 'Order Confirmation',
eVar1: 'Backend Order',
events: 'purchase',
products: ';Product Name;1;99.99',
purchaseID: 'ORD-12345'
});
Configuration Options
Core Configuration Parameters
// AppMeasurement Configuration
var s = s_gi(s_account);
// Required
s.trackingServer = "metrics.yourdomain.com";
s.trackingServerSecure = "metrics.yourdomain.com";
// Visitor ID Service
s.visitor = Visitor.getInstance("{ORG_ID}@AdobeOrg");
// Link Tracking
s.trackDownloadLinks = true;
s.trackExternalLinks = true;
s.trackInlineStats = true;
s.linkDownloadFileTypes = "exe,zip,wav,mp3,mov,mpg,avi,wmv,pdf,doc,docx,xls,xlsx,ppt,pptx";
s.linkInternalFilters = "javascript:,yourdomain.com";
s.linkLeaveQueryString = false;
s.linkTrackVars = "None";
s.linkTrackEvents = "None";
// Currency
s.currencyCode = "USD";
// Charset
s.charSet = "UTF-8";
// Cookies
s.cookieDomainPeriods = "2";
s.cookieLifetime = "s";
s.fpCookieDomainPeriods = "2";
// Session Timeout
s.visitorNamespace = "yourdomain";
s.trackingServerSecure = "metrics.yourdomain.com";
// Plugins
s.usePlugins = true;
s.doPlugins = function(s) {
// Custom plugin code
};
// Privacy
s.trackingServer = "metrics.yourdomain.com";
s.trackingServerSecure = "metrics.yourdomain.com";
Web SDK Configuration
alloy("configure", {
// Required
"edgeConfigId": "{DATASTREAM_ID}",
"orgId": "{ORG_ID}@AdobeOrg",
// Optional
"edgeDomain": "edge.yourdomain.com",
"edgeBasePath": "ee",
"defaultConsent": "in", // "in", "out", "pending"
"context": ["web", "device", "environment", "placeContext"],
"debugEnabled": false,
"onBeforeEventSend": function(options) {
// Modify data before sending
return options;
},
// ID Migration
"idMigrationEnabled": true,
"thirdPartyCookiesEnabled": true,
// Click Collection
"clickCollectionEnabled": true,
"clickCollection": {
"internalLinkEnabled": true,
"externalLinkEnabled": true,
"downloadLinkEnabled": true,
"sessionStorageEnabled": true
},
// Download Link Qualifier
"downloadLinkQualifier": "\\.(exe|zip|wav|mp3|mov|mpg|avi|wmv|pdf|doc|docx|xls|xlsx|ppt|pptx)$",
// Personalization
"prehidingStyle": "#container { opacity: 0 !important }",
// Target
"targetMigrationEnabled": true
});
Verifying Installation
Browser DevTools Network Tab
- Open browser DevTools (F12)
- Navigate to Network tab
- Filter by "adobe" or search for your tracking server
- Look for requests to:
b/ss/(AppMeasurement beacon)interact?(Web SDK Edge Network)- Check request payload includes expected variables
Adobe Experience Platform Debugger
- Install browser extension: Adobe Experience Platform Debugger
- Navigate to your site
- Open Debugger (extension icon)
- Check:
- Summary: Verify Adobe Analytics is detected
- Analytics: View beacon details, eVars, props, events
- Logs: Check for errors or warnings
Console Verification
// Check if AppMeasurement is loaded
console.log(typeof s_gi !== 'undefined' ? 'AppMeasurement Loaded' : 'Not Loaded');
// Check Web SDK
console.log(typeof alloy !== 'undefined' ? 'Web SDK Loaded' : 'Not Loaded');
// Check Visitor ID
if (typeof Visitor !== 'undefined') {
var visitor = Visitor.getInstance("{ORG_ID}@AdobeOrg");
visitor.getMarketingCloudVisitorID(function(id) {
console.log('Marketing Cloud ID:', id);
});
}
// Inspect s object (AppMeasurement)
console.log('s.pageName:', s.pageName);
console.log('s.eVar1:', s.eVar1);
console.log('s.events:', s.events);
// Test send event
if (typeof alloy !== 'undefined') {
alloy("sendEvent", {
"xdm": {
"web": {
"webPageDetails": {
"name": "Test Page"
}
}
}
}).then(function(result) {
console.log('Event sent successfully:', result);
}).catch(function(error) {
console.error('Event send failed:', error);
});
}
Real-Time Reports
- Log into Adobe Analytics
- Navigate to Reports > Real-Time
- Configure real-time reports for:
- Page Views
- Custom Events
- eVars/Props
- Perform test actions on your site
- Verify data appears within 2-3 seconds
Common Installation Issues
| Issue | Symptoms | Solution |
|---|---|---|
| Tracking calls not firing | No requests in Network tab | Verify script is loaded, check for JavaScript errors, ensure init code runs |
| Wrong Report Suite | Data appears in wrong RSID | Check s_account value or datastream configuration matches environment |
| Missing variables | eVars/props empty in beacon | Verify variables are set before s.t() call, check linkTrackVars for link tracking |
| CORS errors | Console shows CORS errors | Configure tracking server CNAME correctly, ensure SSL certificates valid |
| Visitor ID not persisting | New visitor on each page | Check cookie domain settings, verify third-party cookies not blocked |
| Events not deduplicating | Duplicate events in reports | Set purchaseID for transactions, use s.purchaseID consistently |
| Launch library not loading | 404 error for Launch script | Verify embed code URL, check library is published to correct environment |
| Consent blocking tracking | No beacons after consent given | Ensure consent wrapper correctly initializes SDK after consent |
| Mobile app crashes | App crashes on startup | Check SDK version compatibility, verify all required extensions registered |
| Server-side events missing | Backend events don't appear | Verify datastream ID, check API credentials, ensure proper visitor ID passed |
| SPA page views not tracking | Only first page tracked | Implement route change tracking, call s.t() or alloy.sendEvent on navigation |
| Cross-domain tracking broken | New session on domain switch | Configure visitor ID domain settings, implement Visitor API appendVisitorIDsTo |
Debug Mode
AppMeasurement Debug:
// Enable debug output
s.debugTracking = true;
s.trackingServer = "metrics.yourdomain.com";
Web SDK Debug:
alloy("configure", {
"edgeConfigId": "{DATASTREAM_ID}",
"orgId": "{ORG_ID}@AdobeOrg",
"debugEnabled": true // Logs all SDK activity to console
});
// Or use Edge Debugger URL parameter
// https://yoursite.com?adobeEdgeDebugger=true
Security Best Practices
Protect Sensitive Data
// DO NOT track PII in clear text
// BAD:
s.eVar1 = userEmail; // email@example.com
s.eVar2 = userPhone; // 555-1234
// GOOD: Hash or pseudonymize
s.eVar1 = hashString(userEmail); // abc123...
s.eVar2 = 'user_' + hashedId;
// Hashing function example
function hashString(str) {
return crypto.subtle.digest('SHA-256', new TextEncoder().encode(str))
.then(hash => {
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
});
}
Secure API Keys and Secrets
// NEVER expose in client-side code
// BAD:
const DATASTREAM_ID = "12345-abcde-67890"; // Hardcoded
// GOOD: Use environment variables
const DATASTREAM_ID = process.env.REACT_APP_ADOBE_DATASTREAM_ID;
// Server-side only
const API_SECRET = process.env.ADOBE_API_SECRET; // Never send to client
Content Security Policy (CSP)
<!-- Add Adobe domains to CSP -->
<meta http-equiv="Content-Security-Policy" content="
script-src 'self' 'unsafe-inline'
https://assets.adobedtm.com
https://cdn1.adoberesources.net
https://cm.everesttech.net;
connect-src 'self'
https://edge.adobedc.net
https://*.demdex.net
https://metrics.yourdomain.com;
img-src 'self'
https://metrics.yourdomain.com
https://cm.everesttech.net;
">
Implement Consent Management
// Wait for consent before initializing
let consentGiven = false;
function handleConsentChange(consent) {
if (consent.analytics) {
if (!consentGiven) {
// Initialize Adobe on first consent
alloy("configure", { /* config */ });
consentGiven = true;
}
alloy("setConsent", {
consent: [{
standard: "Adobe",
version: "2.0",
value: {
collect: { val: "y" },
metadata: { time: new Date().toISOString() }
}
}]
});
} else {
// Revoke consent
alloy("setConsent", {
consent: [{
standard: "Adobe",
version: "2.0",
value: {
collect: { val: "n" }
}
}]
});
}
}
// Listen to CMP events
window.addEventListener('consentChanged', (e) => {
handleConsentChange(e.detail);
});
Validate Data Before Sending
function sanitizeValue(value, maxLength = 100) {
if (typeof value !== 'string') return '';
// Remove potentially harmful characters
return value
.replace(/<script[^>]*>.*?<\/script>/gi, '')
.replace(/<[^>]+>/g, '')
.substring(0, maxLength)
.trim();
}
// Usage
s.pageName = sanitizeValue(document.title);
s.eVar1 = sanitizeValue(userInput);
Performance Considerations
Async Loading
<!-- AppMeasurement: Load asynchronously -->
<script src="/path/to/AppMeasurement.js" async></script>
<!-- Web SDK: Already async by default -->
<script src="https://cdn1.adoberesources.net/alloy/2.19.1/alloy.min.js" async></script>
Defer Non-Critical Tracking
// Use requestIdleCallback for non-critical events
function trackLowPriority(eventData) {
if ('requestIdleCallback' in window) {
requestIdleCallback(() => {
s.tl(this, 'o', eventData.name);
});
} else {
setTimeout(() => {
s.tl(this, 'o', eventData.name);
}, 1);
}
}
Batch Events (Mobile)
// iOS: Configure batching
let configuration = [
"analytics.batchLimit": 5,
"analytics.offlineEnabled": true
] as [String: Any]
MobileCore.updateConfiguration(configDict: configuration)
// Android: Configure batching
val config = mapOf(
"analytics.batchLimit" to 5,
"analytics.offlineEnabled" to true
)
MobileCore.updateConfiguration(config)
Monitor Bundle Size
# Check Web SDK size impact
npm install --save-dev webpack-bundle-analyzer
# Add to webpack config
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
};
Lazy Load for SPAs
// Load Adobe only when needed
let adobeLoaded = false;
function ensureAdobeLoaded() {
if (adobeLoaded) return Promise.resolve();
return new Promise((resolve) => {
const script = document.createElement('script');
script.src = '/path/to/AppMeasurement.js';
script.onload = () => {
adobeLoaded = true;
initializeAdobe();
resolve();
};
document.head.appendChild(script);
});
}
// Track only when user interacts
document.addEventListener('scroll', () => {
ensureAdobeLoaded().then(() => {
s.tl(this, 'o', 'User Engaged');
});
}, { once: true });
Resource Hints
<!-- Preconnect to Adobe domains -->
<link rel="preconnect" href="https://assets.adobedtm.com">
<link rel="preconnect" href="https://edge.adobedc.net">
<link rel="dns-prefetch" href="https://metrics.yourdomain.com">
Deployment Strategy
- Use Adobe Experience Platform Launch/Tags to load the Web SDK, configure Edge domains, and map data elements to rules.
- If stuck on legacy, deploy appMeasurement via Launch with managed modules (A4T, Media Analytics) and tracking server settings.
- Keep separate dev/stage/prod libraries and embed codes; avoid promoting directly to prod without approvals.
Tag Manager Deployment
- Configure Launch libraries per environment and publish through the correct approval flow.
- Use data elements for data layer keys, then bind them to Web SDK or appMeasurement rules.
- Audit extensions (A4T, Media Analytics, Experience Platform) to ensure versions and settings match the solution design.
Direct Embed or Hard-Coded Scripts
- For static sites without Launch, embed the Web SDK asynchronously and configure the edgeConfig in the page head.
- Document tracking server or CNAME hostnames and ensure TLS/first-party cookie requirements are met.
Validation Checklist
- Use the Adobe Debugger/Assurance to confirm XDM payloads, consent flags, and destination report suites.
- Verify that merchandising eVars bind to product events and that currency, tax, and discount parameters map correctly.
Configuration Recommendations
Web SDK vs. Legacy: Migrate to Adobe Experience Platform Web SDK (alloy.js) for new implementations. It replaces AppMeasurement.js, AT.js, and ECID, reducing script count. Keep AppMeasurement only if you have complex merchandising eVar bindings that haven't been mapped to XDM yet.
First-Party CNAME: Use a first-party CNAME (e.g., metrics.yourdomain.com) for the tracking endpoint. This extends cookie lifetime under Safari ITP from 7 days to the full expiry. Configure through Adobe Customer Care — requires DNS CNAME record pointing to Adobe's edge servers and an SSL certificate.
Attribution Windows: Adobe Advertising Cloud defaults to 30-day click and 1-day viewthrough. Adjust based on your sales cycle: B2B typically needs 60-90 day click windows; ecommerce can use 7-14 day click and 1-day viewthrough.
Launch (Tags) Deployment: Use Adobe Experience Platform Tags (Launch) rather than direct embed. Maintain separate environments (dev/staging/prod) with distinct embed codes. Require approval workflow for production publishes.