Skip to main content
Skip table of contents

Admin: Pre- and post-processing plugins

The Plugins section is used to record details of the pre- and post-processing plugins configured at the current RPI installation.

Pre-processing plugins can be used to manipulate visitor profiles prior to a call being made for a Realtime decision content.

A pre-processing plugin is defined as per the following example:

JSON
{
    "Name": "PreProcessing",
    "Factory": {
        "Assembly": "Redpoint.Resonance.Web.Shared",
        "Type": "Redpoint.Resonance.Web.Shared.Plugins.PreDecisionExampleFactory"
    },
    "Type": {
        "Name": "Predecision",
        "ApiContentFilterOperator": "Include",
        "ApiContextFilters": [
            "PrePluginTest"
        ]
    },
    "Settings": [
        {
            "Key": "Param",
            "Value": "Foo"
        }
    ]
}

The value passed in an API call's apiContext property is used to determine whether a pre-processing plugin is to be applied. You can specify multiple comma-delimited values in a list. apiContentFilterOperator is used to Include or Exclude whether a pre-processing plugin is to be invoked.

For example, if a value passed in apiContext when an API call is made matches a value in the web config setting apiContextFilter, and apiContentFilterOperator is set to Include, pre-processing plugin functionality will be called. The functionality would not be called if apiContentFilterOperator was set to Exclude.

Post-processing plugins can be configured to execute after every decision, or after all decisions have been made.

A post-processing plugin that executes after every decision is defined as per the following example:

JSON
{
    "Name": "PostProcessingExample",
    "Factory": {
        "Assembly": "Redpoint.Resonance.Web.Shared",
        "Type": "Redpoint.Resonance.Web.Shared.Plugins.PostDecisionExampleFactory"
    },
    "Settings": [
        {
            "Key": "Prefix",
            "Value": "pre "
        },
        {
            "Key": "Suffix",
            "Value": "post"
        }
    ]
}

A post-processing plugin that executes after all decisions is defined as per the following example:

JSON
{
   "Name": "Smart Asset Result Plugin Example",
   "Factory": {
     "Assembly": "RedPoint.Resonance.Web.Shared",
     "Type": "RedPoint.Resonance.Web.Shared.Plugins.SmartAssetExamplePluginFactory"
   },
   "Type": {
     "Name": "SmartAssetResults",
     "ApiContextFilters": ["apply-plugin"]
   },
   "Settings": [
     {
       "Key": "ParameterName",
       "Value": "MySmartAssetPluginCounter"
     }
   ]
}

Any smart asset result processing plugin must identify itself with a type of "SmartAssetResults".

A plugin consists of two classes:

  • A factory class derived from RedPoint.Resonance.Web.Shared.Plugins.FilterableRealtimePluginFactoryBase

  • A plugin execution class that implements RedPoint.Resonance.Web.Shared.Plugins.ISmartAssetResultsPlugin

The plugin execution method signature looks as follows:

JSON
public List<DecisionResult> 
Execute(string visitorID, WebVisitor visitorDetails,
SmartAssetRequest request, List<DecisionResult> results)

This can be used to both access and manipulate the results and access and manipulate the visitor profile.

For more information, please see the RealtimeContentPlugins configuration setting in the RPI Reference guide.

RPI will look for plugin files in a location defined by the following application setting:

RealtimeAPIConfiguration__AppSettings__PluginAssemblyPath

  • The setting defaults to "/app/plugins".

  • Pre- and post-decision plugins do not form part of the RPI codebase (other than those documented below). They are authored independently using the library versions shipped with RPI.

Out-of-the-box Plugins

RPI Realtime comes with two out the box plugins that can be configured to call an API before and after returning a smart asset result.

The Pre-Decision API Plugin

A pre-decision plugin can be used to update a visitor profile before any decision is made. The pre-decision API plugin will do this by passing information from the visitor profile to an API, via a JSON payload. It will add any information returned from the API call into the visitor’s profile, ready for a decision to be made.

Configuration

The following configuration settings are available

Key

Value

ServiceURL

API endpoint address

UseCachedResult

If true, results of an API call will be stored in the visitor profile. This result will be used instead of making repeat calls to the API for a configured timespan. Default false

ResultParam

The name of the parameter to store the JSON response package. If configured, this value will be used to store the cached result. Optional

CacheExpirySecs

The number of seconds to re-used any cached results. Default 60 seconds

IDParam

The name of the json property that will contain the Visitor ID. Default VisitorID

ParamList

A list of profile parameters or cached attribute values to send as part of the request to the API

PersistResultsSeperately

If true, each property return in the JSON response will added as seperate parameters to the visitor profile. Default false

Example 1

