### Install and Run Node Sandbox Source: https://github.com/adobe/alloy/blob/main/sandboxes/node/README.md Use these commands to install dependencies and start the Node.js sandbox. This example is intended to demonstrate the API shape and will not run until the Universal JS migration is complete. ```sh pnpm install ``` ```sh pnpm --filter @adobe/alloy-sandbox-node start ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/adobe/alloy/wiki/Project-Setup Run this command after navigating into the project directory to install all necessary project dependencies. ```bash npm install ``` -------------------------------- ### Install mkcert and Nginx Source: https://github.com/adobe/alloy/wiki/Running-the-sandbox-locally-over-HTTPS-on-Mac-OS Installs mkcert and Nginx using Homebrew, then generates a local SSL certificate for a specified domain within the sandbox directory. ```bash brew install mkcert brew install nginx cd sandbox mkcert "alloyio.com" ``` -------------------------------- ### Install mkcert and create certificate Source: https://github.com/adobe/alloy/wiki/Running-the-sandbox-locally-over-HTTPS-on-Mac-OS Installs mkcert using Homebrew and generates a local SSL certificate for a specified domain. Ensure you are in the sandbox directory. ```bash brew install mkcert cd sandbox mkcert "alloyio.com" ``` -------------------------------- ### Start Nginx as root Source: https://github.com/adobe/alloy/wiki/Running-the-sandbox-locally-over-HTTPS-on-Mac-OS Starts the Nginx service with root privileges to allow it to bind to privileged ports like 443. ```bash sudo nginx ``` -------------------------------- ### Run sandbox with HTTPS using react-scripts Source: https://github.com/adobe/alloy/wiki/Running-the-sandbox-locally-over-HTTPS-on-Mac-OS Starts the sandbox development server with HTTPS enabled, specifying the certificate and key files, and the host. Visit https://alloyio.com:3000/ to access the site. ```bash HTTPS=true SSL_CRT_FILE=./alloyio.com.pem SSL_KEY_FILE=./alloyio.com-key.pem HOST=alloyio.com npm start ``` -------------------------------- ### Factory Function Example Source: https://github.com/adobe/alloy/wiki/Conventions Factory functions are preferred over constructors for creating instances. They use the 'create' prefix and avoid the 'this' keyword. ```javascript const offer = createOffer(); ``` -------------------------------- ### Project Entry File with Dependency Injection in JavaScript Source: https://github.com/adobe/alloy/wiki/Conventions An example of an entry file (`index.js`) that imports and initializes modules, passing necessary dependencies. This file is typically tested via end-to-end tests due to its role as an integration point. ```javascript // index.js import cookieJar from "./cookieJar"; import parseConsentCookie from "./parseConsentCookie"; import getStoredConsentForPurpose from "./getStoredConsentForPurpose"; import personalizeContent from "./personalizeContent"; import initialize from "./initialize"; initialize( cookieJar, parseConsentCookie, getStoredConsentForPurpose, personalizeContent ); ``` -------------------------------- ### Enumeration Module Example Source: https://github.com/adobe/alloy/wiki/Conventions Enumeration values shared across modules should be placed in a separate module with named exports. The module name should be singular and located in a 'constants' directory. ```javascript // tagName.js export const BODY = "BODY"; export const IFRAME = "IFRAME"; export const IMG = "IMG"; export const DIV = "DIV"; export const STYLE = "STYLE"; export const SCRIPT = "SCRIPT"; export const SRC = "src"; export const HEAD = "HEAD"; ``` -------------------------------- ### Using ForEach for Single Value Computation Source: https://github.com/adobe/alloy/wiki/Conventions This example shows the 'forEach' pattern for computing a single value from an array, which is discouraged in favor of 'reduce' for this specific use case. ```javascript const consentByPurposeName = {}; purposeNames.forEach(purposeName => { consentByPurposeName[purposeName] = PENDING; }); ``` -------------------------------- ### Using Reduce for Single Value Computation Source: https://github.com/adobe/alloy/wiki/Conventions When computing a single value from an array, the 'reduce' pattern is preferred over 'forEach'. This example demonstrates creating an object to track consent by purpose. ```javascript const consentByPurposeName = purposeNames.reduce((memo, purposeName) => { memo[purposeName] = PENDING; return memo; }, {}); ``` -------------------------------- ### Run sandbox on port 3000 for Nginx proxy Source: https://github.com/adobe/alloy/wiki/Running-the-sandbox-locally-over-HTTPS-on-Mac-OS Starts the sandbox development server on port 3000, which will be proxied by Nginx. This allows Nginx to handle the HTTPS connection on port 443. ```bash cd sandbox PORT=3000 npm start ``` -------------------------------- ### Consent XDM Data Element Example Source: https://github.com/adobe/alloy/wiki/Guidelines-for-Consent-Management-Platforms This object represents consent preferences in the Adobe XDM standard, used within the 'consents' key. It includes fields for collection, personalization, sharing, and metadata. ```json { collect: { val: "y" }, personalize: { content: { val: "n" } }, share: { val: "y" }, metadata: { time: "2019-01-01T15:52:25+00:00" } } ``` -------------------------------- ### Send View Start Event with Custom Data Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/visitor_race.html Sends an initial 'sendEvent' command to AlloyJS, enabling decision rendering and overriding automatically collected device data. This is useful for sending custom XDM data with the first event. ```javascript alloy("sendEvent", { renderDecisions: true, xdm: { // Demonstrates overriding automatically collected data device: { screenHeight: 1, }, }, }).then(function (data) { console.log("Sandbox: View start event has completed.", data); }); ``` -------------------------------- ### Get Email SHA-256 Hash Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/index.html Asynchronously computes the SHA-256 hash of a given string, typically used for email addresses. ```javascript async function getEmailSha256(str) { const buf = await crypto.subtle.digest( "SHA-256", new TextEncoder("utf-8").encode(str), ); return Array.prototype.map .call(new Uint8Array(buf), (x) => ("00" + x.toString(16)).slice(-2)) .join(""); } ``` -------------------------------- ### Prepare Extension Files for NPM Source: https://github.com/adobe/alloy/wiki/Release-Private-Beta Builds the necessary files for the NPM package that the extension will use. ```bash npm run prepublishOnly ``` -------------------------------- ### Initialize Dummy ECID and Web Agent URL Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/agentComposerPreviewPage.html Sets up a dummy ECID for preview purposes and defines the URL for the web agent script. ```javascript const ecid = "dummy\_ecid\_" + Date.now(); // this is a dummy ecid that we will use for preview purposes only const webAgentURL = "https://experience-stage.adobe.net/solutions/experience-platform-brand-concierge-web-agent/static-assets/main.js"; ``` -------------------------------- ### Get URL Parameter Function Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-visitor.html Parses URL parameters to retrieve specific values. Handles URL encoding and decoding. ```javascript function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\\\\[").replace(/[\[\]]/g, "\\\\\]"); var regex = new RegExp("[\\?&]" + name + "=([^]*)"); var results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\\+/g, " ")); } ``` -------------------------------- ### Create a Changeset Source: https://github.com/adobe/alloy/wiki/Release-process Use this command to initiate the creation of a changeset file. It prompts for change type, affected packages, and a summary. ```bash pnpm changeset ``` -------------------------------- ### Utility Functions for URL and Cookies Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/legacy.html Provides functions to get and remove URL parameters, and to read all cookies or specifically the AMCV identity cookie. ```javascript function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\$& ``` ```javascript function removeUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\$& ``` ```javascript function readCookies() { const cookies = {}; document.cookie.split(";").forEach(function (c) { const ct = c.trim(); const index = ct.indexOf("="); const key = ct.slice(0, index); const value = ct.slice(index + 1); cookies[key] = value; }); return cookies; } ``` ```javascript function readIdentityCookie() { const cookies = readCookies(); const value = cookies["AMCV_5BFE274A5F6980A50A495C08@AdobeOrg"]; if (!value) { return "None"; } var parts = decodeURIComponent(value).split("|"); var i = 0; while (parts[i] !== "MCMID" && i < parts.length) { i += 1; } if (i >= parts.length) { return "None"; } return parts[i + 1]; } ``` -------------------------------- ### Get ECID using Alloy Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-alloy.html Retrieves the ECID (Edge Configuration ID) from Alloy using the `getIdentity` command. The ECID is logged to the console. ```javascript getEcidButton.addEventListener("click", function () { alloy("getIdentity") .then(function (result) { window.ecid = result.identity.ECID; console.log("ECID is: " + window.ecid); }) .catch(function (error) { console.log("Get identity error:", error); }); }); ``` -------------------------------- ### Core Entry Points for Platform Services Source: https://github.com/adobe/alloy/blob/main/packages/browser/UNIVERSAL_JS_MIGRATION.md The `createInstance` and `createCustomInstance` functions in `@adobe/alloy-core` now accept an optional `platformServices` object as a second parameter. This allows for injecting platform-specific implementations of services. ```javascript // packages/core/src/index.js export const createCustomInstance = (options, platformServices = {}) => { ... } export const createInstance = (options, platformServices = {}) => { ... } ``` -------------------------------- ### Bootstrap Conversational Experience Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/agentComposerPreviewPage.html Use this function to initialize and preview the conversational experience. Customize appearance and behavior using configuration objects. ```javascript window.bootstrapConversationalExperience({ previewConfigs, styles, ecid, webAgentURL, selector, }); ``` -------------------------------- ### Get URL Parameter Utility Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/index.html A utility function to extract a specific URL parameter's value. It handles URL encoding and special characters. ```javascript function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\\\\[").replace(/[\]\]/g, "\\\\\]"); var regex = new RegExp("[\\?&]" + name + "=([^]*)"); var results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); } ``` -------------------------------- ### Exit Pre-release Mode (Stable Release) Source: https://github.com/adobe/alloy/wiki/Release-process Commands to switch to a new branch, exit beta prerelease mode, and push the branch to prepare for a stable release. ```bash git switch main git switch --create 2.31.1 pnpm changeset pre exit git push origin 2.31.1 ``` -------------------------------- ### Initialize Visitor Instance with at.js 1.x Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/functional-test/testPageWithAtjs1.html Instantiates the Visitor library with a specific organization ID. This is typically done once on page load. ```javascript var visitor = Visitor.getInstance("5BFE274A5F6980A50A495C08@AdobeOrg"); ``` -------------------------------- ### Utility Function to Get URL Parameters Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/visitor_race.html A helper function to extract URL query parameters. It safely handles special characters in parameter names and decodes the resulting value. ```javascript function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\\\\[").replace(/[\]\]/g, "\\\\\]"); var regex = new RegExp("[\\?&]" + name + ")=([^]*)"); var results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); } ``` -------------------------------- ### Initialize Alloy with Configuration Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-alloy.html Configures the Alloy library with essential parameters like edge domain, datastream ID, organization ID, and consent settings. It also handles migration of ECID from legacy Visitor.js. ```javascript !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"]); const orgId = getUrlParameter("orgId") || "5BFE274A5F6980A50A495C08@AdobeOrg"; function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\$& "); var regex = new RegExp("[\\?&]" + name + "=([^]*)"); var results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); } function resolveEdgeDomain() { var defaultEdgeDomain = location.host.indexOf("alloyio.com") !== -1 ? "firstparty.alloyio.com" : undefined; return getUrlParameter("edgeDomain") || defaultEdgeDomain; } function stringToBoolean(str) { if (str) { return JSON.parse(str); } } function resolveBooleanQueryParam(param, defaultValue) { return getUrlParameter(param) ? stringToBoolean(getUrlParameter(param)) : defaultValue; } alloy("configure", { edgeDomain: resolveEdgeDomain(), datastreamId: getUrlParameter("configId") || "bc1a10e0-aee4-4e0e-ac5b-cdbb9abbec83", orgId, thirdPartyCookiesEnabled: getUrlParameter("thirdPartyCookiesEnabled") ? true : false, debugEnabled: true, // If `pending`, wait for the user's consent, but listening to the `setConsent` command. defaultConsent: "in", // Look for existing ECID Cookies set by the legacy Visitor.js library. // That means we need a cookie names: `AMCV_5BFE274A5F6980A50A495C08%40AdobeOrg: MCMID|76365103486713493572334524` idMigrationEnabled: true, }); ``` -------------------------------- ### Build Alloy Source: https://github.com/adobe/alloy/wiki/Running-Functional-Tests-Locally-using-SauceLabs This command is used to build the Alloy project. Specific build commands may vary. ```bash npm run build ``` -------------------------------- ### Package Extension Source: https://github.com/adobe/alloy/wiki/Release-Private-Beta Packages the extension for release. ```bash npm run package ``` -------------------------------- ### Specify Monitors with NPM Package Source: https://github.com/adobe/alloy/wiki/Monitoring-Hooks When using the NPM package, monitors can be specified directly within the `createInstance` function. Alternatively, the global `window.__alloyMonitors` array can still be used. ```javascript var monitor = { onBeforeCommand(data) { console.log(data); }, ... }; var alloyLibrary = require("@adobe/alloy"); var alloy = alloyLibrary.createInstance({ name: "alloy", monitors: [monitor] }); alloy("config", { ... }); alloy("sendEvent", { ... }); ``` -------------------------------- ### Initialize AlloyJS Visitor Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/visitor_race.html Initializes the AlloyJS library for visitor tracking. Ensure this runs before other Alloy commands. It sets up a global `alloy` function and queues commands if the library is not yet loaded. ```javascript Visitor.getInstance("53A16ACB5CC1D3760A495C99@AdobeOrg", {}); !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"]); ``` -------------------------------- ### Customer Bridge Code Example for Consent Source: https://github.com/adobe/alloy/wiki/Guidelines-for-Consent-Management-Platforms This code maps CMP consent categories to XDM format and calls the AEP Web SDK's setConsent command. It should be executed when consent is loaded or updated. ```javascript var identityMap = { ... }; CMP.whenConsentIsLoadedOrUpdated(function(categoriesString, collectedAt) { var categories = categoriesString.split(","); var consentsXdm = { collect: { val: categories.indexOf("abc") !== -1 ? "y" : "n" }, personalize: { content: { val: categories.indexOf("def") !== -1 ? "y" : "n" } }, share: { val: categories.indexOf("ghi") !== -1 ? "y" : "n" }, metadata: { time: collectedAt } }; window.alloy("setConsent", { consent: [{ standard: "Adobe", version: "2.0", value: consentsXdm }], identityMap: identityMap }); }); ``` -------------------------------- ### Get Marketing Cloud Visitor ID (ECID) Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-visitor.html Retrieves the Marketing Cloud Visitor ID (ECID) using the Visitor API and logs it to the console. The ECID is also stored globally on the window object. ```javascript var getEcidBtn = document.querySelector(".getEcidBtn"); getEcidBtn.addEventListener("click", function () { visitor.getMarketingCloudVisitorID(function (ecid) { console.log("ECID", ecid); window.ecid = ecid; }, true); }); ``` -------------------------------- ### Preview Configuration Object Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/agentComposerPreviewPage.html Defines the configuration parameters for the agent composer preview, including IMS organization ID, sandbox name, concierge ID, and AO instance ID. ```javascript const previewConfigs = { imsOrgId: "745F37C35E4B776E0A49421B@AdobeOrg", sandboxName: "agent-composer", conciergeId: "1550b506-8f99-4d79-b829-4c63bb265345", aoInstanceId: "acom\_agent", }; ``` -------------------------------- ### Execute Alloy Command Source: https://github.com/adobe/alloy/wiki/API-Design Use the global Alloy instance function to execute commands. Always provide options as an object, even for single parameters. ```javascript alloy("setDebug", { enabled: true }); ``` -------------------------------- ### Injecting Dependencies in JavaScript Source: https://github.com/adobe/alloy/wiki/Conventions Demonstrates a module that accepts dependencies as arguments, facilitating easier mocking during unit testing. This is the preferred approach for managing dependencies. ```javascript // getStoredConsentForPurpose.js export default (cookieJar, parseConsentCookie, purpose) => { const cookieValue = cookieJar.get(`alloy_consent`); if (cookieValue) { const parsedCookieValue = parseConsentCookie(cookieValue); return parsedCookieValue[purpose]; } }; ``` -------------------------------- ### Configure Alloy for Streaming Media (Automatic Session) Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/media-collection/streaming-media.html Configure Alloy to collect streaming media events with automatic session handling. Ensure the necessary parameters for streaming media are provided during configuration. ```javascript alloy("configure", { streamingMedia: { // adobeStreamingMedia // need to move these at session creation command channel: "video channel", playerName: "ninas player", appVersion: "alloy 2.16.0", adPingInterval: 1, mainPingInterval: 12, }, defaultConsent: "in", edgeBasePath: "ee", edgeConfigId: "27dae196-8c75-4eed-82d1-3895616f85d6", orgId: "97D1F3F459CE0AD80A495CBE@AdobeOrg", // UnifiedJS debugEnabled: true, prehidingStyle: ".personalization-container { opacity: 0 !important }", onBeforeEventSend: function (options) { console.log("onBeforeEEveeent", options); }, }); ``` -------------------------------- ### Initialize Visitor and AppMeasurement Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/legacy.html Initializes the AppMeasurement object and the Visitor API instance. Enables tracking and visitor value retrieval buttons. ```javascript document.getElementById("initializeButton").onclick = function () { var rsid = getUrlParameter("rsid") || "alloy"; window.s = s_gi(rsid); s.trackingServer = "alloy.sc.omtrdc.net"; s.visitor = Visitor.getInstance("5BFE274A5F6980A50A495C08@AdobeOrg", { overwriteCrossDomainMCIDAndAID: true, }); s.eVar1 = "alloy1"; document.getElementById("getVisitorValuesButton").disabled = false; document.getElementById("trackButton").disabled = false; document.getElementById("initializeButton").disabled = true; document.getElementById("currentAMCVIdentity").innerText = readIdentityCookie(); }; ``` -------------------------------- ### Increment Alloy Version for Beta Source: https://github.com/adobe/alloy/wiki/Release-Private-Beta Use this command to increment the version for a private beta release. Use `preminor` for the first beta and `prerelease` for subsequent betas. ```bash npm version preminor --preid beta --no-git-tag-version ``` ```bash npm version prerelease --preid beta --no-git-tag-version ``` -------------------------------- ### Clone Repository (Adobe Employee) Source: https://github.com/adobe/alloy/wiki/Project-Setup Use this command to clone the repository if you are an Adobe employee and have write access. ```bash git clone git@github.com:adobe/alloy.git ``` -------------------------------- ### Configure TCF and Initialize Visitor Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-visitor.html Configures the TCF API with specified settings and initializes the Visitor API instance. Retrieves orgId and aamServer from URL parameters. ```javascript const orgId = getUrlParameter("orgId") || "A99B6A045DA8B6320A494233@AdobeOrg"; __tcfapi.configure({ latency: 200, gdprApplies: true, purpose1: false, purpose10: true, vendorConsent: true, shouldWaitForExplicitConsent: true, tcString: getUrlParameter("consentString"), }); var visitor = Visitor.getInstance(orgId, { doesOptInApply: true, isIabContext: true, isOptInStorageEnabled: false, audienceManagerServer: getUrlParameter("aamServer") || "dcs-qe1.demdex.net", }); ``` -------------------------------- ### Opt In/Out via OneTrust JS API Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/iab-alloy.html Demonstrates how to trigger consent actions using the OneTrust JavaScript API. `OneTrust.AllowAll()` opts users in, while `OneTrust.RejectAll()` opts them out. ```javascript optInViaOneTrustApi.addEventListener("click", function () { OneTrust.AllowAll(); }); optOutViaOneTrustApi.addEventListener("click", function () { OneTrust.RejectAll(); }); ``` -------------------------------- ### Export SauceLabs Environment Variables Source: https://github.com/adobe/alloy/wiki/Running-Functional-Tests-Locally-using-SauceLabs Set your Sauce Labs username and access key as environment variables. Ensure you replace 'YOUR_USERNAME' and 'YOUR_ACCESS_KEY' with your actual credentials. ```bash export SAUCE_USERNAME=YOUR_USERNAME ``` ```bash export SAUCE_ACCESS_KEY=YOUR_ACCESS_KEY ``` -------------------------------- ### Command Execution Source: https://github.com/adobe/alloy/wiki/API-Design Commands are executed by calling the Alloy instance function with a command name and an options object. The options object should contain command-specific configurations as attributes. ```APIDOC ## Command Execution The instance function always accepts two arguments: 1. The command name as a string. 2. The options object which dictates how the command operates, what data gets sent to the server, etc. For some commands, the options object is optional. Here's an example of how a command would be executed: ```js alloy("setDebug", { enabled: true }); ``` Even if a command only has one piece of input, the input should always be provided as an attribute on the options object rather than be the options object itself. For example, a `syncIdentity` command may take an identity object as follows: ```js // Good: the identity is passed as an identity option alloy("syncIdentity", { "identity": { "AppNexus": { "id": "123456" }, "Email": { "id": "example@adobe.com" } } }) ``` Notice that even though the identity object is the primary subject of the command, the customer provides the identity as an `identity` option rather than providing the identity object as the options object itself. To illustrate, this would be considered an improper API: ```js // Bad: the identity is passed as the options object alloy("syncIdentity", { "AppNexus": { "id": "123456" }, "Email": { "id": "example@adobe.com" } }) ``` Although the proper API may seem verbose at times, it provides consistency across commands and allows options to be added later while still being backward-compatible. ``` -------------------------------- ### Include Visitor API and Alloy Script Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/media-collection/streaming-media.html Conditionally includes the Visitor API and Alloy scripts. The Visitor API is loaded first if the 'includeVisitor' URL parameter is 'true', followed by Alloy. Otherwise, only Alloy is loaded. ```javascript function getUrlParameter(name) { name = name.replace(/[\[\]]/g, "\\[").replace(/[\]\]/g, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^]*)"); var results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); } function includeScript(src) { return new Promise(function (resolve, reject) { var tag = document.createElement("script"); tag.type = "text/javascript"; tag.async = true; tag.addEventListener("load", function () { resolve(); }); const nonce = document .querySelector('meta[property="nonce"]') ?.getAttribute("nonce") || document.querySelector("script[nonce]")?.getAttribute("nonce") || ""; tag.setAttribute("nonce", nonce); tag.src = src; document.head.appendChild(tag); }); } if (getUrlParameter("includeVisitor") === "true") { includeScript("https://github.com/Adobe-Marketing-Cloud/id-service/releases/download/4.5.1/visitorapi.min.js").then(function () { Visitor.getInstance("53A16ACB5CC1D3760A495C99@AdobeOrg", { doesOptInApply: getUrlParameter("legacyOptIn") === "true", }); // Alloy only looks for window.Visitor when it initially loads, so only load Alloy after Visitor loaded. includeScript("/alloy.js"); }); } else { includeScript("/alloy.js"); } ``` -------------------------------- ### Importing Dependencies in JavaScript Source: https://github.com/adobe/alloy/wiki/Conventions Illustrates a module that imports dependencies directly. This approach is discouraged in favor of dependency injection for better testability. ```javascript // getStoredConsentForPurpose.js import cookieJar from "./cookieJar"; import parseConsentCookie from "./parseConsentCookie"; export default (purpose) => { const cookieValue = cookieJar.get(`alloy_consent`); if (cookieValue) { const parsedCookieValue = parseConsentCookie(cookieValue); return parsedCookieValue[purpose]; } }; ``` -------------------------------- ### Link SauceLabs Reporter to Project Source: https://github.com/adobe/alloy/wiki/Running-Functional-Tests-Locally-using-SauceLabs Link the testcafe-reporter-saucelabs package to your project to enable Sauce Labs reporting. This command is necessary for the reporter to be recognized. ```bash npm link testcafe-reporter-saucelabs ``` -------------------------------- ### Browser Package Service Instantiation and Injection Source: https://github.com/adobe/alloy/blob/main/packages/browser/UNIVERSAL_JS_MIGRATION.md The browser package (`@adobe/alloy-core`) instantiates concrete browser-specific services (e.g., `BrowserNetworkService`, `BrowserStorageService`) and passes them to the core `createInstance` function via the `platformServices` object. This enables the core logic to utilize platform-agnostic interfaces with browser-specific implementations. ```javascript // packages/browser/src/index.js import { createInstance, createCustomInstance } from "@adobe/alloy-core"; const platformServices = { network: new BrowserNetworkService(), storage: new BrowserStorageService(), cookie: new BrowserCookieService(), runtime: new BrowserRuntimeService(), legacy: new BrowserLegacyService(), globals: new BrowserGlobalsService(), }; export const createBrowserInstance = (options) => createInstance(options, platformServices); ``` -------------------------------- ### Upload Alloy Files to CDN Source: https://github.com/adobe/alloy/wiki/Release-Private-Beta Uploads the built Alloy JavaScript files to the specified CDN directory for the private beta release. ```bash sftp -oHostKeyAlgorithms=+ssh-dss -oStrictHostKeyChecking=no sshacs@dxresources.ssh.upload.akamai.com:/prod/alloy ``` ```bash mkdir edge-destinations-beta ``` ```bash cd edge-destinations-beta ``` ```bash mkdir 2.7.0-beta.0 ``` ```bash cd 2.7.0-beta.0 ``` ```bash put ./dist/alloy.js ``` ```bash put ./dist/alloy.min.js ``` -------------------------------- ### Configure Alloy with Identity Sync Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/index.html Configures Alloy with a specific organization ID, edge domain, and enables third-party cookies if syncIdentity URL parameter is true. It also sets up the configuration ID from the URL. ```javascript alloy("configure", { // TO-DO: remove temporary workaround for collect call with identityMap until thirdPartyCookiesEnabled default behavior is fixed thirdPartyCookiesEnabled: isSyncIdentity, edgeDomain: "firstparty.alloyio.com", configId: getUrlParameter("configId"), orgId: "555B08345D76A68D0A495E79@AdobeOrg", }); ``` -------------------------------- ### Create Event Merge ID and Handle Result Source: https://github.com/adobe/alloy/wiki/API-Design Commands return a promise that resolves with a result object. Ensure the output is accessed as an attribute of the result object for backward compatibility. ```javascript // Good: the event merge ID is provided as an attribute on result alloy("createEventMergeId").then(result => { console.log(result.eventMergeId); }) ``` -------------------------------- ### Configure AlloyJS Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/visitor_race.html Configures the AlloyJS instance with essential parameters like edge domain, datastream ID, organization ID, and debug settings. It also enables ID migration based on URL parameters and sets up prehiding styles. ```javascript alloy("configure", { edgeDomain: location.host.indexOf("alloyio.com") !== -1 ? "firstparty.alloyio.com" : undefined, datastreamId: "9999999", orgId: "53A16ACB5CC1D3760A495C99@AdobeOrg", debugEnabled: true, prehidingStyle: ".personalization-container { opacity: 0 !important }", idMigrationEnabled: !( location.href.indexOf("idMigrationEnabled=false") >= 0 ), }); ``` -------------------------------- ### Initialize Alloy Namespace Source: https://github.com/adobe/alloy/blob/main/sandboxes/browser/public/e2e/index.html Initializes the Alloy namespace in the window object if it doesn't exist, providing a mechanism for asynchronous operations. ```javascript !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"]); ``` -------------------------------- ### Module Using Injected Dependencies in JavaScript Source: https://github.com/adobe/alloy/wiki/Conventions Shows how a module like `personalizeContent.js` utilizes a function that itself relies on injected dependencies. This highlights the cascading nature of dependency injection. ```javascript // personalizeContent.js export default (cookieJar, parseConsentCookie, getStoredConsentForPurpose, personalizations) => { const storedPersonalizationConsent = getStoredConsentForPurpose( cookieJar, parseConsentCookie, "personalization" ); if (storedPersonalizationConsent === "in") { // Render personalizations. } } ``` -------------------------------- ### Define Alloy Monitors in HTML Source: https://github.com/adobe/alloy/wiki/Monitoring-Hooks Define an array of monitor objects in the global `__alloyMonitors` variable before loading Alloy to capture all events. Each object can contain various event handler methods. ```html