Listing Injections

What are listing injection?

Boxalino offers the possibility to inject contents and questions in a list (typically a products listing).

This means that, instead of having (let’s say) a grid of 6x4 products, the grid could be extended to be 7x4 or 8x4 with 4 (or 8) cells occupied by injected contents.

Their position can be configured dynamically and is typically distributed throughout the grid (for example, first content appears in row 2 column 3, second on row 4 column 2, etc.).

Their size can vary spanning over 1 or more columns as well as 1 or more rows (while respecting your grid layout constraints).

This is an important feature for the following reasons:

  1. Users will tend to engage with a list of products much more than elements on top or below it, therefore injecting content inside the list is quite important to get their attention

  2. Users might not be aware of important information (typically communicated with banners) or interesting reads (typically blog entries) which, if injected into a product list, might get their attention much more

  3. Mobile users require much more efforts to select a facet (often, it requires to open a panel, search for the facet name, open it and search for the facet value), by injecting relevant questions inside the list in relevant places, the system can help them filter their list much more conveniently (this function can also be used to gather more profiling information about the user)

How does it work?

First, the injection contents container must be configured as children of the product listing in the narrative.

As here, for example, below the first element indicating what template should be used for each product of the list, two container of contents (banners and blogs) have been added (such container work like any other bx-hits container with their accessor indicating what widget provides the dynamic content).

In addition, the product listing (the same one) must have in its content an “injection” parameter which provides a JSON string configuration for the injection.

In order to set the orange value, put string {{template-injection_listing}} if you don’t have the dynamic expression feature active.

For your testing, you can also simply copy & paste a minified json of your configuration in the injection field, so you don’t have to configure the injection in BigQuery by yourself.

As here, it is typical that the JSON will not be put as a static string in the injection parameter, but instead will be loaded by Boxalino from Google BigQuery. This will be done with a template resource that Boxalino can configure for you.

What is the result?

As a result, the content containers will be removed from the children of the product listing (banner-injection and blog_slider in the first screen-shot) and the products will be returned as normally, but some additional content will be injected throughout the list. As here in the second position, between a first and a second product:

{ "blocks": [ { "blocks": [ { "template":"product", "bx-hit": { "id": "155524", "title": "The title of the product", }, "blocks": [] }, { "template":"blog", "bx-hit": { "id": "blog_123", "title": "The title of the blog" }, "injection": { "position": { "position": "1", "cols": "2", "rows": "1", "type": "fixed", "parameters": [], "segments": [] } }, "blocks": [] }, { "template":"product", "bx-hit": { "id": "155525", "title": "The title of another product", }, "blocks": [] } //... ] } ] }

The injected content will be a block matching the child Layout block of the content container blocks (as usual) and will have an extra “injection” parameter giving additional information about the injected content.

Notably, this injection parameter has a “position” parameter indicating the injected position (e.g.: index 1 here as it is injected before the position 1 (first position being 0)) as well as the size of the injected block in the listing, in the “rows” and “cols” parameters. Here a “cols” of 2 indicate that the content should span over two columns as per this layout:

It is important to take notice that the position and size of the content are provided according to a configuration model which can respect your layout constraints.

So, such an injection would not happen if your mobile layout would bee 2 columns per row in the mobile as it would break the flow (see next section).

Injection configuration model

It is not required to read further if you are only interested to know how to integrate the listing injections and leave the configuration of the injection model to Boxalino which is the typical case. We provide the following information to explain how the full process works, but it will get more complex and you can stop there if you only want to integrate injections in your front-end product listings

As indicated above, while you can define a static stringified JSON in the Narrative parameter “injection” directly, it is not recommended. Instead a better practice is to defined a dynamic expression loading it with a resource template.

The Model has the following parameters

Parameter

Description

Example value

Parameter

Description

Example value

type

configuration model type (currently only ‘standard’)

standard

version

configuration version (currently only 1)

1

sub_version

configuration sub version (currently only 1)

1

layout

constraints about your layout (e.g.: how many cols per device)

 

layout[*].name

key for the layout case (e.g.: for the device)

ua-deviceCategory

layout[*].value

value for the layout case (e.g: for mobile)

Smartphone/Desktop

layout[*].cols

number of columns per row in this device (e.g.: 2 for mobile, 4 for desktop)

2

injection

information about the injections to be made

 

injection.minimum

minimum number of injections (an injection has the number of element defined in the size)

1

injection.maximum

maximum number of injections (an injection has the number of element defined in the size)

1

injection.size

size of an injections (here 4 elements, which means 1 row for the desktop and 2 rows for the mobile in case of example layout[*].cols above)

4

positions

information about which positions should be filled in the listing

 

positions[*].id

unique string identifier of the position

1

positions[*].positions

list of specific positions (which can be different per device for instance)

 

positions[*].positions[*].position

index where the content should be injected

2

positions[*].positions[*].cols

size of the content in columns

1

positions[*].positions[*].rows

size of the content in rows

1

positions[*].positions[*].type

type of position (currently only fixed)

fixed

positions[*].positions[*].parameters

additional parameters (optional)

format: array<struct<name string, array<string>>>

positions[*].positions[*].segments

segments on which this position applies

[{"name": "ua-deviceCategory"
,"value": "Smartphone"}]

positions[*].parameters

additional parameters (optional)

format: array<struct<name string, array<string>>>

content

the content which should be injected

 

content[*].selector_type

selector type to indicate how to recognize which of the content container should be detected (by default detection done by block parameter)

parameter

content[*].selector_name

indicate on which parameter name the content selector should apply (typically selector is done on a template parameter)

template

content[*].selector_value

indicate on which parameter value the content selector should apply (so here we indicate that the selector should take the bloc container template)

blog-container

content[*].type

type of content (so far always container)

container

content[*].position_ids

list of unique position identifiers to be filled with this content source (must match identifiers defined in positions[*].id)

['1','2']

content[*].page_offsets

indicate how much offset should be applied per page (if -1, content is only injected in the first page)

-1

content[*].conditions

advanced conditional logic

see section Advanced Conditions below

content[*].parameters

additional parameters (optional)

format: array<struct<name string, array<string>>>

Example

Here is an example of the configuration model with 3 injected contents:

  1. First banner in position 5 (or 6 on the mobile)

  2. First blog in position 13

  3. Second banner in position 16 (with a cols of 2, so spanning over 2 columns)

{ "type": "standard", "version": "1", "sub_version": "1", "layout": [ { "name": "ua-deviceCategory", "value": "Smartphone", "cols": "2" }, { "name": "ua-deviceCategory", "value": "Desktop", "cols": "4" } ], "injection": { "mininum": "1", "maximum": "1", "size": "4" }, "positions": [ { "id": "0", "positions": [ { "position": "6", "cols": "1", "rows": "1", "type": "fixed", "parameters": [], "segments": [ { "name": "ua-deviceCategory", "value": "Smartphone" } ] }, { "position": "5", "cols": "1", "rows": "1", "type": "fixed", "parameters": [], "segments": [ { "name": "ua-deviceCategory", "value": "Desktop" } ] } ], "parameters": [] }, { "id": "1", "positions": [ { "position": "13", "cols": "1", "rows": "1", "type": "fixed", "parameters": [], "segments": [ { "name": "ua-deviceCategory", "value": "Smartphone" }, { "name": "ua-deviceCategory", "value": "Desktop" } ] } ], "parameters": [] }, { "id": "2", "positions": [ { "position": "16", "cols": "2", "rows": "1", "type": "fixed", "parameters": [], "segments": [ { "name": "ua-deviceCategory", "value": "Smartphone" }, { "name": "ua-deviceCategory", "value": "Desktop" } ] } ], "parameters": [] } ], "content": [ { "selector_type": "parameter", "selector_name": "template", "selector_value": "banner-container", "type": "container", "position_ids": [ "0", "2" ], "page_offset": "-1", "parameters": [] }, { "selector_type": "parameter", "selector_name": "template", "selector_value": "blog-container", "type": "container", "position_ids": [ "1" ], "page_offset": "-1", "parameters": [] } ] }

How to configure the Dynamic Expression & Template Resource

This section is to configure the injection from BigQuery, for your test, we recommend to put the json as a minified configuration manually in the injection parameter (instead of writing {{template-injection_listing}} which will be simpler to manage.

The Dynamic Expression of the product listing Block of the narrative can be configured as a Script → Template Resource variable as here:

The Template Resource should be defined before (here injection_listing) and should come (typically) from a Real-Time Correlation, here are the typical parameters (in Menu : Advanced > Template Resources).

The values to indicate for the Values, type and valuesKey should be confirmed by Boxalino as they depend on the data which is loaded from Google BigQuery, but the values indicated here are the default values and can typically be used.

Injecting Facets

The prior sections indicate how to inject content, but it might also be interesting to inject facets.

In this case, you can reuse the same facet container Layout Block you use for your search and navigation filters, but you need to add one new Facet Layout Block, here is an example:

Then you can set the facet container and new facet Layout containers in your narrative as children of the list container after the product block as you would do for content injection, here is an example:

Finally, you might wnt to add parameters to your facet (for example to have a different label per facet with a question) as follows:

If you follow this pattern to put your main language as a parameter (e.g.: “question”) and sublanguages with _LAN then the system will return the current language automatically in the facet parameters on the main name (so a request in French would here return the facet parameter as “question”: “Quelle couleur…” in case your request language was ‘fr’).

The API response will return in the injected facet block a “bx-facet” parameter with the same structure as the bx-facets you already use for the filters on the left, but only with 1 facet (instead of all of them).

The values which are to be shown to the user has the parameter “show”: true (you can ignore the other ones).

{ "bx-facet": { "field": "brand", "values": [ { "value": "First brand", "hitCount": 18, "show": true, "order": 0 } ...

Advanced Conditions

Listing Conditions can also support advanced real-time conditions (as part of the “content” field) to implement custom behaviors in the listing injections.

The conditions parameter is a list of conditions, each with the following format:

Parameter

Description

Example value

Parameter

Description

Example value

condition.clauses

a list of clauses for the condition to be true or false

 

condition.clauses[*].type

the type of condition, curently only hits-field is supported

hits-field

condition.clauses[*].index

the hit index to consider in the clause

0

condition.clauses[*].field

the name of the hit field to consider in the clause

selected_title, brand, …

condition.claues[*].operator

an operator for the condition

matches exactly

condition.clauses[*].values

the list of value to check

‘null’

condition.clauses[*].andLogic

if the check of the values should be and or if it should be or

false

condition.andLogic

if the check of all the clauses should be any or all

false

condition.trueCommands / falseCommands

a list of commands to execute in case the condition is evaluated as true or false

 

condition.*Commands[*].name

the command name, currently only move-hit and static-hit are supported

move-hit => switch the position of two hits

static-hit => set a static value to the injection instead of a dynamic one

condition.*Commands[*].parameters

the parameters for the commands

the two ‘indexes’ to switch for move-hit

the json stringified value to set in the bx-hit for static-hit

Example #1:

the idea is to detect if the first hit is the drop of the week (promo_6_fuer_5 is not null) and, if so, to switch it with the hit on position 2 and set a static injection bx-hit : {"static": "PROMO_6_FUER_5"}

...   "conditions": [{     "condition": {       "clauses": [{         "type": "hits-field",         "index": "0",         "field": "bq_custom_PROMO_6_FUER_5",         "operator": "matches exactly", "values": ["null"], "andLogic": "false"       }],       "andLogic": "false"     },     "trueCommands": [],     "falseCommands": [{       "name": "move-hit",       "parameters": [{         "name": "indexes",         "values": ["0", "1"]       }]     }, {       "name": "static-hit",       "parameters": [{         "name": "bx-hit",         "values": ["{\"static\": \"PROMO_6_FUER_5\"}"]       }]     }]   }] ...