In this example, we use a smart asset that will make a decision based on a custom parameter value in the visitor profile. The custom parameter will come from a value provided by a pre-decision api call. That api call will expect two values sourced from CAL attributes (MaritalStatus & Gender). It will provide an offer code back based on the combination of these values. The decisions will use this offer code to determine the content provided.

The Smart Asset look as follows:

 

image-20240712-145444.png

Appsettings configuration

CODE
"Plugins": [  
  {
    "Name": "Pre-Decision API Plugin Example",
    "Factory": {
      "Assembly": "RedPoint.Resonance.Web.Shared",
      "Type": "RedPoint.Resonance.Web.Shared.Plugins.APIPredecisionPluginFactory"
    },
    "Type": {
      "Name": "Predecision"
    },
    "Settings": [
      {
        "Key": "ServiceURL",
        "Value": "https://localhost:44347/api/v2/cache/plugins/pre-decision"
      },
      {
        "Key": "UseCachedResult",
        "Value": "true"
      },
      {
        "Key": "ResultParam",
        "Value": "pre-dec-plugin"
      },
      {
        "Key": "CacheExpirySecs",
        "Value": "30"
      },
      {
        "Key": "IDParam",
        "Value": "CustomerKey"
      },
      {
        "Key": "ParamList",
        "Values": [
          "Gender",
          "MaritalStatus"
        ]
      },
      {
        "Key": "PersistResultsSeperately",
        "Value": "true"
      }
    ]
  }
]

 

The smart asset result request is configured to perform a CAL lookup to fetch the required attribute values from a database.

The plugin will then send the following payload in an API call to POST https://localhost:44347/api/v2/cache/plugins/pre-decision

CODE
{
	"Gender": "F",
	"MaritalStatus": "S",
	"CustomerKey": "12998"
}

 

The API used in this example then returns,

CODE
{
	"Plugin_Offer_Code": "F_S_3"
}

The plugin will then both cache this result in the profile as a blob in the pre-dec-plugin parameter and store the Plugin_Offer_Code value as a separate parameter

image-20240712-145830.png

 

Finally, the Realtime API will return the Smart Asset result using the Plugin_Offer_Code parameter value.

CODE
{
    "Results": [
        {
            "ContentName": "Plugin Test",
            "ResultID": "d6435c94-9eed-4d6b-b857-815b47fef974",
            "ContentID": "bc546d44-2320-42f5-9bd6-12a198c48484",
            "PublishHistoryID": 3143,
            "Result": "3",
            "ResultContent": "Offer Result C",
            "ResultDescription": "",
            "ResultContentXML": null,
            "ContentFormat": "TEXT",
            "IsCachedContent": true,
            "DefaultKey": "5",
            "DivName": null,
            "ContentPath": "",
            "IsEmptyResult": false,
            "PluginTag": "",
            "PluginTagDefault": "",
            "ContextName": "",
            "SlotName": "",
            "ContextTag": null,
            "VisitorID": "12998",
            "DecisionType": "Rule",
            "ImpressionID": "impression",
            "ChannelExecutionID": null,
            "RPContactID": null,
            "TriggerKey": null,
            "ErrorMessage": null,
            "RuleName": "Plugin Offer Code F_S_3",
            "RuleID": "45224c90-7981-431a-8f4a-cb6a2955e34a"
        }
    ],
    "Visitor": {
        "VisitorID": "12998",
        "DeviceID": "sss",
        "ImpressionID": "impression",
        "IsMasterKey": true,
        "HasAlternativeKey": false,
        "Keys": null,
        "View": null,
        "SessionID": ""
    }
}

 

The Post-Decision API Plugin

The post-decision API takes the result of a smart asset, passes it to an API. The API can perform any requirement to process the decision result and/or update the result and pass that result back as the smart asset response payload.

Configuration

The following configuration settings are available

Key

Value

ServiceURL

API endpoint address

ParamList

A list of profile parameters or cached attribute values to send as part of the request to the API

Example 2

In this example, we will use the same smart asset used in the pre-decision example. The post-decision API will then take the result and change the ResultContent from a TEXT format to a JSON format, and add the Plugin_Offer_Code value to the ResultContent JSON.

Appsettings configuration

CODE
"Plugins": [
  {
    "Name": "Post-Decision API Plugin Example",
    "Factory": {
      "Assembly": "RedPoint.Resonance.Web.Shared",
      "Type": "RedPoint.Resonance.Web.Shared.Plugins.APIPostDecisionPluginFactory"
    },       
    "Settings": [
      {
        "Key": "ServiceURL",
        "Value": "https://localhost:44347/api/v2/cache/plugins/post-decision"
      },
      {
        "Key": "ParamList",
        "Values": [
          "Plugin_Offer_Code"
        ]
      }
    ]
  }
]

 

