AEM-CIF core components and Adobe Experience Platform integration aem-cif-aep-integration

The Commerce Integration Framework (CIF) core components provide seamless integration with Adobe Experience Platform to forward storefront events and their data from client-side interactions such as add to cart.

The AEM CIF Core Components project provides a JavaScript library called Adobe Experience Platform connector for Adobe Commerce to collect event data from your Commerce storefront. That event data is sent to the Experience Platform where it is used in other Adobe Experience Cloud products, such as Adobe Analytics and Adobe Target to build a 360-degree profile that covers a customer journey. By connecting Commerce data to other products in the Adobe Experience Cloud, you can perform tasks like analyze user behavior on your site, perform AB testing, and create personalized campaigns.

Learn more about the Experience Platform Data Collection suite of technologies that allow you to collect customer experience data from client-side sources.

Send addToCart event data to Experience Platform send-addtocart-to-aep

The following steps show how to send the addToCart event data from AEM-rendered product pages to the Experience Platform using the CIF - Experience Platform Connector. By using the Adobe Experience Platform Debugger browser extension, you can test and review the submitted data.

Review addToCart event data in Adobe Experience Platform Debugger

Prerequisites prerequisites

You must use a local development environment to complete this demo. This includes a running instance of AEM that is configured and connected to an Adobe Commerce instance. Review the requirements and steps for setting up local development with AEM as a Cloud Service SDK.

You also need access to Adobe Experience Platform and permissions to create the schema, dataset, and datastreams for data collection. For more information, see Permission management.

AEM Commerce as a Cloud Service setup aem-setup

To have a working AEM Commerce as a Cloud Service local environment with the necessary code and config, complete the following steps.

Local setup

Follow the Local Setup steps to have a working AEM Commerce as a Cloud Service environment.

Project setup

Follow the AEM Project Archetype steps to create a brand new AEM Commerce (CIF) project.

TIP
In the following example, the AEM Commerce project is named: My Demo Storefront, however, you can choose your own project name.

AEM Commerce Project

Build and deploy the created AEM Commerce project to the local AEM SDK by running the following command from the project’s root directory.

$ mvn clean install -PautoInstallSinglePackage

The locally deployed My Demo StoreFront commerce site with default code and content looks like the following:

Default AEM Commerce Site

Install Peregrine and CIF-AEP connector dependencies

To collect and send the event data from the category and product pages of this AEM Commerce site, you need to install the key npm packages into the ui.frontend module of the AEM Commerce project.

Navigate to the ui.frontend module and install the required packages by running the following commands from the command line.

npm i --save lodash.get@^4.4.2 lodash.set@^4.3.2
npm i --save apollo-cache-persist@^0.1.1
npm i --save redux-thunk@~2.3.0
npm i --save @adobe/apollo-link-mutation-queue@~1.1.0
npm i --save @magento/peregrine@~12.5.0
npm i --save @adobe/aem-core-cif-react-components --force
npm i --save-dev @magento/babel-preset-peregrine@~1.2.1
npm i --save @adobe/aem-core-cif-experience-platform-connector --force
IMPORTANT
The --force argument is required sometimes as PWA Studio is restrictive with the supported peer dependencies. Usually, this should not cause any issues.

Configure Maven to use --force argument

As part of the Maven build process, the npm clean install (using npm ci) is triggered. This also requires the --force argument.

Navigate to the project’s root POM file pom.xml and locate the <id>npm ci</id> execution block. Update the block to look like the following:

<execution>
    <id>npm ci</id>
    <goals>
    <goal>npm</goal>
    </goals>
    <configuration>
    <arguments>ci --force</arguments>
    </configuration>
</execution>

Change Babel configuration format

Switch from the default .babelrc file relative configuration file format to babel.config.js format. This is a project-wide configuration format and allows the plugins and presets to be applied to the node_module with greater control.

  1. Navigate to the ui.frontend module and delete the existing .babelrc file.

  2. Create a babel.config.js file that uses the peregrine preset.

    code language-javascript
    const peregrine = require('@magento/babel-preset-peregrine');
    
    module.exports = (api, opts = {}) => {
        const config = {
            ...peregrine(api, opts),
            sourceType: 'unambiguous'
        }
    
        config.plugins = config.plugins.filter(plugin => plugin !== 'react-refresh/babel');
    
        return config;
    }
    

Configure webpack to use Babel

To transpile the JavaScript files using Babel loader (babel-loader) and webpack, you need to modify the webpack.common.js file.

