Web Angular JS

This document describes how to integrate Personetics Engage client into your Angular layout app.

To understand and test the process of integrating Personetics Widgets, into the bank’s Angular based Application, the customer may initially integrate the sample Personetics code files into their own application. The same process can then be used to replace the sample code with the bank’s custom code provided by Personetics.

Operating Systems

Supported os versions:

14, 15, 16, 17

Deprecation policy:

  • Time frame: Personetics client version 3.9 will support the Angular versions mentioned above for a period of two years from the launch date of the Personetics client version, as long as the operating system provider continues to support these versions.
  • Scope: During this period, support for the Personetics client version includes updates from both Personetics client and the operating system versions.
  • Upgrade implications: In case a customer upgrades their Personetics client version, this may result in changes to the supported operating system versions. Please contact your project manager for further details.

Package Description

The customer is provided an SDK package via sFTP. The package includes the following:

  • personetics-vx.x.x.tgz - Personetics widget Angular node module. This is the only file you need to integrate Personetics into your app.
  • sample-app.zip A simple Angular app example used to demonstrate the integration of, and interaction with the Personetics widget component. We will use mainly the sample-app/src/app/home/home.component.ts

Getting Started

  1. Copy both packages to an accessible directory.
  2. Unzip the sample-app package.

Viewing the Sample App

  1. Copy both packages to an accessible directory.

  2. Unzip the sample-app package.

  3. Open the unzipped sample-app folder in your editor (e.g. VS Code).

  4. In your editor, open a new terminal and navigate to the sample-app folder:
    cd <integration-package-path>/sample-app

  5. Install npm related packages (not related to the Personetics package):
    npm install --legacy-peer-deps

  6. Install the Personetics package:
    npm install <integration-package-path>/personetics-x.x.x.tgz --legacy-peer-deps

  7. After the installation the new “Personetics” folder appears in the node_modules folder and a new dependency appears in the package.json file.

    dependencies: {  
    "personetics": "file:../personetics-[version].tgz", 
    }
    
  8. Run the sample app to view an example of the Personetics widget: npm start. The sample app login page appears.

  1. Click Advanced. Set to Predefined and to Payload, and click Save, in order to view the sample app without requiring a server connection.

  2. Use the Add New Widget button to add new widgets, and use the drop-down to change widgetType for each instance:

Analyze Sample App Code

The Personetics Angular integration sample app is structured around a delegate pattern, which offers a modular and organized way to manage different functionalities. Let's break down the components and their roles in the app:

ComponentDescription
App filesMain container for the entire sample app. It plays a crucial role in managing the routing between different pages or components. By handling the routing logic it ensures that users are directed to the appropriate page based on their interactions. The general app component essentially acts as a coordinator orchestrating the flow of the app.
Login ComponentLocated at sample-app/src/app/login, the Login Component is responsible for managing the login page. Its primary function is to handle user authentication by updating the username (authentication token). Users are prompted to input their credentials, and the Login Component validates these credentials before granting access to the app's features. This component's role is critical for ensuring the security of the app.
Advanced Setting ComponentFound at sample-app/src/app/advanced-settings, the Advanced Setting Component is in charge of managing the advanced settings page. This page enables users to configure global settings that impact the app's behavior and appearance. The component facilitates the interaction between users and the settings, ensuring that changes are saved and applied correctly. This enhances the user experience by providing customizable options.
Home ComponentThe Home Component, located at sample-app/src/app/home, is at the core of the app's functionality. It serves as the central hub for rendering widgets and handling various aspects of the app's behavior. This component has a multifaceted role
Widget RenderingThe Home Component manages the rendering of widgets on the user interface. It ensures that the appropriate widgets are displayed based on the user's interactions and preferences.
Delegate Control FunctionsWithin the Home Component, the delegate control functions are managed. These functions control the flow of the app, delegate tasks to specific components, and manage interactions between components.
Event HandlingEvents triggered by user interactions or other sources are managed within the Home Component. It processes these events, makes decisions based on them, and may trigger changes in widget display, settings, or other app behaviors.
Personetics Widgets and StylesThe Home Component imports and utilizes the widgets and styles provided by Personetics SDK. This integration enables the app to incorporate Personetics-specific features seamlessly into its user interface

