Plugins

Home / Plugins
Consent
Manage choices on (cookie) consent across pages and domains

The Consent API Plugin allows managing user consent preferences regarding cookies (referred to as “consent level”) over a DimML implementation. The Consent API Plugin allows for synchronizing consent over multiple domains. The Consent API Plugin ensures that the given consent level is enforced within the DimML implementation (i.e. when a user gives no consent for analytics, no data can be collected through DimML).

Parameters

  • uid (optional) – An identifier to describe the consent plugin. This can be used for synchronizing consent over multiple domains.
  • consentVersion (optional, default 0) – The version of the consent popup. This can be used to invalidate previously given consent levels when the terms and conditions change.
  • callback (optional) – The function that will be called once the consent API is loaded. The function call takes place in a try/catch statement.
  • lifetime – (optional, default 30): Cookie lifetime in days
  • proofFlow (optional) – Parameter to define name for the flow that can be used for proof flow.
  • urlFlow (optional) – Name for the flow that captures what URLs are being requested. Flow consists of tuples like {url, level}.

Body

The Consent API Plugin does not allow for definition of a plugin body

Output effect

In web browser
The Consent API plugin exposes one object (`dimml.consent`) to the client. This object has two methods.

  • dimml.consent.set(choice) – Sets the user consent level with the value of the *choice* parameter. The value of *choice* has to be a positive integer greater than 0.- – 0: Reserved for testing purposes,
    – 1: Minimum Consent level (i.e. Consent for functional cookies only),
    – 2 and higher: Custom consent levels (e.g. 2 – all cookies, or 2 – analytics 3 – marketing).
  • dimml.consent.get() – Returns an integer corresponding to the level of consent that has been given. Values returned will be either -1 or 1 and higher integers.

In web browser
The consent API plugin exposes two flows. One (urlFlow) that can be used for basic analytics on URLs based on server side data collection and one (proofFlow) that can be used for collecting the consent levels that people consent to.

  • Proof flow – Every time visitor makes a choice on what consent he/she gives, a tuple will be entered in the proof flow. The tuples consist of three fields:uid – The value to identify the Consent API implementation for which consent is given,
    level: The level that a visitor consents to,
    url: The url at which consent is given,
    ip: Contains the ip of the visitor.
  • URL Flow – Every time the consent plugin is loaded a tuple is entered in the url flow. The tuples consist of one key:uid – The UID that loads the consent plugin,
    url – The url where the consent plugin is loaded,
    level – The level of the given consent level.

The Consent plugin does not provide new DimML language constructs.

Additional Remarks
– For browser that have Do Not Track enabled, a first party cookie will be set with value 1 for `choice` since this mode is considered to be an implicit expression of non-consent by the user.
– If cookies (first and third party) are not supported through browser settings, this will be interpreted as an implicit consent of the lowest level. This choice will not show up in the proof flow. If only third party cookies are not accepted, the multi-domain consent will not be stored.
– The consent status is managed with browser cookies. Since this type of cookies is not shared among browsers, a user has to make a choice for each browser separately.
– Changes in given consent are not actively pushed to the client once O2MC Consent is loaded. In a situation where a client changes the consent level, the page code is within that pageview responsible for updating the consent status. Similarly, consent status will not be pushed to other tabs where the same page is opened.

Example

concept Global{
	match '*'

	flow (proof)
	  => debug

	flow (url)
	  => debug

	plugin consent[
		uid = '1',
		consentVersion = '1',
		callback = `websitenamespace.consentManager.init()`,
		lifetime = '31',
		proofFlow = 'proof',
		urlFlow = 'url'
	]

	plugin debug
}
Debug
Allows the use of in browser feedback of the current state of an DimML application

The debug plugin allows the providing run time feedback on the current fields and their values. Any use of the debug flow element allows the feedback of the state at that time. Also any errors when compiling or executing the DimML code are provide in the browser. The information is share in the console log where the same concept is used as the one where the debug statement is used or the error occurs.

Parameters
None

Body

The Debug Plugin does not allow for definition of a plugin body

Output effect
Every use of the debug element for each data tuple results in the execution of a console log function contain the fields and their values. For that purpose the matched concept needs to be triggered by the browser. Note that the console flow element allows the use of server side data evaluation and debugging.

Example

concept Global{
	match '*'

	val url = `document.location.href`

	flow
	=> debug
	=> code[view = `'1'`]
	=> debug
	=> code[done = `'1'`]

	plugin debug
}
Input
Allows the use files as source of data of an DimML application

The input plugin allows the use of files as a basis for processing data. At this time only the CSV option is available for the input plugin. Every line in the file will be translated into a seperate event where each of the columns are used as fields of the input tuple. Since the files are translated into event immediately, files with a large number of lines of code could flood the output sources. Therefore it is possible to the rate at which the event are send to the flows. By default no more than 100 rows per second will be processed.

Parameters
List of string – As input the columns of the file. The names are used as fields

$options constant – Input rate: number of events per seconds

Body

The Input Plugin does not allow for definition of a plugin body

Output effect
Every line of the file will be translated into a separate event to the unnamed flow of the DimML concept. The columns of each line are translated into fields. All unnamed flows will be called immediately in parallel for each of the events in parallel; no sequence can be counted upon.

Example

concept Input {
  match '*'

  plugin input:csv['field1','field2']

  flow
    => buffer:aggregate['1s', count = 'count field1']
    => console

  const $options = `{inputRate: 500}`
}
To actually send the files to the DimML application the file has to be send using POST. The destination URL should be http://dynamic.dimml.io/input and the content type text/csv (for the current CSV transformation). A referrer also needs to be added such that a match is made with the concept containing the input plugin. The referrer can also contain a link to a specific environment, as is the case for web pages. For example if a file example.com.dimml exisits where a concept is made for the file processing which uses *csvinput* as match rule, the following curl command sends the local data.csv file to the correct concept in the plem environment
curl -H "Content-Type: text/csv" -i -X POST --data-binary @data.csv --referer http://www.example.com/csvinput/other?dimml=plem http://dynamic.dimml.io/input
As with matching for web pages, the fact that the match is not exact (but only a substring) is fine. It is recommended to always use a non existing folder/substring in the concept for the input plugin. For instance using the asterix as match rule will result also in other dimml events, such as web page loads, to be processed as if it is a CSV file. An additionally safety is to check if the parsing of each row is correct, which can be checked if the last column exists. This would result in the following code:
concept Input {
  match '*csvinput*'

  plugin input:csv['field1','field2','field3','field4']

  flow
    => select[`field4 != null`@groovy] 
    => buffer:aggregate['1s', count = 'count field1']
    => console

  const $options = `{inputRate: 500}`
}

concept Global {
  match '*'

  ..
}
Output
Allows the use of server side data in output to the input source

The output plugin allows the use of server side data inside an instruction back into the original source of an event. Code for the fields in the source (vals) is executed before server side processing takes place and does not provide a way to receive data afterwards. At this time the output plugin is only available for web pages triggering a request to DimML by the SLOC. Therefore the code block as body is currently only Javascript. In the execution of that block, data processed server side by a DimML application is available.

Parameters
Flow name – Flow name of the flow that executes server side and provides input to the output plugin

Body

Source code for the channel triggering the event

Output effect
With the use of the out code element all fields and their values at that time are collected and the output plugin is triggered. The fields will be available as local variables in the body of the plugin. After the flow has executed completely, the body will be send back to the source and executed there.

Example

concept Global {
    match '*'

    val url = `window.location.href`
    val SessionId = `sessionStorage.dimmlcid=sessionStorage.dimmlcid||guid()`

    flow(in)
    => session['SessionId',
        PagePath = `(session.pagepath=(session.pagepath?:[]))<<url`@groovy]   
    //The out element is necessary for the output plugin to work!
    => out

    plugin debug

    plugin output[flowName = 'in'] `
        console.log('data in the output plugin:'+PagePath);
    `
}
Request
Makes data from the Request header available in the data tuple

The request plugin makes headers and other properties of the request available as fields in the data tuple

Parameters

  • List of field assignments – A list of field definitions, where the fields are added to the data tuple based on data in the code block. All properties, like headers, are available as object in the code block.

Body (only for rest)

  • None

Output effect
All field assignments are executed and the fields are available with their new values

Example

@groovy

concept GetAllHeaders {
  match 'headers'

  request[allheaders = `headers`]

  flow
  => console
}

concept Test {
  match '*'
  request[ref = `headers.referer`]

  flow
  => console
}
Rest
Creates a REST API which can be accessed from external sources

The rest plugin creates a REST API and allows the definition of endpoints and matching concepts. The plugin is used both in a high level concept as well as in the specific concepts that the high level concept points to. In the specific concepts the name of the plugin is rest:json, indicating that the data is processed in JSON format. Currently no other formatting options are available.

The rest plugin facilitates the HTTP methods GET, POST, PUT and DELETE. Apart from pointing a specific URI to a DimML concept, parameters can also be captured from the URI and made available as field in the data tuple. The out flow element is used to send the current data tuple as response. Additionally all query parameters of the URI are available as fields in the data tuple.

Parameters (only for rest:json)

  • flowName (string) – Name of the flow to execute after the REST API end point is called
  • omitList (string) – Value true or false indicating if the data tuple should be provided as a list or not. If set to false, the result would be [“user”:”Peter”,”age”:”32″], if set to true, the result is “user”:”Peter”,”age”:”32″.
  • bodyField (string) – When using POST as HTTP Method, data can not only be provided as key value pairs in the URI, but also as a specific object. If this is the case, the bodyfield parameter defines the field name in the data tuple that can be used to access the data object.

Body (only for rest)

  • Rest API definition – A string containing the REST API definition. Each rows defines an end point by the HTTP method, URI (possibly containing fields to capture from the URI)

Output effect
Every call to the REST API will result in a event being processed according to the URI end point that is called. The data tuple that is set at the moment the out flow element is executed, is provided as response.

Example

@groovy

concept API {
  match '*restapi*'

  rest '
    GET  /user     => ListUsers
    POST /user     => AddUser
    GET  /user/:id => GetUser
    PUT  /user/:id => UpdateUser
         *         => Error
  '
}

concept ListUsers extends JSON {
  flow(api_call) 
  => code[conceptName = `'ListUsers'`]
  => filter['conceptName']
  => out
}

concept AddUser extends JSON {
  flow(api_call) 
  => code[conceptName = `'AddUser'`]
  => filter['conceptName']
  => out
}

concept GetUser extends JSON {
  flow(api_call) 
  => code[conceptName = `'GetUser'`]
  => filter['conceptName','id']
  => out
}

concept UpdateUser extends JSON {
  flow(api_call) 
  => code[conceptName = `'UpdateUser'`]
  => filter['conceptName','id']
  => out
}

concept Error extends JSON {
  flow(api_call)
  => code[conceptName = `'Error'`]
  => filter['conceptName']
  => out
}

concept JSON {
  rest:json[omitList = 'true', flowName = 'api_call', bodyField = 'body']

}
To actually call this API, the following CURL commando can be executed. The referrer should contain the top level private domain of the DimML file as well as other substring defined in the match rule for the REST API top level concept. Additionally the REST API URI should be placed after the dynamic.dimml.io URL.

curl -H "Content-Type: text/csv" -i --referer "http://www.yourdomain.com/restapi?dimml=yourenvironment" dynamic.dimml.io/ListUsers
Script
Execute client side Javascript code

The Script plugin makes sure that a piece of Javascript code is executed whenever the concept is matched. The difference with executing Javascript code in the Pre Match is that the Pre Match code is run before concept matching takes place and therefore the Pre Match Javascript code is always executed. The script plugin has a code block as body which will always be executed as client side Javascript.