Navigate to the ui.frontend module and update the webpack.common.js file to have the following rule inside the module property value:

{
    test: /\.jsx?$/,
    exclude: /node_modules\/(?!@magento\/)/,
    loader: 'babel-loader'
}

Configure Apollo Client

The Apollo Client is used to manage both local and remote data with GraphQL. It also stores the results of GraphQL queries in a local, normalized, in-memory cache.

For InMemoryCache to work effectively, you need a possibleTypes.js file. To generate this file, see Generating possibleTypes automatically. Also, see the PWA Studio reference implementation and an example of a possibleTypes.js file.

  1. Navigate to the ui.frontend module and save the file as ./src/main/possibleTypes.js

  2. Update the webpack.common.js file’s DefinePlugin section to replace the required static variables during build time.

    code language-javascript
    const { DefinePlugin } = require('webpack');
    const { POSSIBLE_TYPES } = require('./src/main/possibleTypes');
    
    ...
    
    plugins: [
        ...
        new DefinePlugin({
            'process.env.USE_STORE_CODE_IN_URL': false,
            POSSIBLE_TYPES
        })
    ]
    

Initialize Peregrine and CIF core components

To initialize the React-based Peregrine and CIF core components, create the required configuration and JavaScript files.

  1. Navigate to the ui.frontend module and create the following folder: src/main/webpack/components/commerce/App

  2. Create a config.js file with the following content:

    code language-javascript
    
    // get and parse the CIF store configuration from the <head>
    const storeConfigEl = document.querySelector('meta[name="store-config"]');
    const storeConfig = storeConfigEl ? JSON.parse(storeConfigEl.content) : {};
    
    // the following global variables are needed for some of the peregrine features
    window.STORE_VIEW_CODE = storeConfig.storeView || 'default';
    window.AVAILABLE_STORE_VIEWS = [
        {
            code: window.STORE_VIEW_CODE,
            base_currency_code: 'USD',
            default_display_currency_code: 'USD',
            id: 1,
            locale: 'en',
            secure_base_media_url: '',
            store_name: 'My Demo StoreFront'
        }
    ];
    window.STORE_NAME = window.STORE_VIEW_CODE;
    window.DEFAULT_COUNTRY_CODE = 'en';
    
    export default {
        storeView: window.STORE_VIEW_CODE,
        graphqlEndpoint: storeConfig.graphqlEndpoint,
        // Can be GET or POST. When selecting GET, this applies to cache-able GraphQL query requests only.
        // Mutations will always be executed as POST requests.
        graphqlMethod: storeConfig.graphqlMethod,
        headers: storeConfig.headers,
    
        mountingPoints: {
            // TODO: define the application specific mount points as they may be used by <Portal> and <PortalPlacer>
        },
        pagePaths: {
            // TODO: define the application specific paths/urls as they may be used by the components
            baseUrl: storeConfig.storeRootUrl
        },
        eventsCollector: {
            eventForwarding: {
                acds: true,
                aep: false,
            }
        }
    };
    
    note important
    IMPORTANT
    While you might already be familiar with the config.js file from AEM Guides - CIF Venia Project, there are a few changes you need to make to this file. First, review any TODO comments. Then, inside the eventsCollector property, find the eventsCollector > aep object and update the orgId and datastreamId properties to the correct values. Learn more.
  3. Create an App.js file with the following content. This file resembles a typical React application-starting point file and contains React and custom hooks and React Context usage to facilitate the Experience Platform integration.

    code language-javascript
    
    import config from './config';
    
    import React, { useEffect } from 'react';
    import ReactDOM from 'react-dom';
    import { IntlProvider } from 'react-intl';
    import { BrowserRouter as Router } from 'react-router-dom';
    import { combineReducers, createStore } from 'redux';
    import { Provider as ReduxProvider } from 'react-redux';
    import { createHttpLink, ApolloProvider } from '@apollo/client';
    import { ConfigContextProvider, useCustomUrlEvent, useReferrerEvent, usePageEvent, useDataLayerEvents, useAddToCartEvent } from '@adobe/aem-core-cif-react-components';
    import { EventCollectorContextProvider, useEventCollectorContext } from '@adobe/aem-core-cif-experience-platform-connector';
    import { useAdapter } from '@magento/peregrine/lib/talons/Adapter/useAdapter';
    import { customFetchToShrinkQuery } from '@magento/peregrine/lib/Apollo/links';
    import { BrowserPersistence } from '@magento/peregrine/lib/util';
    import { default as PeregrineContextProvider } from '@magento/peregrine/lib/PeregrineContextProvider';
    import { enhancer, reducers } from '@magento/peregrine/lib/store';
    
    const storage = new BrowserPersistence();
    const store = createStore(combineReducers(reducers), enhancer);
    
    storage.setItem('store_view_code', config.storeView);
    
    const App = () => {
        const [{ sdk: mse }] = useEventCollectorContext();
    
        // trigger page-level events
        useCustomUrlEvent({ mse });
        useReferrerEvent({ mse });
        usePageEvent({ mse });
        // listen for add-to-cart events and enable forwarding to the magento storefront events sdk
        useAddToCartEvent(({ mse }));
        // enable CIF specific event forwarding to the Adobe Client Data Layer
        useDataLayerEvents();
    
        useEffect(() => {
            // implement a proper marketing opt-in, for demo purpose you hard-set the consent cookie
            if (document.cookie.indexOf('mg_dnt') < 0) {
                document.cookie += '; mg_dnt=track';
            }
        }, []);
    
        // TODO: use the App to create Portals and PortalPlaceholders to mount the CIF / Peregrine components to the server side rendered markup
        return <></>;
    };
    
    const AppContext = ({ children }) => {
        const { storeView, graphqlEndpoint, graphqlMethod = 'POST', headers = {}, eventsCollector } = config;
        const { apolloProps } = useAdapter({
            apiUrl: new URL(graphqlEndpoint, window.location.origin).toString(),
            configureLinks: (links, apiBase) =>
                // reconfigure the HTTP link to use the configured graphqlEndpoint, graphqlMethod and storeView header
    
                links.set('HTTP', createHttpLink({
                    fetch: customFetchToShrinkQuery,
                    useGETForQueries: graphqlMethod !== 'POST',
                    uri: apiBase,
                    headers: { ...headers, 'Store': storeView }
                }))
        });
    
        return (
            <ApolloProvider {...apolloProps}>
                <IntlProvider locale='en' messages={{}}>
                    <ConfigContextProvider config={config}>
                        <ReduxProvider store={store}>
                            <PeregrineContextProvider>
                                <EventCollectorContextProvider {...eventsCollector}>
                                    {children}
                                </EventCollectorContextProvider>
                            </PeregrineContextProvider>
                        </ReduxProvider>
                    </ConfigContextProvider>
                </IntlProvider>
            </ApolloProvider>
        );
    };
    
    window.onload = async () => {
        const root = document.createElement('div');
        document.body.appendChild(root);
    
        ReactDOM.render(
            <Router>
                <AppContext>
                    <App />
                </AppContext>
            </Router>,
            root
        );
    };
    

    The EventCollectorContext exports the React Context which:

    • loads the commerce-events-sdk and commerce-events-collector library,
    • initializes them with a given configuration for Experience Platform and/or ACDS
    • subscribes to all events from Peregrine and forwards them to the events SDK

    You can review the implementation details of the EventCollectorContext here.

Build and deploy the updated AEM project

To make sure the above package installation, code, and config changes are correct, re-build, and deploy the updated AEM Commerce project using the following Maven command: $ mvn clean install -PautoInstallSinglePackage.

Experience Platform setup aep-setup

To receive and store the event data coming from the AEM Commerce pages such as category and product, complete the following steps:

AVAILABILITY
Make sure you are part of the correct Product Profiles under Adobe Experience Platform and Adobe Experience Platform Data Collection. If needed, work with your system administrator to create, update, or assign Product Profiles under the Admin Console.

Create Schema with Commerce field group

To define the structure for commerce event data, you must create an Experience Data Model (XDM) schema. A schema is a set of rules that represent and validate the structure and format of data.

  1. In the browser, navigate to the Adobe Experience Platform product Home page. For example, https://experience.adobe.com/#/@YOUR-ORG-NAME/sname:prod/platform/home.

  2. Locate the Schemas menu in the left navigation section, click the Create Schema button from the top-right section, and select XDM ExperienceEvent.

    AEP Create Schema

  3. Name your schema using the Schema Properties > Display name field and add Field groups by using the Composition > Field groups > Add button.

    AEP Schema Definition

  4. In the Add Field groups dialog, search for Commerce, select the Commerce Details checkbox, and click Add Field groups.

    AEP Schema Definition