Integrate into the Bank’s App

The same procedure is used for integrating the vanilla code, and later the customized product into the bank app.

To integrate the vanilla or customized code into the bank’s app

  1. Import the Personetics widget and style component
  2. Create an event handler function
  3. Call startWidget to open the widget

Add the scripts

Add the the following to the angular.json file:

{
"allowedCommonJsDependencies": [
  "@personetics/assets/personetics/home/js/jquery-3.5.1.min.js",
  "@personetics/assets/personetics/personetics-product/js/personetics-vendors.min.js",
  "@personetics/assets/personetics/personetics-product/js/personetics-api.min.js"
],
"assets": [
  {"glob": "**/*", "input": "./node_modules/personetics/assets/personetics/personetics-product/resources/assets", "output": "./personetics-pkg-assets"},
  {"glob": "**/*", "input": "./node_modules/personetics/assets/personetics/personetics-react-product/assets/personetics-react-pkg-assets", "output": "assets/personetics-react-pkg-assets"},
  {"glob": "**/*", "input": "./node_modules/personetics/assets/personetics/personetics-react-product/modules", "output": "modules"}
],
"scripts": [
  "./node_modules/personetics/assets/personetics/home/js/jquery-3.5.1.min.js",
  "./node_modules/personetics/assets/personetics/personetics-product/js/personetics-vendors.min.js",
  "./node_modules/personetics/assets/personetics/personetics-product/js/personetics-api.min.js",
  "./node_modules/personetics/assets/personetics/personetics-product/js/personetics-widget.min.js",
  "./node_modules/personetics/assets/personetics/personetics-react-product/personetics-vendors.min.js",
  "./node_modules/personetics/assets/personetics/personetics-react-product/personetics-widget.min.js",
  "./node_modules/personetics/assets/personetics/home/js/eventDelegate.js"
 ],
}
{
"assets": [
  {"glob": "**/*", "input": "./node_modules/personetics/assets/personetics/personetics-react-product/assets/personetics-react-pkg-assets", "output": "assets/personetics-react-pkg-assets"},
  {"glob": "**/*", "input": "./node_modules/personetics/assets/personetics/personetics-react-product/modules", "output": "modules"}
],
"scripts": [
  "./node_modules/personetics/assets/personetics/personetics-react-product/personetics-vendors.min.js",
  "./node_modules/personetics/assets/personetics/personetics-react-product/personetics-widget.min.js",
  "./node_modules/personetics/assets/personetics/home/js/eventDelegate.js"
 ],
}

Import Widget and Styles Component

  1. Import the Personetics styles into the bank’s component style file.
    @import "~personetics/assets/personetics/personetics-product/css/personetics.css";
    Example in sample-app/src/app/home/home.component.scss

  2. Import the Personetics component into the app.module.ts file.
    import {PersoneticsComponent} from 'personetics-widget'
    Example in: /sample-app/src/app/app.module.ts

  3. Import the Personetics component in the home home.component.ts .
    import {PersoneticsComponent} from 'personetics-widget'
    Example in: /sample-app/src/app/home/home.component.ts.

  4. Create a reference to the widget component in order to enable using the widget’s public methods.

    export class PersoneticsViewComponent implements OnInit{  
    …  
    @ViewChild(PersoneticsComponent) PersoneticsWidget;  
    …  
    }
    

