Platform
Preferences
Overview

Preferences overview

Learn how to implement notification preferences in Knock.

Preferences enable your users to opt-out of the notifications you send using Knock.

How preferences work

#

A user has a PreferenceSet. A PreferenceSet is a JSON object that tells Knock which channels, categories, and/or workflows a user has opted out of receiving.

When Knock runs a workflow for a user, we evaluate their PreferenceSet. A message will not send if the user has opted out of receiving it.

A preference set is built using three keys: categories, channel_types, workflows. These keys resolve to boolean values to determine if a user has opted out of receiving a notification.

A recipient's default preference set also has a commercial_unsubscribe key which determines if the recipient should receive notifications sent by commercial workflows or broadcasts. Read more about commercial unsubscribe here.

A few examples:



You can combine these keys to create preference grids like the one in the image below:

The PreferenceSet above models this preference grid in your application:

An image of a preference set

Build your preference center

#

Before you start setting preferences for your users, you need to build a preference center in your application. A preference center is a place where users can manage their notification preferences.

There are four steps to building a preference center with Knock:

1

Create a default PreferenceSet

A default preference set is the PreferenceSet users default to using when they first sign up for your product. Any users who don't have a preference set will default to using the default preference set. You can create a default preference set in the Knock dashboard under Developers > Preferences.

Creating a default preference set in Knock dashboard

The default preference set is environment-specific for testing purposes. You can copy the default preference set from one environment to another to keep your environments in sync.

2

Get a user's preferences

Once you have your default PreferenceSet created, you will use the getPreferences method to retrieve a user's preferences for rendering in your application. If no preferences are set, this method will return the default preference set you created in the step above.

3

Render your preference center

Once you have loaded a user's preference, you'll need to render an interface in your application so they can update their notification preferences. Typically you encapsulate all of the getting and setting of preferences in a single component.

You can see an example of this below, but our quickstart guide on building preferences UI provides an in-depth walkthrough of how to build a functional PreferenceCenter component.

A basic preference center
4

Set a user's preferences

When a user makes changes to their preferences in your application, you will use the setPreferences method to save those changes back to Knock.

You can learn more about rendering preferences to users in your application in the Building In-app UI section of our documentation:

Merging preferences

#

When a default PreferenceSet exists for an environment or tenant, Knock will merge all applicable preferences for a recipient when evaluating whether or not to send a notification. Any preferences set at the recipient level will take precedence in the merge, according to the hierarchy outlined below.

Merge hierarchy

#

The following hierarchies are used when merging preferences.

The following standard hierarchy is used to merge preferences when no tenant is applied to the workflow trigger. Each item in the list takes precedence over the ones that follow it:

  1. A recipient's default preference set
  2. The environment-level default preference set

Let's take a look at an example to visualize this merge. Suppose that you have the following preference sets:

A visual of the environment default and recipient default preference sets prior to merging

To visualize the resulting merged preferences, we'll start at the bottom of the hierarchy and work our way up, adding any preferences from the environment default preference set that are not already present in the recipient's default preference set. Any preferences that are set in both places will keep the value from the recipient's default preference set:

A visual of the environment default preferences merging into the recipient's default preferences

The resulting merged preferences will look like this:

A visual of the combined environment default and recipient default preference sets after merging

The environment-level setting to opt all users into collaboration notifications will be respected because the recipient doesn't have an explicit preference for that category, but the recipient's preference to specifically opt in to SMS messages will override the environment-level setting to opt out.

The following hierarchy is used to merge preferences when a tenant is applied to the workflow trigger. Each item in the list takes precedence over the ones that follow it:

  1. A recipient's tenant-specific preference set
  2. The tenant's default preference set
  3. The environment-level default preference set

This merge works in the same way as the standard merge above, but it evaluates different preference sets. Let's take a look at an example to visualize this merge. Suppose that you have the following preference sets:

A visual of the tenant-specific preference sets prior to merging

To visualize the resulting merged preferences, we'll start at the bottom of the hierarchy and move upward—first adding preferences from the environment default to the tenant's default preference set, then adding any of those preferences that are not already present in the recipient's tenant-specific preference set. At each step, if a preference exists in both sets, the value from the higher level in the hierarchy takes precedence:

A visual of the tenant-specific preferences merging into the tenant's default preferences

The resulting merged preferences will look like this:

A visual of the combined tenant-specific and tenant default preference sets after merging

The environment-level settings to opt all users out of SMS messages and into collaboration notifications will be respected because neither the tenant nor the recipient have an explicit preference for these items. The tenant's preference to opt users in to reminders notifications will be overridden by the recipient's setting to opt out.

For more information on how you can override these hierarchies, see the Frequently asked questions section below.

Preference evaluation rules

#

When a workflow is triggered, Knock will evaluate the preferences for each recipient of the workflow and send notifications for each channel step in the workflow based on that evaluation. There are some important rules and caveats to consider:

  • If you do not set a preference for a given channel, workflow, or workflow category, Knock defaults them to true.
  • When a recipient clicks an unsubscribe link, their default preference set will be updated, marking commercial_unsubscribe as true. They will be opted-out of commercial messages, and they will continue to receive transactional messages based on their other preferences. Read more about commercial unsubscribe here.