TIP
See the Basics of schema composition for more information.

Create Dataset

To store the event data, you must create a Dataset that conforms to the schema definition. A dataset is a storage and management construct for a collection of data, typically a table, that contains a schema (columns) and fields (rows).

  1. In the browser, navigate to the Adobe Experience Platform product Home page. For example, https://experience.adobe.com/#/@YOUR-ORG-NAME/sname:prod/platform/home.

  2. Locate the Datasets menu in the left navigation section and click the Create dataset button from the top-right section.

    AEP Create Datasets

  3. On the new page, select Create dataset from schema card.

    AEP Create Datasets Schema Option

  • On the new page, search and select the schema you created in the previous step, and click the Next button.

    AEP Create Datasets Select Schema

  1. Name your Dataset using the Configure dataset > Name field and click the Finish button.

    AEP Create Datasets Name

TIP
See the Datasets overview for more information.

Create Datastream

Complete the following steps to create a Datastream in the Experience Platform.

  1. In the browser, navigate to the Adobe Experience Platform product Home page. For example, https://experience.adobe.com/#/@YOUR-ORG-NAME/sname:prod/platform/home.

  2. Locate the Datastreams menu in the left navigation section and click the New Datastream button from the top-right section.

    AEP Create Datastreams

  3. Name your Datastream using the Name required field. Under the Event Schema field, select the created schema and click Save.

    AEP Define Datastreams

  4. Open the created Datastream, and click Add Service.

    AEP Datastreams Add Service

  5. Under the Service field, select the Adobe Experience Platform option. Under Event Dataset field, select the dataset name from the previous step and click Save.

    AEP Datastreams Add Service Details

TIP
See the Datastream overview for more information.

Add datastream value into AEM Commerce configuration add-aep-values-to-aem

After completing the above Experience Platform setup, you should have datastreamId in the left rail of the Datastream details and orgId in the top-right corner of the Profile Picture > Account info > User Information modal.

AEP Datastreams ID

  1. In the AEM Commerce project’s ui.frontend module, update the config.js file and specifically the eventsCollector > aep object properties.

  2. Build and deploy the updated AEM Commerce project

Trigger addToCart event and verify data collection event-trigger-verify

The above steps complete the AEM Commerce and Experience Platform setup. You can now trigger an addToCart event and verify data collection using the Snowplow Inspector and dataset Metrics and graphs toggle in the product UI.

To trigger the event, you can use AEM author or the publish service from your local setup. For this example, use AEM author by logging in to your account.

  1. From Sites page, select the My Demo StoreFront > us > en page and click Edit in top action bar.

  2. From the top action bar, click View as Published, then click any preferred category from the storefront’s navigation.

  3. Click any preferred product card in the Product Page, then select color, size to enable the Add to Cart button.

  4. Open the Snowplow Inspector extension from the browser’s extension panel and select Experience Platform Wed SDK in the left rail.

  5. Return to the Product Page and click Add to Cart button. This sends data to the Experience Platform. The Adobe Experience Platform Debugger extension shows the event details.

    AEP Debugger Add-To-Cart Event-Data

  6. Within Experience Platform product UI, navigate to the Datasets > My Demo StoreFront, under the Dataset activity tab. If the Metrics and graphs toggle is enabled, the event-data stats are displayed.

    Experience Platform Dataset Data stats

Implementation Details implementation-details

The CIF Experience Platform Connector is built on top of the Data Connection for Adobe Commerce, which is part of the PWA Studio project.

The PWA Studio project lets you create Progressive Web Application (PWA) storefronts powered by Adobe Commerce or Magento Open Source. The project also contains a component library called Peregrin for adding logic to visual components. The Peregrin library also provides the custom React hooks that are used by CIF Experience Platform Connector to integrate with Experience Platform seamlessly.

Supported Events supported-events

As of now, the following events are supported:

Experience XDM Events:

  1. Add to Cart (AEM)
  2. View Page (AEM)
  3. View Product (AEM)
  4. Search Request sent (AEM)
  5. Search Response received (AEM)

When Peregrine components are reused in the AEM Commerce project:

Experience XDM Events:

  1. Remove from Cart
  2. Open Cart
  3. View Cart
  4. Instant Purchase
  5. Start Checkout
  6. Complete checkout

Profile XDM Events:

  1. Sign in
  2. Create Account
  3. Edit Accoun

Additional Resources additional-resources

For more information, see the following resources:

recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab