Rendering Widgets
This section describes how widgets are rendered and provides various examples.
Rendering Process
Below are the API commands used per operation.
Operation | Description |
---|---|
Teaser Rendering | Teasers operate with a processed response from the server. The API command can be called by the bank and either provided on “startWidget” as payload or requested by the widget if missing from the initialization. The following API are used, according to the implementation: - getInsights - used to to generate and retrieve insights for the following widgets: carousel, trackersDashboard, hub, singleTeaser, budget related widgets and ACT related widgets - getInboxInsights - used to generate and retrieve insights for 'inbox' widget |
Story Rendering | The story blocks are retrieved using the getInsightDetails API command. The server response is then used to render the blocks. The API command can be called by the bank using either Personetics SDK, or independently by injecting the payload property (as part of the startWidget) into the widget. |
Story rating and feedback | The story widget 'rating' and 'feedback' functionality is implemented using dedicated API calls. - getInsightRating - updateInsightRating - updateInsightFeedback |
Example of subscription-widget rendering of the using startWidget API:
-
Open the widget using a “startWidget” call; widgetType = 'subscription-dashboard', and include all relevant Key Values.
startWidget ({"widgetType":"subscription-dashboard"})
-
Following this call, a pre-defined WebView should be opened by the bank, and the widget’s render should be injected to it.
-
Following this call, a pre-defined WebView should be opened by the bank, and the widget’s render should be injected to it.
-
In some cases, the startWidget may include additional payload parameters. In that case, the startWidget would include an additional “params” parameter:
startWidget ({"widgetType":"subscription-dashboard", "params”: {…}})
-
To display subscription data, the widget sends and API request to the server. The API name is getUserSubscriptions and it should include protocol version. The bank must decide between either options:
- The request can be sent by the widget, after the “startWidget” initialization, through the delegate function of the widget:
Personetics Subscription-Dashboard Widget --> Delegate: sendRequestToEnrichServer (requestHeaders, postParam, requestId) - by the bank application before the “startWidget” and provided as additional payload once “startWidget” is called:
Delegate --> PServer API: handleServerResponse (data, requestId)
- The request can be sent by the widget, after the “startWidget” initialization, through the delegate function of the widget:
-
Following this call, a pre-defined WebView should be opened by the bank, and the widget’s render should be injected to it.
startWidget Examples
This section describes how to use startWidget to render the story-widget and teaser widgets, and provides rendering and response code examples for various layouts.
Inbox Code Examples
Below are inbox widget code examples
JSONObject configurations = new JSONObject();
JSONObject params = new JSONObject();
JSONObject assets = new JSONObject();
JSONObject internationalization = new JSONObject();
JSONObject theme = new JSONObject();
try {
if(getResources().getBoolean(R.bool.is_use_payload)) {
params.put(Personetics.PDB_PAYLOAD, config.get(Personetics.PDB_PAYLOAD));
}
params.put(Personetics.PDB_USER_ID, getResources().getString(R.string.default_user));
configurations.put(Personetics.PDB_WIDGET_TYPE, "inbox");
configurations.put(Personetics.PDB_DEVICE_TYPE, "android");
configurations.put(Personetics.PDB_SELECTOR_STRING, "#root");
configurations.put(Personetics.PDB_PARAMS, params);
if(getResources().getBoolean(R.bool.is_use_remote_assets_mode)) {
assets.put(Personetics.PDB_BASEURL, getString(R.string.remote_assets));
assets.put(Personetics.PDB_USEREMOTEASSETS, true);
}
internationalization.put(Personetics.PDB_LANGUAGE, "en");
theme.put(Personetics.PDB_DARKMODE, false);
config.put(Personetics.PDB_CONFIGURATIONS, configurations);
config.put(Personetics.PDB_ASSETS, assets);
config.put(Personetics.PDB_INTERNATIONALIZATION, internationalization);
config.put(Personetics.PDB_THEME, theme);
} catch (JSONException e) {
e.printStackTrace();
}
return ((MainActivity)getActivity()).getPersonetics().startWidgetWithView(getActivity(), config);
let personeticsInfo = NSMutableDictionary.init()
let personeticsBridge = BankPersoneticsDelegate.init()
let configurations = NSMutableDictionary.init()
let params = NSMutableDictionary.init()
let assets = NSMutableDictionary.init()
let internationalization = NSMutableDictionary.init()
let theme = NSMutableDictionary.init()
guard let constants = NetworkManager.shared.constants else { return }
params.setValue(constants.userName, forKey: Personetics.PDBuserId)
configurations.setObject("inbox", forKey: Personetics.PDBWidgetType as NSCopying)
configurations.setObject("ios", forKey: Personetics.PDBDeviceType as NSCopying)
configurations.setObject("#root", forKey: Personetics.PDBSelectorString as NSCopying)
internationalization.setObject(constants.appLanguage, forKey: Personetics.PDBlanguage as NSCopying)
personeticsBridge.viewCtrl = self
personeticsInfo.setValue(constants.protocolVersion, forKey: Personetics.PDBprotocolVersion)
personeticsInfo.setValue(constants.webViewTag, forKey: Personetics.PDBwebViewTag)
if constants.useRemoteAssets == true {
assets.setObject(true, forKey: Personetics.PDBuseRemoteAssets as NSCopying)
assets.setObject(constants.remoteUrl, forKey: Personetics.PDBbaseUrl as NSCopying)
}
if constants.darkMode == true {
theme.setValue(constants.darkMode, forKey: Personetics.PDBdarkMode)
}
personeticsInfo.setValue(personeticsBridge, forKey: Personetics.PDBpDelegate )
if constants.usePayload {
if let infoPayload = payload {
params.setValue(infoPayload, forKey: Personetics.PDBpayload)
} else {
getPayloadForType(type: "inbox", requestType: "getInboxInsights", navParams: nil)
return
}
}
configurations.setObject(params, forKey: Personetics.PDBparams as NSCopying)
personeticsInfo.setValue(configurations, forKey: Personetics.PDBconfigurations)
personeticsInfo.setValue(assets, forKey: Personetics.PDBassets)
personeticsInfo.setValue(internationalization, forKey: Personetics.PDBinternationalization)
personeticsInfo.setValue(theme, forKey: Personetics.PDBtheme)
let personetics = Personetics.init()
personeticsBridge.personetics = personetics
if let personeticsController = personetics.startWidget(personeticsInfo: personeticsInfo) as? UIViewController {
personeticsController.updateViewConstraints()
self.navigationController?.pushViewController(personeticsController, animated: true)
}
startWidget Carousel Example
Below are examples for the carousel widget type. The examples are identical for all teaser widgets, where the widgetType parameter is set according to the widget type.
personetics.startWidget(
{"configurations": {
"deviceType": "web",
"ctxId": "dashboard",
"params": {
"userId": "B_1012"
},
"selectorString": "#root",
"widgetType": "carousel"
},
"assets": {"useRemoteAssets": true
“baseUrl”: "https://bank-assets.s1.amazonaws.com/clientproduct-assets/assets/"
},
"internationalization": {
"language": "en"
}});
final personeticsInfo_carousel = {
"protocolVersion": "2.6",
"internationalization": {"language" “en”},
"configurations": {
"widgetType": “carousel”,
"selectorString": "#root",
"deviceType": “flutter”,
"ctxid": “dashboard”,
"params": {},
},
'widgetHeight': 260,
'widgetWidth': 320,
};
let personeticsInfo = NSMutableDictionary.init()
let personeticsBridge = BankPersoneticsDelegate.init()
let configurations = NSMutableDictionary.init()
let params = NSMutableDictionary.init()
let assets = NSMutableDictionary.init()
let internationalization = NSMutableDictionary.init()
let theme = NSMutableDictionary.init()
guard let constants = NetworkManager.shared.constants else { return }
params.setValue(constants.userName, forKey: Personetics.PDBuserId)
configurations.setObject("inbox", forKey: Personetics.PDBWidgetType as NSCopying)
configurations.setObject("ios", forKey: Personetics.PDBDeviceType as NSCopying)
configurations.setObject("#root", forKey: Personetics.PDBSelectorString as NSCopying)
internationalization.setObject(constants.appLanguage, forKey: Personetics.PDBlanguage as NSCopying)
personeticsBridge.viewCtrl = self
personeticsInfo.setValue(constants.protocolVersion, forKey: Personetics.PDBprotocolVersion)
personeticsInfo.setValue(constants.webViewTag, forKey: Personetics.PDBwebViewTag)
if constants.useRemoteAssets == true {
assets.setObject(true, forKey: Personetics.PDBuseRemoteAssets as NSCopying)
assets.setObject(constants.remoteUrl, forKey: Personetics.PDBbaseUrl as NSCopying)
}
if constants.darkMode == true {
theme.setValue(constants.darkMode, forKey: Personetics.PDBdarkMode)
}
personeticsInfo.setValue(personeticsBridge, forKey: Personetics.PDBpDelegate )
if constants.usePayload {
if let infoPayload = payload {
params.setValue(infoPayload, forKey: Personetics.PDBpayload)
} else {
getPayloadForType(type: "inbox", requestType: "getInboxInsights", navParams: nil)
return
}
}
configurations.setObject(params, forKey: Personetics.PDBparams as NSCopying)
personeticsInfo.setValue(configurations, forKey: Personetics.PDBconfigurations)
personeticsInfo.setValue(assets, forKey: Personetics.PDBassets)
personeticsInfo.setValue(internationalization, forKey: Personetics.PDBinternationalization)
personeticsInfo.setValue(theme, forKey: Personetics.PDBtheme)
let personetics = Personetics.init()
personeticsBridge.personetics = personetics
if let personeticsController = personetics.startWidget(personeticsInfo: personeticsInfo) as? UIViewController {
personeticsController.updateViewConstraints()
self.navigationController?.pushViewController(personeticsController, animated: true)
}
Note: the ‘selectorString’ example of ‘#root’ corresponds to the sample app example. The relevant path should be defined.
payload Example
Following are payload examples per layout.
Note: For details on 'payload', refer to )[payload Structure](payload-structure.
{
"configurations": {
"deviceType": "web",
"ctxId": "dashboard",
"params": {
"payload": {
"GET_INSIGHTS": {
"ok": true,
"protocolVersion": "2.6",
"requestChannel": "VANILLA_QA",
"requestType": "getInsights",
"requestId": "NLjFSETDjW7-K35x",
"status": "200",
"statusMessage": "ok",
"insights": []],
"numberOfInsights": 8,
"unreadMessages": 4,
"numberOfUnreadInsights": 4
}
},
"userId": "B_1012"
},
"selectorString": "#root",
"widgetType": "inbox"
},
"assets": {
"baseUrl": https://client-vanilla-assets.s3.amazonaws.com/product-react-assets/assets/,
"useRemoteAssets": false
},
"internationalization": {
"language": "en"
},
}
func getPayloadForType(type: String, requestType: String, navParams: NSMutableDictionary?) {
let serverUrl = NetworkManager.shared.getEngageServerUrl()
let requestType = requestType
let requestBodyParams = NSMutableDictionary.init()
guard let constants = NetworkManager.shared.constants else { return }
requestBodyParams.setValue(requestType, forKey: "type")
requestBodyParams.setValue("dashboard", forKey: Personetics.PDBctxId)
requestBodyParams.setValue(constants.protocolVersion, forKey: "protocolVersion")
requestBodyParams.setValue(constants.appLanguage, forKey: "lang")
let requestHeaders = NetworkManager.shared.getOptionalReqHeaders()
NetworkManager.shared.doPostMessage(serverUrl: serverUrl, reqHttpBoday: requestBodyParams,
reqHeaders: requestHeaders, requestType: requestType, onSuccess: { [weak self] result in
if let payload = result as? String {
switch type {
case "story-widget":
self?.startStoryWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "inbox":
self?.startInboxWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "hub":
self?.startHubWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "singleTeaser":
self?.startSingleTeaserWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "trackersDashboard":
self?.startTrackersDashboardWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "carousel":
self?.startCarouselWidget(payload: BankUtility.stringToJsonObject(dataString: payload))
case "manage-budgets":
if let addNavParams = navParams {
self?.startBudgetManageWidget(payload: BankUtility
.stringToJsonObject(dataString: payload), navParams: addNavParams)
} else {
self?.startBudgetManageWidget(payload: BankUtility
.stringToJsonObject(dataString: payload), navParams: nil)
}
case "subscription-dashboard":
if let addNavParams = navParams {
self?.startSubscriptionDashboardWidget(payload: BankUtility
.stringToJsonObject(dataString: payload), navParams: addNavParams)
} else {
self?.startSubscriptionDashboardWidget(payload: BankUtility
.stringToJsonObject(dataString: payload), navParams: nil)
}
case "actOnboarding":
if let addNavParams = navParams{
self?.startOnboardingWidget(payload: BankUtility.stringToJsonObject(dataString: payload), navParams: addNavParams)
}else{
self?.startOnboardingWidget(payload: BankUtility.stringToJsonObject(dataString: payload), navParams:nil)
}
case "actManagement":
if let addNavParams = navParams{
self?.startManagementWidget(payload: BankUtility.stringToJsonObject(dataString: payload), navParams: addNavParams)
}else{
self?.startManagementWidget(payload: BankUtility.stringToJsonObject(dataString: payload), navParams:nil)
}
default:
break
}
} else {
}
}, onError: {result in
print("Get Payload \(requestType) Response ****Failed****: \(String(describing: result)))")
})
}
private View populatePersoneticsPriview() {
JSONObject configurations = new JSONObject();
JSONObject params = new JSONObject();
JSONObject assets = new JSONObject();
JSONObject internationalization = new JSONObject();
JSONObject theme = new JSONObject();
try {
params.put(Personetics.PDB_USER_ID, getResources().getString(R.string.default_user));
configurations.put(Personetics.PDB_WIDGET_TYPE, "inbox");
configurations.put(Personetics.PDB_DEVICE_TYPE, "android");
configurations.put(Personetics.PDB_SELECTOR_STRING, "#root");
if(getResources().getBoolean(R.bool.is_use_remote_assets_mode)) {
assets.put(Personetics.PDB_BASEURL, getString(R.string.remote_assets));
assets.put(Personetics.PDB_USEREMOTEASSETS, true);
}
internationalization.put(Personetics.PDB_LANGUAGE, "en");
theme.put(Personetics.PDB_DARKMODE, false);
if (getResources().getBoolean(R.bool.is_use_payload)){
params.put(Personetics.PDB_PAYLOAD,payload);
}
configurations.put(Personetics.PDB_PARAMS, params);
config.put(Personetics.PDB_CONFIGURATIONS, configurations);
config.put(Personetics.PDB_ASSETS, assets);
config.put(Personetics.PDB_INTERNATIONALIZATION, internationalization);
config.put(Personetics.PDB_THEME, theme);
} catch (JSONException e) {
e.printStackTrace();
}
return ((MainActivity)getActivity()).getPersonetics().startWidgetWithView(getActivity(), config);
}
The payload variable contains:
payload.put("GET_INBOX_INSIGHTS",jsonResponse);
story-widget Example
story-widget code example
{
"protocolVersion": "2.6",
"configurations": {
"params": {
"insightId": "dda4db90-76ba-4598-932d-027760271f26",
"instanceId": "VerifyMailAddress",
},
"widgetType": "story-widget",
"selectorString": "#root",
"deviceType": "flutter"
},
"internationalization": {
"language": "en"
}
}
"userId": "ProgramUser_3", // example for userID
"insightId": "bd165da9-cf04-46da-ad22-1c8844a86454",// example for insightId of a clicked teaser
"instanceId": "ProgramTracker",", // example for instanceId of a clicked teaser
"eventType": "teaserClick",
"lang": "en", //language
"clickedTeaser": <elm> //an element node of the clicked teaser
teaserId": "perso-teaser-template_bd165da9-cf04-46da-ad22-1c8844a86454" //an id attribute of the clicked teaser
}
Code Examples
Following are code examples, for carousel, trackersDashboard, hub, inbox, and manage-budgets. In each layout, the examples apply to all widget types, as defined under widgetType.
final personeticsInfo_carousel = {
"protocolVersion": "2.6",
"internationalization": {"language" “en”},
"configurations": {
"widgetType": “carousel”,
"selectorString": "#root",
"deviceType": “flutter”,
"ctxid": “dashboard”,
"params": {},
},
'widgetHeight': 260,
'widgetWidth': 320,
};
Note: the ‘selectorString’ example of ‘#root’ corresponds to the sample app example. The relevant path should be defined.
Updated 12 months ago