Knock only sends a notification if all preference combinations that exist on the recipient evaluate to true.

  • A workflow can belong to multiple categories. Only one of those category preferences needs to evaluate to false for the notification not to send.
  • If a workflow's category is set to false, the notification will not send even if a channel_type on the workflow is explicitly set to true.

Our Preferences API provides endpoints for retrieving all of the preferences that have been set on a recipient.

You can also use the workflow debugger in your dashboard to view the preferences that were evaluated for the recipient on a given workflow run.

An image of a workflow run's evaluated preferences

Bulk set user preferences

#

You can update the preferences of up to 1000 users in a single batch by using the users.bulkSetPreferences method. This executes an asynchronous job which will overwrite any existing preferences for the users provided. You can track the progress of the BulkOperation returned via the bulk operation API.


Advanced concepts

#
  • Per-tenant preferences. In multi-tenant B2B applications, an advanced use case is customer admins who want to set the tenant-level default PreferenceSet for new users within their tenant.
  • Object preferences. In the guide above, we referred to user preferences. You can also set preferences for objects.
  • Preference conditions. You can build advanced conditions and store them on Knock’s preference model to power use cases such as per-resource muting (example: mute notifications about this task) or threshold alerts (example: only notify me if my account balance is below $5).
  • Merge strategy. It's possible to configure the merge strategy on specific preferences within a PreferenceSet. This allows you to override the default merge hierarchy when preferences are evaluated. See the Frequently asked questions section below for more details and use cases.
  • Workflow overrides. If you need to override a recipient's notification preferences to send notifications like a password reset email, you can override the preferences model. To do this, go to your workflow, click "Manage workflow," and enable "Override recipient preferences." You will need to commit this change for it to take effect. When enabled, the workflow will send to all of its channels, regardless of the recipient's preferences.
  • Commercial unsubscribe. You can configure 1-click unsubscribe links to help users opt-out of commercial or promotional notifications and comply with CAN-SPAM requirements.

Frequently asked questions

#

While our preferences API endpoints will always overwrite the existing PreferenceSet with the new preferences provided, it's possible to update a single preference by using any of our recipient identification methods, including while triggering a workflow (as seen in the example below). This will perform a deep merge of the provided preferences into any existing preferences, just like any other properties stored on the recipient.

Note that the syntax for providing the id of the preference set on an InlinePreferenceSetRequest is slightly different than the way that our preferences endpoints handles them; you'll simply provide a key-value pair where the key is the id of the preference set and the value is the PreferenceSet you'd like to merge.

Here's what this looks like in practice. If a user has these existing default preferences:

and they would like to update their email preference for the collaboration category to false, you can do so by providing the following InlinePreferenceSetRequest while triggering a workflow:

This will result in the following PreferenceSet being set on the recipient prior to the workflow being triggered:

By default, a recipient's individual preferences will always take the highest precedence in the merge when preferences are evaluated (according to the hierarchy outlined under Merging preferences above).

Some applications have use cases where it's necessary for a preference that is set at the tenant level to override a user's individual preference. For example, you may want to allow a team admin to disable a certain type of notification for their entire team, regardless of whether an individual user has opted in to that notification. To achieve this, you can set the __strategy__ key on the preference you'd like to override to a value of "replace".

In the following example, although the user has specifically opted into receiving email notifications for the collaboration category, email notifications with that category will not send because the tenant's default preference set has set the collaboration category to false. Consider the following preference sets:


The merge during preference evaluation will look like this:

A visual of the tenant's default preferences merging into the recipient's tenant-specific preferences with the replace strategy applied

The recipient's preference for the project-updates category is preserved in the merge, but their preference for collaboration notifications is overridden by the tenant's preference due to the replace strategy.

This replace strategy will also be reflected when you request the user's preferences via API. Although the user's tenant-specific preferences have explicitly been set to the above, the __strategy__ key will be present on the PreferenceSet returned, indicating that their preference has been overridden by the tenant's:


Here are some important thing to keep in mind when using the replace strategy:

  • This strategy will only apply to the specific preference(s) where it's included; there's no way to override the entire PreferenceSet at the top level.
  • The __strategy__ key can only be used on a combined workflows-channel_types or categories-channel_types preference, as seen in the example above.
  • When the preference with the replace strategy is removed, any existing preferences that were overridden by the replace strategy will be immediately restored to their original values. For the example above, the user will once again be opted in to collaboration notifications.

In the workflow debugger, Knock will show you the preferences that were evaluated for the recipient on a given workflow run. You may notice channel_types preferences, even if you didn't explicitly set them on the recipient or in your environment default preference set.

An image of a workflow run's evaluated preferences

This is because Knock automatically opts all recipients in to all channel_types by default, to ensure that the recipient receives notifications unless they have been explicitly opted out.

If you want to override this behavior, you can set the channel_types preference to false for all channel types in your environment default preference set. This will opt the recipient out from all notifications.