Adobe Analytics Install / Embed Tag or SDK | OpsBlu Docs

Adobe Analytics Install / Embed Tag or SDK

Deployment approach for installing Adobe Analytics's tag or SDK across web, mobile, and server environments.

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

Adobe Launch provides centralized tag management with version control, approval workflows, and environment-specific configurations.

Step 1: Create a Launch Property

  1. Navigate to https://experience.adobe.com/#/data-collection/tags
  2. Click "New Property"
  3. Enter property details:
    • Name: Your website/app name
    • Domains: Add all domains where tracking will occur
    • Privacy: Select appropriate privacy settings
  4. 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

  1. In your Launch property, navigate to Extensions > Catalog
  2. Search for "Adobe Analytics"
  3. Click "Install" on the Adobe Analytics extension
  4. 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:

  1. Navigate to Data Elements > Add Data Element
  2. Create elements for:

Example JavaScript data element for page name:

return _satellite.getVar('Page Name') || document.title;

Step 5: Create Rules

Pageview Rule:

  1. Rules > Add Rule > Name: "AA - Page Load"
  2. Events: Add > Core - Page Load (Window Loaded)
  3. 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

  1. Navigate to Publishing Flow
  2. Create Library: Add all changed resources
  3. Submit for approval
  4. Build for Development
  5. Test thoroughly
  6. Promote to Staging > Production

Method 2: Web SDK with Launch

The modern implementation using Adobe Experience Platform Web SDK:

Install Web SDK Extension

  1. Extensions > Catalog > Search "Web SDK"
  2. Install "Adobe Experience Platform Web SDK"
  3. 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

  1. Navigate to Admin > Code Manager in Adobe Analytics
  2. Download latest AppMeasurement for JavaScript
  3. Extract files: AppMeasurement.js and VisitorAPI.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

  1. Open browser DevTools (F12)
  2. Navigate to Network tab
  3. Filter by "adobe" or search for your tracking server
  4. Look for requests to:
    • b/ss/ (AppMeasurement beacon)
    • interact? (Web SDK Edge Network)
    • Check request payload includes expected variables

Adobe Experience Platform Debugger

  1. Install browser extension: Adobe Experience Platform Debugger
  2. Navigate to your site
  3. Open Debugger (extension icon)
  4. 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

  1. Log into Adobe Analytics
  2. Navigate to Reports > Real-Time
  3. Configure real-time reports for:
    • Page Views
    • Custom Events
    • eVars/Props
  4. Perform test actions on your site
  5. 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;
">
// 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.