The script plugin is executed in parallel to the client side Javascript code in the val/field definitions. Therefore no data can be share accross these two options for executing Javascript code.

Note that the output plugin is executed after the execution of all flows and not when the concept is matched. The output plugin can be used to execute Javascript code, using data processed server side by a flow.

Example

concept Global {
  match '*'

  plugin script `
    console.log('the script plugin executed this code')
  `
}
Validator
Validate the data correctness on individual fields following user defined rules

The O2MC Platform Validator Plugin allows users to validate arbitrary data input following user-defined rules. These rules are defined by extending the indivual fields at the start by extending the val statements. Validation on fields can occur based on fixed values, regular expressions and code (resulting in a boolean result). For each individual field validation an event is triggered in the validation flow. As a result a single event with 5 fields, could lead to 5 validation events handled by the validation flow.

Parameters

  • flowName (optional, default: ‘validate’) – The name of the flow containing the output of the Validator Plugin.

Body

When a body is specified, the validator plugin no longer collects data using the standard collection mechanism. The body is interpreted as Javascript that can use an injected function named ‘validate’ to send a JSON object that requires validation. This separates the code that collects data from the validator plugin and is mainly used when validating analytics and marketing pixels.

**NOTE:** In previous versions of the validator plugin collecting (additional) values required the plugin body to return a JSON object that includes these values. This is now achieved through the same mechanism as normal data collection: the *val* statement. Values are collected as they normally would; you should no longer use ‘= null'; the JSON object to validate (as described in the previous paragraph) is available as the variable ‘data’.A validation rule that uses data collected through the body of the validator plugin would look like this:

val pageName[validation = 'home'] = `data.pageName`

Output effect

In web browser
The validator plugin does not expose any new functionality within the client’s browser.

Server side

The validator plugin adds three language constructs to the DimML language. A full example of a validation rule with all supported functionality is as follows:

val pageName[
  validation = `validatePagename(value)`,
  validationLabel = 'correct-pagename',
  validationMessage = 'something went wrong at :url'
] = `data.pageName`
  • validation – The validation rule. The rule can be defined as a string, as a regex or as a function literal. If the rule is a string, exact string matching will be performed. If the rule is a regex the variable is checked for the presence of a matching pattern. A code literal should yield an expression (written in a server-side language) that uses the ‘value’ argument to return either the boolean value ‘true’ (if validation was successful) or any other value which will be interpreted as ‘false’. In case the other value is a string, it is used instead of the ‘validationMessage’.
  • validationLabel (optional) – A label to be used for data collection. This label will be incorporated in the tuples in the data flow.
  • validationMessage (optional) – A message that can be used for debugging. The message can be enriched with DimML variables for extra information (e.g. *’Error occurred on :url’*).

The Validator Plugin implements a flow that can be named using the *flowName* parameter. The flow contains tuples with a tuple per validation rule and per tuple the label of the validation rule, the name of the variable, the result of the validation rule and an optional validation message. The implementation in the example would give the following output if the validation rule would not hold:

{validation: false, validationMessage: 'pagename at http://example.com/index.html is not home', validationLabel: 'correct-pagename', validationName: 'pageName'}

If the validation rule would hold the flow would contain the following tuple:

{validation: true, validationLabel: 'correct-pagename', validationName: 'pageName'}

Example

concept Global {
 val pageName[
 validation = `validatePagename(value)`,
 validationLabel = 'correct-pagename', 
 validationMessage = 'something went wrong at :url'
 ] = `data.pageName`

 val url = `location`

 def validatePagename = {pageName => `
 if (pageName == 'home')
 return true;
 else
 return "pagename at :url is not home"; 
 `}

 flow (validate)
 => debug

 plugin validator [flowName = 'validate'] `captureSC(validate)`

 def captureSC = {validate => `
 validate({pageName: 'not home'});
 `}

 plugin debug
}