oeCloud Service Personalization Example

There are certain scenarios where we want to mdify the API resopnses based on certain conditions. This guide walks you through the process of creating personalization rules for a Model that will change the response of models on the fly.

What you’ll learn

By the end of this guide you will learn to create a Personalization Rule associated with Product. you will be covering below rules:

  • field Name Replace : Replace field name with Product Name.
  • field Value Replace : Replace field name’s app1 value with mcommerce.
  • Sort : Sort the response values in ascending order of description.
  • mask : Mask/Remove Description from the response.
  • filter : Filter the results based on name.
  • fieldMask : formats and masks some of the characters based on pattern on code in the response.

What you’ll need

To complete this guide, you will need the following -

  • an understanding of what a Model is in the context of Loopback, which is the basis of the oeCloud Framework. You can go through the loopback documentation for the same by clicking here
  • an understanding of Model creation. You can go through the guide for the same.
  • a running NodeJS application built using the oeCloud Framework.
  • a working REST client. You can use the Linux cURL command as a REST client if you have access to a Linux machine or have Git Bash installed on your Windows machine. REST addons for browsers, like Postman for Firefox or Google Chrome also can be used to complete this guide. You can use API explorer also to complete this guide.
  • chrome, mod header plugin in chrome.You can get it here
  • User has to pass scope values from mod header plugin if it mentioned in model.

How to complete this guide

You can start from scratch and complete each step, or you can bypass basic setup steps that are already familiar to you.

To start from the scratch go to Getting Started

First We need to create a model ‘Product’ which should have below schema. To create a model, you can follow the Create a Model with Properties Guide.But briefly, you can POST below JSON Data for Category Model to ModelDefinitions. Request API will be http://localhost:3000/api/ModelDefinitions.

If you have already created Product Model then modify the Model following Manage a Model guide.

{
    "name": "Product",
    "base": "BaseEntity",
    "plural": "Products",
    "properties": {
        "code": {
            "type": "string",
            "required": true
        },
        "name": {
            "type": "string",
            "required": true
        },
        "category": {
            "type": "string"
        },
        "price": {
            "type": "number"
        },
        "offeredSince": {
            "type": "date"
        },
        "active": {
            "type": "boolean"
        },
        "description": {
            "type": "string",
            "required": true
        },
        "tags":{
            "type":"array"
        }
    }
}

Note: strict property of model definition should be false, by default value will be false.

POST the data to Product Model

Now that you’ve created the Product model, Let’s use the below mentioned api and post some data.

http://localhost:3000/api/Product

Request Data:

[
  {
    "code": "c101",
    "name": "app1",
    "description": "mobile app",
    "tags":["javascript","Reactjs"]
  },
  {
    "code": "c102",
    "name": "app2",
    "description": "polymer app",
    "tags":["javascript","polymerjs"]
  },
  {
    "code": "c103",
    "name": "app3",
    "description": "node app",
    "tags":["javascript","nodejs"]
  }
]

Defining Personalization Rules

User can create the personalization rule by POSTing the appropriate PersonalizationRule to below API:

http://localhost:3000/api/PersonalizationRules

Below are the various Rules that can be created to achieve service personalization:

Field Name Replace

The fields or properties in the response Data can be replaced with a value by defining a rule. For example when the below rule is applied it returns all Product model instances with properties ’name’ replaced by Character name.

{
    "modelName": "Product",
    "personalizationRule": {
      "fieldReplace": {
        "name": "Product name"
      }
    },
    "scope": {
      "device": "android"
    }
}

Response

User has to pass scope values from mod header plugin as passed in scope. In this case set device as android in headers.

Note :

If there is any data personalization rules also applied then first data personalization will get applied and then service personalization.


User can get below response on their http://localhost:3000/api/Products

