Push Notifications

General

The Push Notifications feature is implemented via common standards and technologies. Users can decide per section or entry if they want to receive notifications on creation or updates. As an administrator, you can decide the style and the content of the notifications.

The notifications are per definition always opt-in: The user has to allow notifications in their browser.

Portrait decides between the two following notification modes:

Single Entry Notification

Will get triggered when either:

  • A subscribed entry has been updated

  • A subscribed section has been updated and only one entry was changed

 

Bildschirmfoto 2024-03-01 um 11.55.21-20240301-105536.jpeg
Example Single Entry Notification on iOS 17.3

Section Notification

Will get triggered when:

  • A subscribed section has been updated and the sum of updated and created entries is higher than 1

 

Bildschirmfoto 2024-03-01 um 12.07.17-20240301-110755.jpeg

Requirements

This feature works with Portrait 6.5.x onwards and does not function in combination with the public mode.

Usage

To receive push notifications, users can subscribe to entries or entire sections. Each subscription is valid for the current device the user is using. In addition, the user has to allow push notifications via their browser as well as on their operating system.

Users are too often asked for permissions on the web. Visit a news website nowadays, and you will be prompted to opt-in for notifications. This leads to the habit, that users just click on “decline” without realizing what is going on. This is doomed to not work, and should be considered a bad practice by the site providers.

However, Portrait will only ask for permission to send notifications the first time, you click on subscribe. This should reduce friction, and engage in a better way.

Read more about Using Push Notifications in the user manual section.

Anatomy of a push notification

Before we dig into the configuration of push notifications, we take a look at a real world example for a notification (based on the iOS platform).

This example is based on the expense management app:

Everything marked green or red can be changed.

The app icon (marked green) and the app name “Spesen” (marked green, part of the title) - is a global setting and based on your App config: General settings

Title (“Benachrichtigung”) and body (“Kaffee kaffeemik - 15,50 (Dominik Rainer) aktualisiert”) is a setting per configuration - see below.

As you might have noticed, the word “von” (in English: “from”) is always part of the title on iOS. Firstly, that will look different on other platforms like Android or Chrome Dekstop.

Secondly, this can make up weird confusing texts, so please check this, before you ship your app.

Examples:

Spesenverwaltung - Spesen von Spesen
Neuer Eintrag von Spesen
Benachrichtigung von Spesen

To summarize: If you want to be grammatically correct, your freedom in the title is limited - shift relevant content to the body instead.

App Configuration

In the application YML file, check that you defined the basic setup of the push notifications service. Newer setups of Portrait ship already with these settings.

application: push: enabled: true push_service_subject: 'mailto:yourEmail@domain.at' urgency: normal

The following settings are possible:

Name

Type

Description

Name

Type

Description

enabled

boolean

true or false - default is “true”.

push_service_subject

string

Used as the subject in the VAPID method for the push service. This must be either a “mailTo-Link” or the URI to your site.

Example:
“https://portrait.customer.xyz”

urgency

string

Optional – default is NORMAL.
Possible values are: VERY_LOW, LOW, NORMAL, HIGH.

application: push: deplay: 2000 # in ms threadPoolSize: 1

Name

Type

Description

Name

Type

Description

enabled

boolean

true

threadPoolSize

int

The number of the threadpool used for processing the initial task for submitting a batch of notifications.

delay

int

The delay in ms when the threadtask to process the notifications is launched. Should at least 2000ms in order to for customFields Permission checks to work. (lower the chance a dirty read on elasticsearch)

VAPID Keys

In order to authenticate to the push service, Vapid Keys are used. Keys use the Elliptic Curve Diffie-Hellman format - ECDH. These are stored in the config folder and consist of a private key vapid_private_key and a public key vapid_public_key.

Configuration per Section

The content of the notifications is configured on section level. Thus, title and body can be customized per each section separately. Otherwise, a default configuration is used.

Example configuration:

section: sections: - name: expenses group: Mein Arbeitsplatz caption: Spesen push: titleSection: "{{sectionName}} - Neuigkeiten" titleSingleItem: "{{sectionName}} - Neuigkeiten" bodySection: "{{totalCount}} Aktualisierungen" bodySingleItem: "{{name}} {{#eq actionType \"created\"}}erstellt{{else}}aktualisiert{{/eq}}"

 

The following settings are possible:

Name

Type

Description

Name

Type

Description

titleSingleItem

string

Title of the notification for a single entry.

Recommended - default is:

{{sectionGroup}} - {{sectionName}}

Default example:
“My Workplace - Expenses”

bodySingleItem

string

Message of the notification.

Recommended - default is:

{{sectionGroup}} - {{sectionName}} - {{name}} {{#eq actionType "created"}}created{{else}}updated{{/eq}}

Default example:
“My Workplace - Expenses - A Cup of Coffee created”

titleSection

string

Title of the notification for a section.

Recommended - default is:

{{sectionGroup}} - {{sectionName}}

Default example:
“My Workplace - Expenses”

bodySection

string

Message of the notification for a section.

{{totalCount}} Updates in {{sectionName}}

Default example:
”2 Updates in Expenses”

Field processors

As seen in the previous chapters, custom notification content relies on Field Processors. In the context of Notifications, the following parameters are supported:

Property

Single Entry / Section

Description

Property

Single Entry / Section

Description

sectionId

/

The internal ID of the section.

sectionName

/

The caption of the section.

sectionGroup

/

The group the section is part of in the menu / sidebar of the frontend.

totalCount

/

The total amount of updated/added elements of the subscribed section.

createdCount

/

The amount of new entries of a subscribed section.

updatedCount

/

The amount of updated entries of a subscribed section.

actionType

/

Reflects the status of the action. Either created or updated.

Comes handy in combination with a field processor evaluator, example:

Entry {{#eq actionType "created"}}created{{else}}updated{{/eq}}!

name

/

The name of the entry.

All fields of an entry

/

Each field/column of a single entry can be part of the push notifications - refer to the field with its key.

Useful, if you need to build precise and short notification texts.

Example
Your entry contains a field VENNAME with the value "kaffeemik".

The section config therefore is:

You want to the following the notification text:
“New expense from kaffeemik”

Therefore, your field processor looks like this:
New expense from ({{VENNAME}})