The smart asset used in Example 1 is now republished using this post decision plugin

 

image-20240712-151943.png

Now, when the result is requested, the post decision API plugin will call a POST on https://localhost:44347/api/v2/cache/plugins/post-decision with the following payload

CODE
{
	"Plugin_Offer_Code": "F_S_3",
	"Result": {
		"ContentName": "Plugin Test",
		"ResultID": "9ff4b722-a7ff-4918-86b2-063bb5016996",
		"ContentID": "bc546d44-2320-42f5-9bd6-12a198c48484",
		"PublishHistoryID": 3142,
		"Result": "3",
		"ResultContent": "Offer Result C",
		"ResultDescription": "",
		"ResultContentXML": null,
		"ContentFormat": "TEXT",
		"IsCachedContent": true,
		"DefaultKey": "5",
		"DivName": null,
		"ContentPath": "",
		"IsEmptyResult": false,
		"PluginTag": "Post-Decision API Plugin Example",
		"PluginTagDefault": "",
		"ContextName": null,
		"SlotName": null,
		"ContextTag": null,
		"VisitorID": null,
		"DecisionType": "Rule",
		"ImpressionID": null,
		"ChannelExecutionID": null,
		"RPContactID": null,
		"TriggerKey": null,
		"ErrorMessage": null,
		"RuleName": "Plugin Offer Code F_S_3",
		"RuleID": "45224c90-7981-431a-8f4a-cb6a2955e34a"
	}
}

The API is then able to manipulate the Result object, and pass it back to the plugin - the response from the external API in this example, looks as follows with the ResultContentand ContentFormatproperty edited:

CODE
{
            "ContentName": "Plugin Test",
            "ResultID": "1a25697c-7a59-4d77-87ba-ae7814598011",
            "ContentID": "bc546d44-2320-42f5-9bd6-12a198c48484",
            "PublishHistoryID": 3149,
            "Result": "3",
            "ResultContent": {
                "SmartAssetResult": "Offer Result C",
                "Plugin_Offer_Code": "F_S_3",
                "Comment": "Converted to JSON by Post Decision API Plugin"
            },
            "ResultDescription": "",
            "ResultContentXML": null,
            "ContentFormat": "JSON",
            "IsCachedContent": true,
            "DefaultKey": "5",
            "DivName": null,
            "ContentPath": "",
            "IsEmptyResult": false,
            "PluginTag": "Post-Decision API Plugin Example",
            "PluginTagDefault": "Meatloaf",
            "ContextName": "",
            "SlotName": "",
            "ContextTag": null,
            "VisitorID": "12998",
            "DecisionType": "Rule",
            "ImpressionID": "impression",
            "ChannelExecutionID": null,
            "RPContactID": null,
            "TriggerKey": null,
            "ErrorMessage": null,
            "RuleName": "Plugin Offer Code F_S_3",
            "RuleID": "45224c90-7981-431a-8f4a-cb6a2955e34a"
        }

This is then returned from the Realtime API as follows

CODE
{
    "Results": [
        {
            "ContentName": "Plugin Test",
            "ResultID": "1a25697c-7a59-4d77-87ba-ae7814598011",
            "ContentID": "bc546d44-2320-42f5-9bd6-12a198c48484",
            "PublishHistoryID": 3149,
            "Result": "3",
            "ResultContent": {
                "SmartAssetResult": "Offer Result C",
                "Plugin_Offer_Code": "F_S_3",
                "Comment": "Converted to JSON by Post Decision API Plugin"
            },
            "ResultDescription": "",
            "ResultContentXML": null,
            "ContentFormat": "JSON",
            "IsCachedContent": true,
            "DefaultKey": "5",
            "DivName": null,
            "ContentPath": "",
            "IsEmptyResult": false,
            "PluginTag": "Post-Decision API Plugin Example",
            "PluginTagDefault": "Meatloaf",
            "ContextName": "",
            "SlotName": "",
            "ContextTag": null,
            "VisitorID": "12998",
            "DecisionType": "Rule",
            "ImpressionID": "impression",
            "ChannelExecutionID": null,
            "RPContactID": null,
            "TriggerKey": null,
            "ErrorMessage": null,
            "RuleName": "Plugin Offer Code F_S_3",
            "RuleID": "45224c90-7981-431a-8f4a-cb6a2955e34a"
        }
    ],
    "Visitor": {
        "VisitorID": "12998",
        "DeviceID": "sss",
        "ImpressionID": "impression",
        "IsMasterKey": true,
        "HasAlternativeKey": false,
        "Keys": null,
        "View": null,
        "SessionID": ""
    }
}
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.