Create handlePersoneticsEvents

  1. Create a handler function handlePersoneticsEvents. Use the example handlePersoEvents function to implement the interaction logic with the widget.

    private handlePersoEvents(data){  
       switch (data.requestString){  
        case 'sessionEnded' :
           const { widgetSelector } = data.json.requestData;  // Used to identify different widgets
           ... 
        case 'sessionError' :
           const { widgetSelector } = data.json.requestData;  // Used to identify different widgets
           ... 
        case 'navigateToPage' : 
           const { widgetSelector } = data.json.requestData;  // Used to identify different widgets
           ... 
        case 'sendRequestToPServer' :  
           const { widgetSelector } = data.json.requestData;  // Used to identify different widgets
           ...
        case 'sendRequestToEnrichServer' :  
           const { widgetSelector } = data.json.requestData;  // Used to identify different widgets
           ...
        case 'personeticsEvent' :
           const { widgetSelector } = data.json.requestData.data;  // Used to identify different widgets
            switch(data.json.requestData.data.eventType){  
              case "teaserClick":  
              …  
            };  
        }
    }  
    
  2. Use the widget’s handleServerResponse method to inject data received from the personetics server and display relevant content.

    case "sendRequestToPServer": {
      				const { widgetSelector } = data.json.requestData;
      
              this.homeService
                .SendRequestToPServer(
                  pserverUrl,
                  data.json.requestData
                )
                .subscribe(
                  (successResponse) => {
                    self.PersoneticsWidgets[widgetSelector].handleServerResponse(
                      successResponse,
                      data.json.requestId
                    );
                  },
                  (errorResponse) => {
                    console.log("SendRequestToPServer Error: " + errorResponse);
                  }
                );
      break;
    

Start Personetics Widget

To start the Personetics widget

  1. Start the Personetics widget.

     this.PersoneticsWidgets[widgetSelector].StartPersoneticsWidget(widgetConfig);
    
  2. You may start using the Personetics component in the bank’s relevant html file.
    <personetics-widget></personetics-widget>
    Example in sample-app/src/app/home/home.component.html
    Or you can create them dynamically based on numbers of widgets needed:

    private createWidgetContainer(widgetType, widgetIndex) {
      const selectorString = `root-${widgetType}-${widgetIndex}`;
    
      const dynamicComponentFactory =
            this.componentFactoryResolver.resolveComponentFactory(
              PersoneticsComponent
            );
      this.dynamicComponentRef[widgetIndex] =
        this.dynamicComponentContainer.createComponent(dynamicComponentFactory);
      this.dynamicComponentRef[widgetIndex].instance.selectorString =
        selectorString;
    
      this.cdr.detectChanges();
    }
    
    // Dynamically create instances
    Object.entries(filteredWidgetTypes).forEach(([widgetIndex, widgetType]) => {
      const selectorString = `#root-${widgetType}-${widgetIndex}`;
      this.createWidgetContainer(widgetType, widgetIndex);
    }
    
    // Starting a widget
    this.dynamicComponentRef[widgetIndex].instance.StartPersoneticsWidget(
      widgetConfig
    );
    
    

    Note: Refer to the Widget API document for all the required information.

Event Handler Functions

This section lists all the available functions for the creation of the Class Delegate Protocol file. Examples of some implementations are provided in the sample-app/src/app/home/home.component.ts file.

navigateToPage

This function is invoked by Personetics widget to pass the navigation information. The Bank application can use this information to navigate to a different page within or outside the native app. Values can optionally be assigned (function must be included).

case "navigateToPage": {
  const { widgetSelector } = data.json.requestData;
  
  if (data.json && data.json.requestData && data.json.requestData.data)
    var requestData = data.json.requestData.data;
 
   // Retrieve data from request data
  const { payload, navigateTarget, insightId, instanceId, useCaseId } = requestData;
  
  // Update widget's configurations with retrieved data
  this.widgetConfig[widgetIndex].configurations.params = {
    ...this.widgetConfig[widgetIndex].configurations.params,
    insightId,
    instanceId,
    useCaseId,
  };
 
  if (typeof navigateTarget !== "undefined") {
    switch (navigateTarget) {
      case "subscriptions":
        this.widgetsConfig[widgetSelector].configurations.widgetType = PersoneticsComponent.wTypes.SUBSCRIPTION
        this.widgetsConfig[widgetSelector].configurations.params.params = payload
        break;
 
      case "manageBudget":
        this.widgetsConfig[widgetSelector.configurations.widgetType = PersoneticsComponent.wTypes.BUDGET
        this.widgetsConfig[widgetSelector].configurations.params.params = payload
        break;

      case "recap":
        this.widgetsConfig[widgetSelector.configurations.widgetType = PersoneticsComponent.wTypes.RECAP
        this.widgetsConfig[widgetSelector].configurations.params.params = payload
        break;
    }
 
		this.startWidget();
  } else alert(JSON.stringify(data.json.requestData));
 
  break;
}

personeticsEvent

Triggered by events of an incident captured on the web. This is a generic event that triggered by Personetics widget. Value definitions required for specific products.

Example:

Event ‘teaserClick’ is generated when the end-user clicks on a teaser. In this case, the bank should implement (write code) for relevant behaviour, where the default behavior implementation opens the story widget.
For a full list of events, refer to Widget Client API doc, Delegate Callbacks section, widgetEvent, Event Types.

Note: There are various event types. Be sure to check what is the event type and act according to the business use-case.

Case

  case "personeticsEvent": {
   const { widgetSelector } = data.json.requestData.data;
 	 switch (data.json.requestData.data.eventType) {
    case "inboxWidgetStarted": {
      this.widgetsConfig[widgetSelector].configurations = {
        ...this.widgetsConfig[widgetSelector].configurations,
        widgetType: PersoneticsComponent.wTypes.INBOX,
        // Add data from requestData
        params: {
          ...this.widgetConfig[widgetIndex].configurations.params,
          userId:
          this.configurationService.configurationSettings
          .startWidgetConfigurations.configurations.params.userId,
          insightId: data.json.requestData.data.insightId,
          useCaseId: data.json.requestData.data.useCaseId,
        },
      };
 
      this.startWidget();  // See code from previous section
      break;
    }
    case "teaserClick": {
      this.widgetsConfig[widgetSelector].configurations = {
        ...this.widgetsConfig[widgetSelector].configurations,
        widgetType: PersoneticsComponent.wTypes.STORY_WIDGET,
        // Add data from requestData
        params: {
          ...this.widgetConfig[widgetIndex].configurations.params,
          userId:
          this.configurationService.configurationSettings
          .startWidgetConfigurations.configurations.params.userId,
          insightId: data.json.requestData.data.insightId,
          useCaseId: data.json.requestData.data.useCaseId,
        },
      };
 
      this.startWidget();  // See code from previous section
      break;
    }
  }
  break;
}

sendRequestToEnrichServer and sendRequestToPServer

Note: Case for sendRequestToEnrichServer and sendRequestToPServer are the same.

case "sendRequestToPServer":
case "sendRequestToEnrichServer": {
  	const { widgetSelector } = data.json.requestData;
  
    if (data.json.requestData.hasOwnProperty("bankId")) {
        this.configurationService.updateConfigurationSettings({
            bankId: data.json.requestData.bankId,
            initiationMode: data.json.requestData.initiationMode,
        });
    }
    const self = this;
    
    if (data.requestString === "sendRequestToEnrichServer")
        this.widgetsConfig[widgetSelector].pserverUrl =
        this.configurationService.configurationSettings.enrichServerUrl;
    		this.homeService.SendRequestToPServer(
            this.widgetsConfig[widgetSelector].pserverUrl,
            data.json.requestData
        )
        .subscribe(
            (successResponse) => {
                this.dynamicComponentRef[
                  widgetSelector
                ].instance.handleServerResponse(
                  successResponse,
                  data.json.requestId,
                  widgetSelector
                );
            },
            (errorResponse) => {
                console.log("SendRequestToPServer Error: " + errorResponse);
            }
        );

    break;
}

sessionEnded

Personetics sends the event when the session ends. The bank can then use this event info as needed.

 case "sessionEnded": {
   	const { widgetSelector } = data.json.requestData;
    this.widgetsCallStack[widgetSelector].pop();
    const [previousWidget] = this.widgetsCallStack[widgetSelector].slice(-1);
 
    if (previousWidget) {
      this.startWidget(previousWidget, widgetSelector);
    }
 
    break;
 }