The ProductViewCapture component

The REST API JSON payload for a View event is as follows, and we will be calling an Event Server Heroku endpoint. The Heroku endpoint format will be https://<appname>.herokuapp.com/event.json?accessKey=$accessKey, where $accessKey is obtained when the application is created via the PredictionIO Event Server app:

      {
"event": "view",
"entityType": "user",
"entityId": "",
"targetEntityType": "item",
"targetEntityId": ""
}

Here, entityId is the userId and targetEntityId is the productId. We know that, for initial training, we have used entityId as u1, u2, u3, and so on, and, similarly, item IDs are i1,i2,i3, and so on. We can keep the Salesforce IDs and train the model with the Salesforce user IDs or Product IDs; however, to keep things simpler, we will use a custom ExternalId field on the user and Product objects.

Let's name this custom field as PredictionIOExternalId__c on user and Product objects.

To convert JSON to Apex, you can use an online utility (https://www.adminbooster.com/tool/json2apex).

This Lightning Component will be placed on the Product Detail page, and whenever a user views the Detail page of the product, we will call the Event Server endpoint to register a View event.

The Apex code to make a callout to the Event Server is as follows:

    public with sharing class ProductViewCaptureController {
/**
* Makes an API call to PredictionIO Event Server To
Capture Product View Event
* @param Id of the Product
* @throws AuraEnabled Exception if something fails
*/
@AuraEnabled
public static void callEventServer(String productId){
if(productId == null){
throw new AuraHandledException('ProductId is missing..');
}
try{
PredictionIOSettings__c pioSettings =
PredictionIOSettings__c.getValues(
'PredictionIOEventServer');
String endPoint =
pioSettings.API_Endpoint__c + '?accessKey=' +
pioSettings.ApplicationID__c;
String pioproductId =
ProductSelector.getProduct(productId).
PredictionIOExternalId__c;
String piouserId =
UserSelector.getCurrentUser().PredictionIOExternalId__c;
ProductViewCaptureModel productviewEvent =
new
ProductViewCaptureModel('view','user',piouserId,
'item',pioproductId);
String requestBody = JSON.serialize(productviewEvent);
HttpUtil http = new HttpUtil();
HttpResponse response =
http.invokePostRequest(endPoint,requestBody);
if(response.getStatusCode() != 201){
throw new
AuraHandledException('Free Dyno is Sleeping
...Start the server');
}
}
catch(exception e){
throw new AuraHandledException(e.getmessage());
}
}
}

The key thing to note here is that we are using the Apex HTTP callout to call the Event Server. The entire code can be viewed at https://github.com/Packtpublishing/Learning-Salesforce-Einstein/tree/master/Chapter4/PIOLightningComponents/src/classes.

Please note that the preceding code is experimental and written for the purpose of demonstrating concepts, and for production purposes, one can modify the code as per business needs.

The frontend code for the Lightning Component will not involve any UI element except an onload function, which invokes server side function with the Product Id. The entire code can be viewed at https://github.com/PacktPublishing/Learning-Salesforce-Einstein/tree/master/Chapter4/PIOLightningComponents/src/aura/ProductViewCapture.

The following component markup is simple and does not involve any complex markups, and, to the end user, it is invisible:

    <aura:component implements=
"flexipage:availableForAllPageTypes,
flexipage:availableForRecordHome,
force:hasRecordId,forceCommunity:availableForAllPageTypes"
access=
"global" controller="ProductViewCaptureController">

<aura:handler name="init" value="{! this }" action="{! c.init
}"/>

<aura:attribute name="recordId" type="String" />
</aura:component>

The controller and helper are as follows:

    ({
init : function(component, event, helper) {
helper.saveViewEvent(component, event);
}
})

The helper code will invoke the Apex method we discussed earlier. Consider the following code:

    ({
/**
* Call apex controller method callEventServer
* @param component,event
* @return void
*/
saveViewEvent : function(component, event) {
var action = component.get("c.callEventServer");
var self = this;
action.setParams({
productId : component.get("v.recordId") ,
});
action.setCallback(this, function(res){
var resState = res.getState();
if (component.isValid() && resState === "SUCCESS") {
var response = res.getReturnValue();
}
else if (component.isValid() && resState === "ERROR") {
self.toast('Error',res.getError()[0].message,
'error','sticky');
}
});
$A.enqueueAction(action);
},
...
})

Observe how we are using a standard attribute to get RecordId, and we can get the ID of the product in the JavaScript function. This is possible when we include the force:hasRecordId

<aura:attribute name="recordId" type="String" />
//JavaScript Code to get the Context ID
productId : component.get("v.recordId")

Once you have the component available in your instance, you can drag the component using the App Builder to the D product page, as shown in the following screenshot:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset