generated from AdobeDocs/dev-site-documentation-template
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #547 from spoorthipujariadobe/cbe_tutorial
code based experiences tutorial
- Loading branch information
Showing
3 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 184 additions & 0 deletions
184
src/pages/edge/adobe-journey-optimizer/code-based/tabs/tutorial.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
<Variant platform="android" function="updatepropositionsforsurfaces" repeat="2"/> | ||
|
||
#### Java | ||
|
||
```java | ||
final Surface surface1 = new Surface("mainActivity#banner"); | ||
final Surface surface2 = new Surface("secondActivity#promotions"); | ||
|
||
final List<Surface> surfaces = new ArrayList<>(); | ||
surfaces.add(surface1); | ||
surfaces.add(surface2); | ||
|
||
// fetch propositions from server and cache in-memory | ||
Messaging.updatePropositionsForSurfaces(surfaces) | ||
``` | ||
|
||
<Variant platform="ios" function="updatepropositionsforsurfaces" repeat="2"/> | ||
|
||
#### Swift | ||
|
||
```swift | ||
let surface1 = Surface("mainActivity#banner") | ||
let surface2 = Surface("secondActivity#promotions") | ||
|
||
/// fetch propositions from server and cache in-memory | ||
Messaging.updatePropositionsForSurfaces([surface1, surface2]) | ||
``` | ||
|
||
<Variant platform="android" function="getpropositionsforsurfaces" repeat="2"/> | ||
|
||
#### Java | ||
|
||
```java | ||
final Surface surface1 = new Surface("mainActivity#banner"); | ||
final Surface surface2 = new Surface("secondActivity#promotions"); | ||
|
||
final List<Surface> surfaces = new ArrayList<>(); | ||
surfaces.add(surface1); | ||
surfaces.add(surface2); | ||
|
||
Messaging.getPropositionsForSurfaces(surfaces, new AdobeCallbackWithError<Map<Surface, List<Proposition>>>() { | ||
@Override | ||
public void fail(final AdobeError adobeError) { | ||
// handle error | ||
} | ||
|
||
@Override | ||
public void call(Map<Surface, List<Proposition>> propositionsMap) { | ||
// get the content for the given surfaces | ||
if (propositionsMap == null || propositionsMap.isEmpty()) { | ||
// bail early if no propositions are found | ||
return; | ||
} | ||
|
||
// read surface1 propositions | ||
List<Proposition> propositionsForSurface1 = propositionsMap.get(surface1); | ||
|
||
// read surface2 propositions | ||
List<Proposition> propositionsForSurface2 = propositionsMap.get(surface2); | ||
} | ||
}); | ||
``` | ||
|
||
<Variant platform="ios" function="getpropositionsforsurfaces" repeat="2"/> | ||
|
||
#### Swift | ||
|
||
```swift | ||
let surface1 = Surface(path: "myView#button") | ||
let surface2 = Surface(path: "myViewAttributes") | ||
|
||
Messaging.getPropositionsForSurfaces([surface1, surface2]) { propositionsDict, error in | ||
guard error == nil else { | ||
/// handle error | ||
return | ||
} | ||
|
||
guard let propositionsDict = propositionsDict, !propositionsDict.isEmpty else { | ||
/// bail early if no propositions are found | ||
return | ||
} | ||
|
||
/// get the content for the given surfaces | ||
if let propositionsForSurface1 = propositionsDict[surface1] { | ||
/// read surface1 propositions | ||
} | ||
|
||
if let propositionsForSurface2 = propositionsDict[surface2] { | ||
/// read surface2 propositions | ||
} | ||
} | ||
``` | ||
|
||
<Variant platform="android" function="using-propositions" repeat="2"/> | ||
|
||
#### Java | ||
|
||
```java | ||
// get the propositions for surface1 | ||
if (propositionsForSurface1 == null || propositionsForSurface1.isEmpty()) { | ||
// bail early if no propositions are found for surface1 | ||
return; | ||
} | ||
|
||
// iterate through items in proposition | ||
for (final PropositionItem propositionItem: propositionsForSurface1.get(0).getItems()) { | ||
if (propositionItem.getSchema() == SchemaType.HTML_CONTENT) { | ||
// retrieve the HTML content | ||
final String htmlContent = propositionItem.getHtmlContent(); | ||
|
||
// use retrieved html content | ||
} | ||
} | ||
``` | ||
|
||
<Variant platform="ios" function="using-propositions" repeat="2"/> | ||
|
||
#### Swift | ||
|
||
```swift | ||
/// get the propositions for surface1 | ||
if let codePropositions: [Proposition] = propositionsDict?[surface1], !codePropositions.isEmpty { | ||
/// iterate through items in proposition | ||
ForEach(codePropositions.first?.items as? [PropositionItem] ?? [], id:\.itemId) { propositionItem in | ||
if propositionItem.schema == .htmlContent { | ||
// retrieve the HTML content | ||
let htmlContent = propositionItem.htmlContent | ||
|
||
// use retrieved html content | ||
} | ||
} | ||
} | ||
``` | ||
|
||
<Variant platform="android" function="track" repeat="2"/> | ||
|
||
#### Java | ||
|
||
```java | ||
// Tracking display of PropositionItem | ||
// use the same propositionItem object that was used to get the content in the previous section | ||
propositionItem.track(MessagingEdgeEventType.DISPLAY); | ||
|
||
// Tracking interaction with PropositionItem | ||
// use the same propositionItem object that was used to get the content in the previous section | ||
propositionItem.track("click", MessagingEdgeEventType.INTERACT, null); | ||
``` | ||
|
||
<Variant platform="ios" function="track" repeat="2"/> | ||
|
||
#### Swift | ||
|
||
```swift | ||
/// Tracking display of PropositionItem | ||
/// use the same propositionItem object that was used to get the content in the previous section | ||
propositionItem.track(withEdgeEventType: MessagingEdgeEventType.display) | ||
|
||
/// Tracking interaction with PropositionItem | ||
/// use the same propositionItem object that was used to get the content in the previous section | ||
propositionItem.track("click", withEdgeEventType: MessagingEdgeEventType.display) | ||
``` | ||
|
||
<Variant platform="android" function="track-with-tokens" repeat="2"/> | ||
|
||
#### Java | ||
|
||
```java | ||
// Tracking interaction with PropositionItem with tokens | ||
// Extract the tokens from the PropositionItem item data | ||
final List<String> tokenList = new ArrayList<>(); | ||
tokenList.add(dataItemToken1); | ||
tokenList.add(dataItemToken2); | ||
propositionItem.track("click", MessagingEdgeEventType.INTERACT, tokenList); | ||
``` | ||
|
||
<Variant platform="ios" function="track-with-tokens" repeat="2"/> | ||
|
||
#### Swift | ||
|
||
```swift | ||
/// Tracking interaction with PropositionItem with tokens | ||
/// Extract the tokens from the PropositionItem item data | ||
propositionItem.track("click", withEdgeEventType: .interact, forTokens: [dataItemToken1, dataItemToken2]) | ||
``` |
120 changes: 120 additions & 0 deletions
120
src/pages/edge/adobe-journey-optimizer/code-based/tutorial.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
--- | ||
title: Code-based experiences implementation tutorial | ||
description: This document describes how to fetch, display and track code-based experiences using the Adobe Journey Optimizer extension. | ||
keywords: | ||
- Adobe Journey Optimizer | ||
- Messaging | ||
- Code-based experiences | ||
- Tutorial | ||
--- | ||
|
||
import Tabs from './tabs/tutorial.md' | ||
|
||
# Code-based experiences implementation tutorial | ||
|
||
This document describes how to fetch, display and track code-based experiences using the Adobe Journey Optimizer extension. | ||
|
||
## Pre-requisites | ||
|
||
[Integrate and register Messaging extension](../index.md#implement-extension-in-mobile-app) in your app. | ||
|
||
## Fetch and cache the code-based content | ||
|
||
To fetch the content for the surfaces configured in Adobe Journey Optimizer campaigns, call the [updatePropositionsForSurfaces](../api-reference.md#updatepropositionsforsurfaces) API . You should batch requesting multiple [Surface](../public-classes/surface.md) URIs in a single API call when possible. The returned code-based experiences are cached in-memory by the Messaging extension and persists through the lifecycle of the app (i.e as long as the app is running). An example of the call is shown below: | ||
|
||
<TabsBlock orientation="horizontal" slots="heading, content" repeat="2"/> | ||
|
||
Android | ||
|
||
<Tabs query="platform=android&function=updatepropositionsforsurfaces"/> | ||
|
||
iOS | ||
|
||
<Tabs query="platform=ios&function=updatepropositionsforsurfaces"/> | ||
|
||
## Retrieve cached propositions | ||
|
||
To retrieve the previously fetched content from the in-memory cache, call the [getPropositionsForSurfaces](../api-reference.md#getpropositionsforsurfaces) API with a list of required surface URIs and a completion handler. The completion handler will be invoked with a list of [Proposition](../public-classes/proposition.md) objects corresponding to the requested surfaces, or `AEPError` object if an error occurs. | ||
|
||
<InlineAlert variant="warning" slots="text"/> | ||
|
||
If a requested surface was not previously cached prior to calling `getPropositionsForSurfaces` (using the `updatePropositionsForSurfaces` API), no propositions will be returned for that surface. | ||
|
||
The following example shows how to retrieve the content for the previously cached surfaces: | ||
|
||
<TabsBlock orientation="horizontal" slots="heading, content" repeat="2"/> | ||
|
||
Android | ||
|
||
<Tabs query="platform=android&function=getpropositionsforsurfaces"/> | ||
|
||
iOS | ||
|
||
<Tabs query="platform=ios&function=getpropositionsforsurfaces"/> | ||
|
||
## Using the retrieved propositions | ||
|
||
The [Proposition](../public-classes/proposition.md) object returned in the completion handler encapsulates the content specified for the corresponding surface, as well as information needed for tracking interactions with the content. Multiple `Proposition` objects can be returned for a single surface based on the number of campaigns configured for it in Adobe Journey Optimizer. Each `Proposition` object in turn can contain multiple items, represented by the [PropositionItem](../public-classes/proposition-item.md) class, based on how the campaign's content is defined. To access the content, iterate through the list of `PropositionItem` present in the returned list of `Proposition`. The `SchemaType` of the `PropositionItem` indicates the type of content it contains and can be used to determine how to render or interpret the returned content. The `PropositionItem` class contains helper functions to access the different types of supported content. | ||
|
||
The following example shows how to iterate through the propositions returned earlier and retrieve the HTML content. Please adapt the solution to suit the needs of your application and use the returned proposition content appropriately. | ||
|
||
<TabsBlock orientation="horizontal" slots="heading, content" repeat="2"/> | ||
|
||
Android | ||
|
||
<Tabs query="platform=android&function=using-propositions"/> | ||
|
||
iOS | ||
|
||
<Tabs query="platform=ios&function=using-propositions"/> | ||
|
||
## Tracking interactions with code-based experiences | ||
|
||
Since the onus of rendering the code-based experience lies with the app developer, you must monitor the desired end user interactions and call the appropriate tracking APIs. To record an interaction with the code-based content, call the [track](../public-classes/proposition-item.md#track) API provided in the `PropositionItem` class. The following code shows two examples of tracking: when the content is displayed to the user and when the user clicks on the content. These examples are for illustrating how to call the track API and not a recommendation on where it should be called. Please examine your app workflow to find the appropriate way to perform tracking. | ||
|
||
<TabsBlock orientation="horizontal" slots="heading, content" repeat="2"/> | ||
|
||
Android | ||
|
||
<Tabs query="platform=android&function=track"/> | ||
|
||
iOS | ||
|
||
<Tabs query="platform=ios&function=track"/> | ||
|
||
### Tracking items from embedded decisions | ||
|
||
When Adobe Journey Optimizer campaigns are created with embedded decisions, the server can respond with one or more items based on the number of items requested in the decision. To track these embedded items, the Adobe Journey Optimizer campaign UI provides `item._trackingToken` attributes. When authoring the campaign's content, you would need to embed the provided token as an HTML data-attribute in case of HTML content or JSON attribute in case on JSON content. The following example campaign shows content with embedded decision, where multiple paragraph tags containing image URLs can be returned. | ||
|
||
```html | ||
<html> | ||
<body> | ||
{{#each decisionPolicy.1234567.items as |item|}} | ||
<ul id={{item._id}} data-item-token="{{item._trackingToken}}"><img src="{{item.heroimage1.sourceURL}}" alt="Winter Sale" width="80%" height="50%"></ul> | ||
{{/each}} | ||
</body> | ||
</html> | ||
``` | ||
|
||
For the above example, the server can return a response with two decision items in the item data within a single `PropositionItem` | ||
|
||
```html | ||
<html> | ||
<body> | ||
<ul id="mockId1" data-item-token="mockToken1"><img src="https://image1.jpeg" alt="Winter Sale" width="80%" height="50%"></ul> | ||
<ul id="mockId2" data-item-token="mockToken2"><img src="https://image2.jpeg" alt="Winter Sale" width="80%" height="50%"></ul> | ||
</body> | ||
</html> | ||
``` | ||
|
||
Since the embedded items are located inside a single PropositionItem's data, the app developer will need to extract the `data-item-token` when tracking the interactions with the item. The token, along with the other tracking information, will need to be passed to the [track](../public-classes/proposition-item.md#track) API provided by the Messaging SDK. If no tracking tokens are supplied, normal tracking events will be sent. If tracking tokens were used during authoring, it will be assumed that all the corresponding embedded items were displayed. The following code shows an example of calling the track API with tokens. | ||
|
||
<TabsBlock orientation="horizontal" slots="heading, content" repeat="2"/> | ||
|
||
Android | ||
|
||
<Tabs query="platform=android&function=track-with-tokens"/> | ||
|
||
iOS | ||
|
||
<Tabs query="platform=ios&function=track-with-tokens"/> |