Pre render hooks [@since 6.2]

Pre render hooks are functions that let you run code before SiteVision starts rendering a page. Hooks are declared in the hooks.js file that must be placed directly under the WebApp's /src folder.

To get access to the hooks available, simply require('hooks') in your hooks.js file. See example below.

Available hooks

There are three types of pre render hooks available: beforeRender, getPageTitle and addHeadElement. 

beforeRender

The beforeRender hook accepts a function with req and res as arguments. This hook is intended to run arbitrary code.

  • beforeRender((req, res) => {})

getPageTitle

The getPageTitle hook accepts a function with req as argument. This hook should return a string that will be used as title of the current page.

  • getPageTitle(req => 'Page title')

A null or blank string will be ignored. SiteVision will always escape the returned string. If multiple WebApps on the same page use this hook, the last successfully invoked getPageTitle-hook will be used as <title> of current page.

addHeadElement

The addHeadElement hook accepts a function with req as argument. This hook should return a string (a valid <head> element) that will be added to the <head> section of the current page.

  • addHeadElement(req => ...)

A null or blank returned string will be ignored. SiteVision will not escape the returned string so remember to escape all dynamically inserted values.

Request object (req)

The request object (req) is almost identical to the request object in a regular WebApp callback. However, there are two differences:

Additions

  • A context object is available that makes it possible to fetch data in a hook and later consume it during rendering of the WebApp. See the example below of how it might be used.

Limitations

  • route parameters will not be resolved. If you need to resolve route parameters in a hook, use the req.path property to resolve your captured value.

Response object (res)

The response object (res) is limited within the hooks context. The servlet response is not committed in this phase which makes it possible to set cookies and redirect. The following methods are available:

Example

Below is an example of what a hooks.js might look like

// hooks.js
(function() {
   'use strict';

   const { beforeRender, addHeadElement, getPageTitle } = require('hooks');
   const { getEventData } = require('/module/server/eventsApi');
   const { escape } = require('underscore');

   beforeRender((req) => {
      const data = getEventData(req.params.eventId);

      req.context.eventData = data; // req.context is propagated to the rendering phase (index.js)
   });

   getPageTitle((req) => req.context.eventData.title);

   addHeadElement((req) => {
      const description = escape(req.context.eventData.description);

      return '<meta property="og:description" content="' + description + '">';
   });
   
   addHeadElement((req) => {
      const image = escape(req.context.eventData.image);

      return '<meta property="og:image" content="' + image + '">';
   });
}());

The req.context object is available during rendering of the WebApp with the data set in the beforeRender-hook.

// index.js
router.get('/', (req, res) => {
   logger.info(req.context.eventData); // eventData set in beforeRender hook
});	

Requireables

SiteVision's Public API and WebApp specific requireables are available when evaluating hooks.

// hooks.js context, WebApp specifics
const 
  _             = require('underscore'); // [example](https://underscorejs.org/)
  
  appData       = require('appData'),       // [example](/docs/webapps/configuration/appdata),
  appInfo       = require('appInfo'),       // [example](/docs/webapps/require/appinfo),
  appResource   = require('appResource'),   // [example](/docs/webapps/resource#h-AppResource)
  globalAppData = require('globalAppData'), // [example](/docs/webapps/configuration/appdata)
  hooks         = require('hooks'),         // [example](/docs/webapps/hooks)
  i18n          = require('i18n'),          // [example](/docs/webapps/i18n)
  storage       = require('storage'),       // [example](/docs/data-storage)
  oauth2        = require('oauth2'),        // since 7.0 [example](/docs/webapps/require/oauth2)
  privileged    = require('privileged'),    // since 7.0 [example](/docs/webapps/require/privileged)  
  
  serverModule  = require('/module/server/moduleName'); // [example](/docs/webapps/module)

The SiteVision Public API is always accessible server-side. All interfaces, classes and enums that are anotated with the @Requireable annotation is available via the require function.

Note that Public API requireables always has a leading capital letter (requireable name matches the name of the Public API interface/class/enum).

// Server context (e.g. index.js, server module etc.)
const
  properties             = require('Properties'),
  propertyUtil           = require('PropertyUtil'),
  resourceLocatorUtil    = require('ResourceLocatorUtil'),
  portletContextUtil     = require('PortletContextUtil'),
  permissionUtil         = require('PermissionUtil'),
  publishingUtil         = require('PublishingUtil'),
  versionUtil            = require('VersionUtil'),
  metadataUtil           = require('MetadataUtil'),
  metadataDefinitionUtil = require('MetadataDefinitionUtil'),
  outputUtil             = require('OutputUtil'),  
  userIdentityUtil       = require('UserIdentityUtil'),
  mimeTypeUtil           = require('MimeTypeUtil'),
  nodeIteratorUtil       = require('NodeIteratorUtil'),
  nodeTreeUtil           = require('NodeTreeUtil'),  
  nodeComparatorUtil     = require('NodeComparatorUtil'),
  nodeFilterUtil         = require('NodeFilterUtil'),
  nodeTypeUtil           = require('NodeTypeUtil'),
  localInboundRestApi    = require('RestApi'),
  ...