# Server-side events

Each section below includes server-side events emitted by a particular module and modules that extend them (e.g., all piece types emit the events listed for @apostrophecms/piece-type). See the server-side events guide for more detail on using events.

Code block examples represent the handlers section of a module.

NOTE

As a reminder, when referencing an event in the handlers section from within the module that emits it we only need to use the event name. This includes events emitted by functionality that a module inherits (e.g., all piece type modules emit events from @apostrophecms/piece-type functionality).

handlers(self, options) {
  return {
    // 'beforeSave' is an event the @apostrophecms/user module emits.
    'beforeSave': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/user/index.js

When naming an event emitted by a different module, the event name must be prefixed with the name of the module that emitted it followed by a colon.

handlers(self, options) {
  return {
    // This team module is specifically listening for 'beforeSave' on
    // the @apostrophecms/user module.
    '@apostrophecms/user:beforeSave': {
      async handlerName() { ... }
    }
  };
}
modules/team/index.js

# Core app events

These events are emitted by the primary Apostrophe app. Reference these events with the prefix apostrophe: (e.g., apostrophe:ready).

# destroy

Triggered when the app's destroy method is called. Most commonly used in tests. Your handlers should clean up any custom setTimeout or setInterval timers and/or open socket or database connections you have created. You should not "destroy" your actual website content. Just close any remaining open connections, timeouts, etc.

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'apostrophe:destroy': {
      async handlerName() { ... }
    }
  };
}
modules/any-module/index.js

# modulesRegistered

Triggered during startup after all modules are registered and their init functions run. This is the last opportunity to adjust module configuration (e.g., field schema) in response to other active modules.

There is no data included with the event for handlers. Previously named modulesReady, which still works as an alias.

handlers(self, options) {
  return {
    'apostrophe:modulesRegistered': {
      async handlerName() { ... }
    }
  };
}
modules/any-module/index.js

# ready

Invoked after all apostrophe:modulesRegistered handlers and start up functions have completed. All modules are now completely ready for work.

There is no data included with the event for handlers. Previously named afterInit, which still works as an alias.

handlers(self, options) {
  return {
    'apostrophe:ready': {
      async handlerName() { ... }
    }
  };
}
modules/any-module/index.js

# run

Not intended for project use. If Apostrophe was invoked as a command line task, Apostrophe's task module responds to this event by executing the task. Otherwise, Apostrophe's Express module responds to this event by listening for connections. If your goal is to do something just before that happens, you should listen for apostrophe:ready instead.

# Parameters

  • isTask: A boolean value indicating whether the process was started as an Apostrophe task.
handlers(self, options) {
  return {
    'apostrophe:run': {
      async handlerName(isTask) { ... }
    }
  };
}
modules/any-module/index.js

# @apostrophecms/db events

Events emitted by the @apostrophecms/db module.

# reset

Invoked after all collections are dropped from the database in the @apostrophecms/db:reset command line task.

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'reset': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/db/index.js

# @apostrophecms/doc events

Events emitted by the @apostrophecms/doc module.

# fixUniqueError

Triggered when a unique key error is thrown by MongoDB. Apostrophe uses this to modify the slug property to make it unique.

# Parameters

  • req: The active request
  • doc: The database document that triggered the error
handlers(self, options) {
  return {
    'fixUniqueError': {
      async handlerName(req, doc) { ... }
    }
  };
}
modules/@apostrophecms/doc/index.js

# afterReplicate

Triggered after Apostrophe automatically replicates certain documents across all locales, including parked pages and piece types with the replicate: true option. This runs once during startup.

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'afterReplicate': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/doc/index.js

# @apostrophecms/doc-type events

These events are emitted by all page type and piece type modules since they extend @apostrophecms/doc-type. In most cases it will be best to watch for the event from a piece type or page type module rather than the doc type module.

If specifically watching events on @apostrophecms/doc-type, as opposed to modules that extend it, it will normally be important to check the type of the document in question before proceeding with the handler's work.

# beforeInsert

Triggered just before Apostrophe inserts a document into the database for the first time.

# Parameters

  • req: The active request
  • doc: The document data being inserted into the database
  • options: Any options passed from the insert method
