Notifications

At different moments in the lifecycle of the web request, Zotonic sends notifications. By observing these notifications you can override Zotonic’s behaviour. You can also add your own notifications.

Zotonic’s notifier system makes it possible to create modular components with a pluggable interface. The notifier system is used by internal core Zotonic components like the authentication mechanism, the logging system and more.

The notification system can not only act as a traditional event subscription system but also as an advanced priority based function dispatch system. It uses the same priority system which is used to select templates. This makes it possible to override pre-defined default behaviour of core Zotonic modules.

A notification message is a tagged tuple. The first element of the tuple is the type of notification message. An observer can use this to subscribe to specific messages it is interested in.

Example:

{acl_logon, 1234}

Or:

{module_activate, mod_stream, <0.32.0>}

You can find a list of all notifications in the reference section.

Sending notifications

As mentioned earlier, the notification system can not only be used to just send events to observers. Observers can also return values back. They can do this in various ways described in the methods below.

Notification types

notify

Send a message to all observers. This is used if you want to notify other observers about a specific event. In Zotonic this is used a lot. For instance, it is used to notify modules of about user logons, or notify when modules are activated and deactivated.

notify1

Notify the first observer. This is useful for if you want to be sure just one observer can do something with the message.

first

Call all observers, and use the first non undefined answer. This is used to get information from one of the observers. By using the notification system it makes sure that modules are decoupled.

map

Call all observers and get a list of all answers.

foldl

Do a fold over all observers, high prio observers first.

foldr

Do a fold over all observers, low prio observers first.

notify_sync

Synchronous notification, wait till all observers have processed the notification before continuing. The notify will notify all observers asynchronously and returns before all notifications are processed.

The synchronous notification also shares the current database transaction (if any) and other context data with the observers. This allows to process the notification within a transaction.

Subscribing to notifications

Registering as an observer works as follows:

z_notifier:observe(NotificationType, Handler, Priority, Context)

If the module is either a Zotonic module or a site module, the Priority parameter can be omitted. The observer will then get the same priority as the module.

NotificationType
The type of notification you want to observe, an atom.
Handler
Can be a pid(), or a {Module, Fun} tuple. When the handler is a pid() and the notification is sent with notify or notify1 the gen_server process receives a handle_cast. When an answer is expected back handle_call is used. This is the case for first, map, foldl and foldr.
Priority
The priority of the observer. This influences the order in which they are called.
Context
The Zotonic context.

Example:

z_notifier:observe(acl_logon, {mysitewww, handle_logon}, Context)

Subscription shorthands

Modules and sites can use shortcuts for registering as an observer. When the Zotonic module exports a function with the prefix observe_ or pid_observe_ Zotonic’s module manager will register the observer for you.

For example exporting observe_acl_logon/2 will register that function as an observer. It will be triggered when the acl_logon notification is fired. Functions prefixed with pid_observe_ are for gen_server based modules: they get passed the gen_server’s PID as the first argument.

Handling notifications

When a notifications is sent the z_notifier module looks in its tables to see if there are any observers interested in receiving it. There are three types of notifications.

Cast notifications

This is the simplest notification. The notifier does not expect an answer back the result of the handler is ignored. This kind of notification is triggered by calling z_notifier:notify/2 or z_notifier:notify1/2. They are useful for letting other modules know about a certain even or condition. This makes it possible for other modules to act on it.

For example, mod_development uses call notifications to trigger builds and reloads. By doing this other modules can notify mod_development to trigger builds. But when mod_development is disabled nothing will happen.

Call notification

For this kind of notification, z_notifier expects an answer back. This answer is returned back to the notifier. This kind of notifications is used to decouple modules. For instance a module can ask another module for a special URL to go to after logging in without knowing which module will do this. Call notifications are triggered by: z_notifier:first/2 and z_notifier:map/2.

For example, mod_signup uses a call notification to find out what page to redirect to after a successfull signup. This allows one to customize the signup process.

Fold notifications

Fold notifications are called, with z_notifier:foldl/3 or z_notifier:foldr/3. It works similarly to the lists:foldr and lists:foldl functions of Erlang’s lists module. The fold function calls each observer in sequence, either starting at highest (foldl) or at lowest (foldr) priority, passing values and an initial accumulator value. Each observer can adapt values in the accumulator, and needs to return it, for passing on to the next observer. The final value of the accumulator is returned as result. This is useful if you want multiple modules to be able to adapt and use values in the accumulator. For example, mod_admin uses a fold notification (called admin_menu) to build up the admin navigation menu, where each observer is called to add menu entries to the menu.

Modules Developer Guide Browser/server interaction

Referred by

observe_rsc_pivot_done/2

Signal that a resource pivot has been done.

observe_acl_context_authenticated/2

Set the context to a typical authenticated user. Used by m_acl.erl

observe_export_resource_visible/2

mod_export - Check if the resource or dispatch is visible for export.

observe_menu_save/2

Save the menu tree of a menu resource

observe_auth_confirm/3

Confirm a user id.

observe_user_context/3

Set #context fields depending on the user and/or the preferences of the user.

observe_email_ensure_handler/2

Add a handler for receiving e-mail notifications

observe_acl_logoff/2

Clear the associated access policy for the context.

observe_mailinglist_mailing/2

Send a page to a mailinglist (notify) Use \{single_test_address, Email\} when sending to a specific e-mail address.

postback_event

Message sent by a user-agent on a postback event. Encapsulates the encoded postback and any additional data. This is…

observe_export_resource_content_type/2

mod_export - Determine the mime type for the export.

observe_identity_verified/2

Notify that a user’s identity has been verified. Signals to modules handling identities to mark this identity as…

observe_media_upload_props/3

Notification that a medium file has been uploaded. This is the moment to change properties, modify the file etc. The…

observe_admin_menu/3

Used for fetching the menu in the admin.

observe_identity_password_match/2

Check if passwords are matching. Uses the password hashing algorithms.

observe_pivot_fields/3

Foldr to change or add pivot fields for the main pivot table. The rsc contains all rsc properties for this resource

observe_email_status/2

Email status notification, sent when the validity of an email recipient changes

observe_media_identify_file/2

Try to identify a file, returning a map with file properties.

observe_page_url/2

Fetch the url of a resource’s html representation

controller_id

Handle different content representations of a page.

observe_cors_headers/2

Set CORS headers on the HTTP response.

observe_filewatcher/2

Broadcast some file changed, used for livereload by mod_development

observe_auth_reset/2

First to check for password reset forms, return undefined, ok, or \{error, Reason\}.

observe_media_viewer/2

Request to generate a HTML media viewer for a resource. The HTML data can not contain any Javascript, as it might be…

observe_media_update_done/2

Media update done notification. action is ‘insert’, ‘update’ or ‘delete’

observe_media_import/2

Notification to translate or map a file after upload, before insertion into the database Used in mod_video to queue…

observe_url_abs/2

Make a generated URL absolute, optionally called after url_rewrite by z_dispatcher

observe_admin_edit_blocks/3

Used in the admin to fetch the possible blocks for display

observe_comment_insert/2

Notification to signal an inserted comment. ‘comment_id’ is the id of the inserted comment, ‘id’ is the id of the…

observe_signup_confirm_redirect/2

Fetch the page a user is redirected to after signing up with a confirmed identity

observe_signup_check/3

signup_check Check if the signup can be handled, a fold over all modules. Fold argument/result is \{ok, Props

observe_logon_ready_page/2

Check where to go after a user logs on.

observe_rsc_insert/3

Foldr for an resource insert, these are the initial properties and will overrule the properties in the insert request.

observe_output_html/3

Fold for mapping non-iolist output to iolist values.

observe_rsc_get/3

Resource is read, opportunity to add computed fields Used in a foldr with the read properties as accumulator.

observe_media_identify_extension/2

Try to find a filename extension for a mime type (example: <<".jpg"\>\> )

observe_sanitize_embed_url/2

Sanitize an embed url. The hostpart is of the format: <<"youtube.com/v..."\>\> .

observe_email_failed/2

Notify that we could NOT send an e-mail (there might be a bounce later...) The Context is the depickled z_email:send/2…

observe_dispatch_host/2

Try to find the site for the request Called when the request Host doesn’t match any active site.

observe_postback_notify/2

Handle a javascript notification from the postback handler. The message is the the request, trigger the id of the…

observe_acl_user_groups/2

Return the groups for the current user.

observe_survey_submit/2

A survey has been filled in and submitted.

observe_export_resource_data/2

mod_export - fetch a row for the export, can return a list of rows, a binary, and optionally a continuation state.

observe_auth_options_update/3

Update the given (accumulator) authentication options with the request options.

observe_auth_precheck/2

First for logon of user with username, check for ratelimit, blocks etc.

Modules

Modules are the building blocks of Zotonic. They add functionality to your Zotonic website such as:

observe_logon_submit/2

Handle a user logon. The posted query args are included. Return:: {ok, UserId} or {error, Reason}

observe_media_upload_rsc_props/3

Notification that a medium file has been uploaded. This is the moment to change resource properties, modify the file…

observe_signup_done/2

Signal that a user has been signed up (map, result is ignored)

observe_media_upload_preprocess/2

Notification to translate or map a file after upload, before insertion into the database Used in mod_video to queue…

observe_import_resource/2

An external feed delivered a resource. First handler can import it. Return:: {ok, m_rsc:resource_id()} , `{error

observe_rsc_update_done/2

An updated resource has just been persisted. Observe this notification to execute follow-up actions for a resource…

observe_session_context/3

Refresh the context or request process for the given request or action

observe_search_query/2

Map a custom search term to a #search_sql_term{} record.

observe_auth_postcheck/2

First for logon of user with username, called after successful password check.

observe_activity_send/2

Push a list of activities via a ‘channel’ (eg ‘email’) to a recipient. The activities are a list of

observe_tkvstore_get/2

Get a value from the typed key/value store

observe_rsc_merge/2

Map to signal merging two resources. Move any information from the loser to the winner. The loser will be deleted.

observe_module_activate/2

A module has been activated and started.

observe_export_resource_header/2

mod_export - Fetch the header for the export.

observe_ssl_options/2

Request the SSL certificates for this site. The server_name property contains the hostname used by the client. (first…

observe_content_types_dispatch/3

Get available content types and their dispatch rules Example: \{\{<<”text”>>, <<”html”>>, [\]\}, page\} A special…

observe_import_csv_definition/2

Find an import definition for a CSV file by checking the filename of the to be imported file.

observe_email_received/2

Notification sent to a site when e-mail for that site is received

observe_email_add_handler/2

Add a handler for receiving e-mail notifications

observe_identity_verification/2

Request to send a verification to the user. Return ok or an error. Handled by mod_signup to send out verification…

observe_sanitize_element/3

Sanitize an HTML element.

observe_dropbox_file/2

Handle a new file received in the ‘files/dropbox’ folder of a site. Unhandled files are deleted after an hour. If the…

observe_auth_logoff/3

User is about to log off. Modify (if needed) the logoff request context.

observe_pivot_rsc_data/3

Fold over the resource props map to extend/remove data to be pivoted

observe_category_hierarchy_save/2

Save (and update) the complete category hierarchy

observe_hierarchy_updated/2

Signal that the hierarchy underneath a resource has been changed by mod_menu

observe_set_user_language/2

Set the language of the context to a user’s prefered language

observe_debug/2

Push some information to the debug page in the user-agent. Will be displayed with io_lib:format(“~p: ~p~n”, [What

Browser/server interaction

There are multiple ways to set up interaction between server-side Zotonic code and client-side JavaScript.

observe_user_is_enabled/2

Check if a user is enabled. Enabled users are allowed to log in. Return true , false or undefined . If undefined is…

observe_survey_is_allowed_results_download/2

Check if the current user is allowed to download a survey.

observe_auth_checked/2

Notify after logon of user with username, communicates valid or invalid password

observe_menu_rsc/2

Fetch the menu id belonging to a certain resource

observe_m_config_update_prop/2

Site configuration parameter was changed

Notifications

This is a list of all built-in notifications that Zotonic sends. Observe these notifications in your code to add custom…

observe_custom_pivot/2

Add custom pivot fields to a resource’s search index (map) Result is a single tuple or list of tuples `{pivotname

observe_signup_confirm/2

Signal that a user has been confirmed. (map, result is ignored)

observe_export_resource_footer/2

mod_export - Fetch the footer for the export. Should cleanup the continuation state, if needed.

observe_auth_confirm_done/2

A user id has been confirmed.

observe_acl_is_allowed_prop/2

Check if a user is authorizded to perform an action on a property. Defaults to true .

observe_email_bounced/2

Bounced e-mail notification. The recipient is the e-mail that is bouncing. When the the message_nr is unknown the it is…

observe_acl_is_owner/2

Check if a user is the owner of a resource. id is the resource id.

observe_mailinglist_message/2

Send a welcome or goodbye message to the given recipient. The recipient is either a recipient-id or a recipient props.

observe_auth_validate/2

First to validate a password. Return \{ok, RscId\} or \{error, Reason\}.

observe_request_context/3

Refresh the context or request process for the given request or action

observe_edge_delete/2

An edge has been deleted Note that the Context for this notification does not have the user who deleted the edge.

observe_acl_logon/2

Initialize context with the access policy for the user.

observe_rsc_upload/2

Upload and replace the resource with the given data. The data is in the given format.

observe_export_resource_filename/2

mod_export - return the \{ok, Filename\} for the content disposition.

observe_auth_logon/3

User logs on. Add user-related properties to the logon request context.

Overriding Zotonic

This chapter describes how to override the templates, styling and logic provided by Zotonic.

observe_edge_update/2

An edge has been updated Note that the Context for this notification does not have the user who updated the edge.

observe_rsc_delete/2

Resource will be deleted. This notification is part of the delete transaction, it’s purpose is to clean up associated…

observe_signup_url/2

Handle a signup of a user, return the follow on page for after the signup. Return {ok, Url} ‘props’ is a map with…

observe_survey_get_handlers/3

Fetch list of handlers for survey submits.

observe_email_sent/2

Notify that we could NOT send an e-mail (there might be a bounce later...) The Context is the depickled z_email:send/2…

observe_media_replace_file/2

Notification that a medium file has been changed (notify) The id is the resource id, medium contains the medium’s…

observe_email_is_blocked/2

Check if an email address is blocked

observe_scomp_script_render/2

Add extra javascript with the \{% script %\} tag. (map) Used to let modules inject extra javascript depending on the…

observe_rsc_query_item/2

Send a notification that the resource ‘id’ is added to the query query_id.

observe_media_stillimage/2

See if there is a ‘still’ image preview of a media item. (eg posterframe of a movie) Return:: {ok, ResourceId} or…

observe_tkvstore_put/2

Put a value into the typed key/value store

acl_mqtt

MQTT acl check, called via the normal acl notifications. Actions for these checks: subscribe, publish

observe_dispatch/2

Final try for dispatch, try to match the request. Called when the site is known, but no match is found for the path

observe_m_config_update/2

Site configuration parameter was changed

observe_signup/2

Request a signup of a new or existing user. Arguments are similar to #signup_url\{\} Returns \{ok, UserId\} or \{error

observe_edge_insert/2

An edge has been inserted. Note that the Context for this notification does not have the user who created the edge.

observe_signup_failed_url/2

Signup failed, give the error page URL. Return \{ok, Url\} or undefined. Reason is returned by the signup handler for…

observe_rsc_update/3

An updated resource is about to be persisted. Observe this notification to change the resource properties before they…

observe_url_rewrite/3

Rewrite a URL after it has been generated using the z_dispatcher

observe_survey_is_submit/2

Check if a question (page block) is a submitting question.

media_import_props

Notification to translate or map a file after upload, before insertion into the database Used in mod_video to queue…

observe_tkvstore_delete/2

Delete a value from the typed key/value store

observe_pivot_update/3

Pivot just before a m_rsc_update update. Used to pivot fields before the pivot itself.

observe_admin_rscform/3

Used in the admin to process a submitted resource form

observe_export_resource_content_disposition/2

mod_export - return the \{ok, Disposition\} for the content disposition.

observe_dispatch_rewrite/3

Rewrite a URL before it will be dispatched using the z_sites_dispatcher

observe_language/2

Notify that the session’s language has been changed

observe_export_resource_encode/2

mod_export - Encode a single data element.

observe_acl_is_allowed/2

Check if a user is authorized to perform an operation on a an object (some resource or module). Observe this…

observe_activity/2

An activity in Zotonic. When this is handled as a notification then return a list of patterns matching this activity.

observe_module_deactivate/2

A module has been stopped and deactivated.

observe_auth_validated/2

Authentication against some (external or internal) service was validated

observe_email_drop_handler/2

Drop an e-mail handler for a user/resource id. (notify). The notification, user and resource should be the same as when…

observe_action_event_type/2

Render the javascript for a custom action event type. The custom event type must be a tuple, for example: `{% wire…

postback

See also

observe_security_headers/2

Check and possibly modify the http response security headers All headers are in lowercase.

observe_media_preview_options/3

Modify the options for an image preview url or tag. This is called for every image url generation, except if the…

observe_auth_client_logon_user/2

Send a request to the client to login a user. The zotonic.auth.worker.js will

observe_url_fetch_options/2

Determine the URL fetch options for fetching the content of an URL. Used by z_fetch.erl.

observe_media_import_medium/2

Notification to import a medium record from external source. This is called for non-file medium records, for example…

observe_resource_headers/3

Let all modules add resource specific response headers to the request. The accumulator is the list of headers to be set.

observe_validate_query_args/3

Called just before validation of all query arguments by z_validation.

observe_email_dkim_options/2

Return the options for the DKIM signature on outgoing emails. Called during email encoding.

observe_auth_client_switch_user/2

Send a request to the client to switch users. The zotonic.auth.worker.js will

observe_logon_options/3

Check for logon options, called if logon_submit returns undefined. This is used to fetch external (or local…

observe_http_log_access/2

Access log event for http. Called from the z_stats.

observe_email_send_encoded/2

Add a handler for receiving e-mail notifications

observe_rsc_import_fetch/2

Fetch the data for an import of a resource. Returns data in the format used by m_rsc_export and m_rsc_import. Either…

observe_middleware/3

Delegates the request processing.

observe_search_query_term/2

Map a custom search term to a #search_sql_term{} record.

observe_acl_user_groups_modify/3

Modify the list of user groups of a user. Called internally by the ACL modules when fetching the list of user groups a…

observe_media_viewer_consent/2

Optionally wrap HTML with external content so that it adheres to the cookie/privacy settings of the current site…

observe_acl_collab_groups_modify/3

Modify the list of collaboration groups of a user. Called internally by the ACL modules when fetching the list of…

observe_survey_result_column_values/3

Modify row with answers for export. The header columns are given and the values that are known are set in the folded…

observe_survey_result_columns/3

Add header columns for export. The values are the names of the answers and the text displayed above the column. The…

observe_translate/2

Request a translation of a list of strings. The resulting translations must be in the same order as the request. This…

observe_language_detect/2

Try to detect the language of a translation. Set is_editable_only to false to detect any language, even if the language…

observe_auth_identity_types/3

Return the list of identity types that allow somebody to logon and become an active user of the system. Defaults to […

observe_identity_update_done/2

Notify that a user’s identity has been updated by the identity model.

observe_email_is_recipient_ok/2

Check if an email address is safe to send email to. The email address is not blocked and is not marked as bouncing.

observe_content_security_header(Default, Acc, Context)

Check and possibly modify the http response security headers All headers are in lowercase.