[
  {
    "code": "c101",
    "description": "mobile app",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["javascript","Reactjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false,
    "Product name": "app1"
  },
  {
    "code": "c102",
    "description": "polymer app",
    "id": "5757f48a8ce5bba8489b6322",
    "tags":["javascript","polymerjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "d5c84340-dcfb-409c-b58c-ae9bce3e64d2",
    "_isDeleted": false,
    "Product name": "app2"
  },
  {
    "code": "c103",
    "description": "node app",
    "id": "5757f48a8ce5bba8489b6323",
    "tags":["javascript","nodejs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "c84ac213-4848-4177-9bbd-844fcdf74d01",
    "_isDeleted": false,
    "Product name": "app3"
  }
]

Field Value Replace

User can update the personalization rule using below API endpoint PUT http://localhost:3000/api/PersonalizationRules

The value of a particular property of a model can be replaced by defining a personalization rule for that model. For example when the below rule is applied on Product model, it returns all instances with ’name’ property value replaced by mcommerce for app1.

{
    "modelName": "Product",
    "personalizationRule": {
      "fieldValueReplace": {
        "name": {
                "app1": "mcommerce"
            }
      }
    },
    "scope": {
      "device": "desktop"
    }
  }

Set device as desktop in headers.

Response

User can get below response on their Created model endpoint

[
  {
    "code": "c101",
    "name": "mcommerce",
    "description": "mobile app",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["javascript","Reactjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false
  },
  {
    "code": "c102",
    "name": "app2",
    "description": "polymer app",
    "id": "5757f48a8ce5bba8489b6322",
    "tags":["javascript","polymerjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "d5c84340-dcfb-409c-b58c-ae9bce3e64d2",
    "_isDeleted": false
  },
  {
    "code": "c103",
    "name": "app3",
    "description": "node app",
    "id": "5757f48a8ce5bba8489b6323",
    "tags":["javascript","nodejs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "c84ac213-4848-4177-9bbd-844fcdf74d01",
    "_isDeleted": false
  }
]

FieldValueReplace will also work on properties of type ‘array’. The elements in the value of a particular property of a model can be replaced by defining a personalization rule for that model. For example when the below rule is applied on Product model, it returns all instances with ’tags’ property values replaced with values defined below. All elements for which replace values are defined will be replaced leaving rest of them as it is.

{
    "modelName": "Product",
    "personalizationRule": {
      "fieldValueReplace": {
        "tags": {
                "Reactjs": "react",
                "javascript":"js",
                "polymerjs":"polymer"
            }
      }
    },
    "scope": {
      "device": "laptop"
    }
  }

Set device as laptop in headers.

Response

User can get below response on their Created model endpoint

[
  {
    "code": "c101",
    "name": "mcommerce",
    "description": "mobile app",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["js","react"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false
  },
  {
    "code": "c102",
    "name": "app2",
    "description": "polymer app",
    "id": "5757f48a8ce5bba8489b6322",
    "tags":["js","polymer"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "d5c84340-dcfb-409c-b58c-ae9bce3e64d2",
    "_isDeleted": false
  },
  {
    "code": "c103",
    "name": "app3",
    "description": "node app",
    "id": "5757f48a8ce5bba8489b6323",
    "tags":["js","nodejs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "c84ac213-4848-4177-9bbd-844fcdf74d01",
    "_isDeleted": false
  }
]

Sort

User can update the personalization rule using Personalization endpoint The response data of a model will be sorted based on the sort expression defined in the Personalization rule. For example when the below rule is applied, all the Product instances will be sorted in ascending order of description.

{
    "modelName": "Product",
    "personalizationRule": {
      "sort": {
            "description": "asc"
        }
    },
    "scope": {
      "device": "tab"
    }
  }
  

Set device as tab in headers.

Response

User can get below response on their Created model endpoint

[
  {
    "code": "c101",
    "name": "app1",
    "description": "mobile app",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["javascript","Reactjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false
  },
  {
    "code": "c103",
    "name": "app3",
    "description": "node app",
    "id": "5757f48a8ce5bba8489b6323",
    "tags":["javascript","nodejs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "c84ac213-4848-4177-9bbd-844fcdf74d01",
    "_isDeleted": false
  },
  {
    "code": "c102",
    "name": "app2",
    "description": "polymer app",
    "id": "5757f48a8ce5bba8489b6322",
    "tags":["javascript","polymerjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "d5c84340-dcfb-409c-b58c-ae9bce3e64d2",
    "_isDeleted": false
  }
]

Mask

User can update the personalization rule using Personalization endpoint When some of the fields are to be removed from the response Data based on the context, then a personalization rule can be defined to mask some set of fields from the response data. For example when the below rule is applied, all the Product instances returned in the response data ‘description’ property, will be masked from the response data.

{
    "modelName": "Product",
    "personalizationRule": {
      "mask": {
            "description": true
        }
    },
    "scope": {
      "device": "windows"
    }
  }

Set device as windows in headers.

Response

User can get below response on their Created model endpoint

[
  {
    "code": "c101",
    "name": "app1",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["javascript","Reactjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false
  },
  {
    "code": "c102",
    "name": "app2",
    "id": "5757f48a8ce5bba8489b6322",
    "tags":["javascript","polymerjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "d5c84340-dcfb-409c-b58c-ae9bce3e64d2",
    "_isDeleted": false
  },
  {
    "code": "c103",
    "name": "app3",
    "id": "5757f48a8ce5bba8489b6323",
    "tags":["javascript","nodejs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "c84ac213-4848-4177-9bbd-844fcdf74d01",
    "_isDeleted": false
  }
]

Filter

User can update the personalization rule using Personalization endpoint Response Data can be filtered based on a condition by defining a personalization rule for a model. For example the following rule returns all Product model instances where the name is equal to app.

{
    "modelName": "Product",
    "personalizationRule": {
      "filter": {
        "name": "app1"
      }
    },
    "scope": {
      "device": "mobile"
    }
  }

Set device as mobile in headers.

Response

User can get below response on their Created model endpoint

[
  {
    "code": "c101",
    "name": "app1",
    "description": "mobile app",
    "id": "5757f48a8ce5bba8489b6321",
    "tags":["javascript","Reactjs"],
    "_type": "Product",
    "_createdBy": "upload",
    "_modifiedBy": "upload",
    "_createdOn": "2016-06-08T10:33:46.542Z",
    "_modifiedOn": "2016-06-08T10:33:46.542Z",
    "_version": "870649af-0a7d-4067-9bfe-8dd03b67709e",
    "_isDeleted": false
  }
]  

Field Mask

When some of the fields are to be given in a different format in response and want to mask some of the characters to preserve data, fieldMask personalization rule can be applied.

We will use product model to demonstrate different scenerios of using fieldMask personalization rule.

Defining a fieldMask personalization rule.

parameter Description type example
pattern* Regex pattern used to divide into groups for formatting and masking string ‘([/d]{2})([/w]{3})’
flags used as optional arguments for pattern like g, i etc array of strings [‘g’,‘i’]
maskCharacter character used for masking . default is ‘X’ string ‘x’
format the format in which the output should be given. Default is the source input format string ‘($1)-$2’
mask If given the group will be masked with the given or default character else actual output in specific format(if given) is returned in response array of strings [’$2’,’$3’]

Post data into product model.

Use api POST/Products and post the following data.

{
  "code": "prd9012",
  "name": "OmniTrix",
  "category": "Smart Watch",
  "price": 12500,
  "active": true,
  "description": "An Alien tech watch allows you to transform... nah just a smart watch",
  "tags": ["smartWatch", "digitalWatch","watch"],
  "id":"sw10"
}

Response:

{
  "code": "prd9012",
  "name": "OmniTrix",
  "category": "Smart Watch",
  "price": 12500,
  "active": true,
  "description": "An Alien tech watch allows you to transform... nah just a smart watch",
  "tags": [
    "smartWatch",
    "digitalWatch",
    "watch"
  ],
  "id": "sw10",
  "_type": "Product",
  "_createdBy": "admin",
  "_modifiedBy": "admin",
  "_createdOn": "2017-09-26T06:00:02.113Z",
  "_modifiedOn": "2017-09-26T06:00:02.113Z",
  "_isDeleted": false,
  "_version": "1a8d7e37-8100-4886-9929-2c745be7df77"
}

Now we will see different scenerios of using fieldMask personalization rule.

  1. Applying rule to format code property based on region.

    Post the following personalization rule in personalizationRule model
    ```
    {
     "modelName": "Product",
     "personalizationRule": {
     "fieldMask": {
       "code": {
         "pattern": "([a-z]{3})([0-9]{4})",
          "format": "UK-$2"
         }
       }
     },
     "scope": {
     "region": "uk"
       }
     }
    ```
    
    Set `region` as `uk` in headers and call GET/Products/sw10.
    
    **Response**
    ```
    {
     "code": "UK-9012",
     "name": "OmniTrix",
     "category": "Smart Watch",
     "price": 12500,
     "active": true,
     "description": "An Alien tech watch allows you to transform... nah just a smart watch",
     "tags": [
       "smartWatch",
       "digitalWatch",
       "watch"
     ],
     "id": "sw10",
     "_type": "Product",
     "_createdBy": "admin",
     "_modifiedBy": "admin",
     "_createdOn": "2017-09-26T06:57:49.819Z",
     "_modifiedOn": "2017-09-26T06:57:49.819Z",
     "_isDeleted": false,
     "_version": "f263a3e1-7532-4c9f-87d9-beaceae1eeaa"
    

    } ```

    **NOTE** : The `code` property in the response is in the format defined in the personalization rule.
    
  2. Applying rule to format and mask first 2 numbers of code property based on region.

    Post the following personalization rule in personalizationRule model
    ```
    {
     "modelName": "Product",
     "personalizationRule": {
     "fieldMask": {
       "code": {
         "pattern": "([a-z]{3})([0-9]{2})([0-9]{2})",
         "format": "US-$2$3",
         "mask":["$2"]
         }
       }
     },
     "scope": {
     "region": "us"
       }
     }
    ```
    
    Set `region` as `us` in headers and call GET/Products/sw10
    
    **Response**
    ```
    {
     "code": "US-XX12",
     "name": "OmniTrix",
     "category": "Smart Watch",
     "price": 12500,
     "active": true,
     "description": "An Alien tech watch allows you to transform... nah just a smart watch",
     "tags": [
       "smartWatch",
       "digitalWatch",
       "watch"
     ],
     "id": "sw10",
     "_type": "Product",
     "_createdBy": "admin",
     "_modifiedBy": "admin",
     "_createdOn": "2017-09-26T06:57:49.819Z",
     "_modifiedOn": "2017-09-26T06:57:49.819Z",
     "_isDeleted": false,
     "_version": "f263a3e1-7532-4c9f-87d9-beaceae1eeaa"
    

    } ``` NOTE : The response is in the format specified in personalization for region us and first 2 numbers are masked with X(default value).

  3. Applying rule to format and mask first 2 numbers of code property with specific character based on region.

    Post the following personalization rule in personalizationRule model
    ```
    {
     "modelName": "Product",
     "personalizationRule": {
     "fieldMask": {
       "code": {
         "pattern": "([a-z]{3})([0-9]{2})([0-9]{2})",
         "format": "CA $2$3",
         "mask":["$2"],
         "maskCharacter":"*"
         }
       }
     },
     "scope": {
     "region": "ca"
       }
     }
    ```
    
    Set `region` as `ca` in headers and call GET/Products/sw10
    
    **Response**
    ```
    {
     "code": "CA **12",
     "name": "OmniTrix",
     "category": "Smart Watch",
     "price": 12500,
     "active": true,
     "description": "An Alien tech watch allows you to transform... nah just a smart watch",
     "tags": [
       "smartWatch",
       "digitalWatch",
       "watch"
     ],
     "id": "sw10",
     "_type": "Product",
     "_createdBy": "admin",
     "_modifiedBy": "admin",
     "_createdOn": "2017-09-26T06:57:49.819Z",
     "_modifiedOn": "2017-09-26T06:57:49.819Z",
     "_isDeleted": false,
     "_version": "f263a3e1-7532-4c9f-87d9-beaceae1eeaa"
    

    } ``` NOTE : The response is in the format specified in personalization for region ca and first 2 numbers are masked with *(given in personalization rule).

  4. Applying rule to mask first 2 numbers of code property with specific character based on region(No formatting of property).

    Post the following personalization rule in personalizationRule model
    ```
    {
     "modelName": "Product",
     "personalizationRule": {
     "fieldMask": {
       "code": {
         "pattern": "([a-z]{3})([0-9]{2})([0-9]{2})",
         "mask":["$2"],
         "maskCharacter":"*"
         }
       }
     },
     "scope": {
     "region": "mx"
       }
     }
    ```
    
    Set `region` as `mx` in headers and call GET/Products/sw10
    
    **Response**
    ```
    {
     "code": "prd**12",
     "name": "OmniTrix",
     "category": "Smart Watch",
     "price": 12500,
     "active": true,
     "description": "An Alien tech watch allows you to transform... nah just a smart watch",
     "tags": [
       "smartWatch",
       "digitalWatch",
       "watch"
     ],
     "id": "sw10",
     "_type": "Product",
     "_createdBy": "admin",
     "_modifiedBy": "admin",
     "_createdOn": "2017-09-26T06:57:49.819Z",
     "_modifiedOn": "2017-09-26T06:57:49.819Z",
     "_isDeleted": false,
     "_version": "f263a3e1-7532-4c9f-87d9-beaceae1eeaa"
    

    } ``` NOTE : The response has first 2 numbers masked with *(given in personalization rule).

  5. Applying multiple rule to mask first 2 numbers of code property with specific character based on region(No formatting of property).

    Post the following personalization rule in personalizationRule model
    ```
    {
     "modelName": "Product",
     "personalizationRule": {
     "fieldMask": {
       "code": {
         "pattern": "([a-z]{3})([0-9]{2})([0-9]{2})",
         "mask":["$2"],
         "maskCharacter":"*",
         "format":"IND-$2$3"
         },
       "id": {
         "pattern": "([a-z]{2})([0-9]{2})",
         "format":"$1"
         }
       }
     },
     "scope": {
     "region": "in"
       }
     }
    ```
    
    Set `region` as `in` in headers and call GET/Products/sw10
    
    **Response**
    ```
    {
     "code": "IND-**12",
     "name": "OmniTrix",
     "category": "Smart Watch",
     "price": "INR 12500",
     "active": true,
     "description": "An Alien tech watch allows you to transform... nah just a smart watch",
     "tags": [
       "smartWatch",
       "digitalWatch",
       "watch"
     ],
     "id": "sw",
     "_type": "Product",
     "_createdBy": "admin",
     "_modifiedBy": "admin",
     "_createdOn": "2017-09-26T06:57:49.819Z",
     "_modifiedOn": "2017-09-26T06:57:49.819Z",
     "_isDeleted": false,
     "_version": "f263a3e1-7532-4c9f-87d9-beaceae1eeaa"
    

    } ``` NOTE : The response has both the rules applied on response.

Summary

Congratulations! You’ve just created a service-personalization example using oeCloud Framework.