handlers(self, options) {
  return {
    'beforeInsert': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# beforeUpdate

Triggered just before Apostrophe updates an existing document in the database.

# Parameters

  • req: The active request
  • doc: The document data being updated in the database
  • options: Any options passed from the update method
handlers(self, options) {
  return {
    'beforeUpdate': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# beforeSave

Triggered just before Apostrophe either inserts or updates a document. Invoked immediately after beforeInsert and beforeUpdate in their respective cases.

# Parameters

  • req: The active request
  • doc: The document data being saved to the database
  • options: Any options passed from the saving method
handlers(self, options) {
  return {
    'beforeSave': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterInsert

Triggered just after Apostrophe inserts a document into the database for the first time. The doc._id property is available at this point.

# Parameters

  • req: The active request
  • doc: The document data being inserted into the database
  • options: Any options passed from the insert method
handlers(self, options) {
  return {
    'afterInsert': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterUpdate

Triggered just after Apostrophe updates an existing document in the database.

# Parameters

  • req: The active request
  • doc: The document data being updated in the database
  • options: Any options passed from the update method
handlers(self, options) {
  return {
    'afterUpdate': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterSave

Triggered just after Apostrophe either inserts or updates a document. Invoked immediately after afterInsert and afterUpdate in their respective cases.

# Parameters

  • req: The active request
  • doc: The document data being saved to the database
  • options: Any options passed from the saving method
handlers(self, options) {
  return {
    'afterSave': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# beforeDelete

Triggered just before Apostrophe permanently deletes an existing document from the database.

# Parameters

  • req: The active request
  • doc: The document being deleted from the database
  • options: Any options passed from the deleting method
handlers(self, options) {
  return {
    'beforeDelete': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterDelete

Triggered just after Apostrophe permanently deletes an existing document from the database.

# Parameters

  • req: The active request
  • doc: The document being deleted from the database
  • options: Any options passed from the deleting method
handlers(self, options) {
  return {
    'afterDelete': {
      async handlerName(req, doc, options) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterArchive

Triggered after a document is archived when saving it.

# Parameters

  • req: The active request
  • doc: The document being archived
handlers(self, options) {
  return {
    'afterArchive': {
      async handlerName(req, doc) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterRescue

Triggered after a document is rescued (the opposite of archiving) when saving it.

# Parameters

  • req: The active request
  • doc: The document being rescued
handlers(self, options) {
  return {
    'afterRescue': {
      async handlerName(req, doc) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# beforePublish

Triggered just before a draft document is published.

# Parameters

  • req: The active request
  • data: An object containing the following properties:
    • draft: The draft document data
    • published: The document data as it will be published
    • options: Any options passed from the publish method
    • firstTime: A boolean value, true if the document has never been published before
handlers(self, options) {
  return {
    'beforePublish': {
      async handlerName(req, data) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterPublish

Triggered just after a draft document is published.

# Parameters

  • req: The active request
  • data: An object containing the following properties:
    • draft: The draft document data
    • published: The document data as it will be published
    • options: Any options passed from the publish method
    • firstTime: A boolean value, true if the document has never been published before
handlers(self, options) {
  return {
    'afterPublish': {
      async handlerName(req, data) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterRevertDraftToPublished

Triggered after a draft document is reverted to the most recent published state. This is separate from the undo and redo features in the user interface.

# Parameters

  • req: The active request
  • result: An object containing the following property:
    • draft: The new draft document
handlers(self, options) {
  return {
    'afterRevertDraftToPublished': {
      async handlerName(req, result) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# afterRevertPublishedToPrevious

Triggered after a published document is reverted to the most recent "previous" state (the previous published version). This is separate from the undo and redo features in the user interface.

# Parameters

  • req: The active request
  • result: An object containing the following property:
    • published: The new published document
handlers(self, options) {
  return {
    'afterRevertPublishedToPrevious': {
      async handlerName(req, result) { ... }
    }
  };
}
modules/@apostrophecms/doc-type/index.js

# @apostrophecms/express events

Events emitted by the @apostrophecms/express module.

# afterListen

Triggered after the Express module begins listening for connections.

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'afterListen': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/express/index.js

# compileRoutes

Not intended for project use. Triggered prior to middleware and route registration. Used to get all modules to compile their respective routes for registration. To add custom routes, configure the appropriate properties of your module, (e.g., apiRoute, restApiRoute).

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'compileRoutes': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/express/index.js

# @apostrophecms/login events

Events emitted by the @apostrophecms/login module.

# deserialize

Triggered on every request made when a user is logged in, populating req.user.

# Parameters

  • user: The user's data from the database
handlers(self, options) {
  return {
    'deserialize': {
      async handlerName(user) { ... }
    }
  };
}
modules/@apostrophecms/login/index.js

# @apostrophecms/migration events

Events emitted by the @apostrophecms/migration module.

# after

Triggered after all data migrations have run. The database is now in a stable state.

There is no data included with the event for handlers.

handlers(self, options) {
  return {
    'after': {
      async handlerName() { ... }
    }
  };
}
modules/@apostrophecms/migration/index.js

# @apostrophecms/page events

Events emitted by the @apostrophecms/page module.

# serveQuery

Triggered just before the database query executes to find the best matching page for a request. This can be used to make final adjustments to the query.

# Parameters

  • req: The active request
  • query: The database query that will execute
handlers(self, options) {
  return {
    'serveQuery': {
      async handlerName(req, query) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# serve

Triggered just before a requested page is served.

# Parameters

  • req: The active request
handlers(self, options) {
  return {
    'serve': {
      async handlerName(req) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# notFound

Triggered when Apostrophe fails to find a matching page for a request, just before the 404 response. This is a final chance to do extra work to find a matching page and assign the URL to req.redirect.

# Parameters

  • req: The active request
handlers(self, options) {
  return {
    'notFound': {
      async handlerName(req) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# @apostrophecms/page-type events

These events are emitted by all page type modules since they extend @apostrophecms/page-type. In most cases it will be best to watch for the event from a page type's module rather than the @apostrophecms/page-type module.

If specifically watching events on @apostrophecms/page-type, as opposed to modules that extend it, it will normally be important to check the type of the page in question before proceeding with the handler's work.

# beforeUnpublish

Triggered just before a page's published document is deleted, leaving only a draft document.

# Parameters

  • req: The active request
  • published: The published document that is about to be unpublished
handlers(self, options) {
  return {
    'beforeUnpublish': {
      async handlerName(req, published) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# beforeMove

Triggered just before a page is moved from one position in the page tree to another.

# Parameters

  • req: The active request
  • page: The page being moved
  • target: The page used as a target for positioning in the page tree
  • position: The position to place the page in relation to the target: before and after insert the new page as a sibling of the target; firstChild and lastChild insert the new page as a child of the target
handlers(self, options) {
  return {
    'beforeMove': {
      async handlerName(req, page, target, position) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# afterMove

Triggered just after a page is moved from one position in the page tree to another.

# Parameters

  • req: The active request
  • page: The page being moved
  • data: An object containing the following properties:
    • originalSlug: The page's slug prior to moving
    • originalPath: The page's path prior to moving
    • changed: An array of all pages that were changed by the move, including children of the moved page
    • target: The page used as a target for positioning in the page tree
    • position: The position to place the page in relation to the target
handlers(self, options) {
  return {
    'afterMove': {
      async handlerName(req, page, data) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# afterConvert

Triggered after page data is run through the schema module's convert method, validating its data to the page type's field schema.

# Parameters

  • req: The active request
  • data: The data being saved to the page, prior to schema conversion
  • page: The page as it will be saved, following schema conversion
handlers(self, options) {
  return {
    'afterConvert': {
      async handlerName(req, data, page) { ... }
    }
  };
}
modules/@apostrophecms/page/index.js

# @apostrophecms/piece-type events

These events are emitted by all piece type modules since they extend @apostrophecms/piece-type. In most cases it will be best to watch for the event from a piece type's module rather than the @apostrophecms/piece-type module.

If specifically watching events on @apostrophecms/piece-type, as opposed to modules that extend it, it will normally be important to check the type of the piece in question before proceeding with the handler's work.

# beforeUnpublish

Triggered just before a piece's published document is deleted, leaving only a draft document.

# Parameters

  • req: The active request
  • published: The published document that is about to be unpublished
handlers(self, options) {
  return {
    'beforeUnpublish': {
      async handlerName(req, published) { ... }
    }
  };
}
modules/@apostrophecms/piece-type/index.js

# afterConvert

Triggered after piece data is run through the schema module's convert method, validating its data to the piece type's field schema.

# Parameters

  • req: The active request
  • data: The data being saved to the piece, prior to schema conversion
  • piece: The piece as it will be saved, following schema conversion
handlers(self, options) {
  return {
    'afterConvert': {
      async handlerName(req, data, piece) { ... }
    }
  };
}
modules/@apostrophecms/piece-type/index.js

# @apostrophecms/search events

Events emitted by the @apostrophecms/search module.

# determineTypes

Triggered after the search module identifies the document types to include in search results. This is a chance to change the included types.

# Parameters

  • types: An array of document type names
handlers(self, options) {
  return {
    'determineTypes': {
      async handlerName(types) { ... }
    }
  };
}
modules/@apostrophecms/search/index.js

# beforeIndex

Triggered just before the search index page is served, after the page's results are stored on req.data.docs.

# Parameters

  • req: The active request
handlers(self, options) {
  return {
    'determineTypes': {
      async handlerName(req) { ... }
    }
  };
}
modules/@apostrophecms/search/index.js

# @apostrophecms/template events

Events emitted by the @apostrophecms/template module.

# addBodyData

Not intended for project use. Triggered just before a body data object is added to a request prior to rendering a page. A module's getBrowserData and enableBrowserData are better places to work on this data in project code.

# Parameters

  • bodyData: The body data object as it has been constructed
handlers(self, options) {
  return {
    'addBodyData': {
      async handlerName(bodyData) { ... }
    }
  };
}
modules/@apostrophecms/template/index.js