HomeGuidesAPI Reference
Submit Documentation FeedbackJoin Developer CommunityOptimizely GitHubOptimizely NuGetLog In

Global functions

This topic describes and provides examples of global functions in Optimizely Connect Platform (OCP).

Global functions are very similar in nature to regular functions with the notable exceptions being they do not execute in an installation sandbox (single OCP account) and they are versioned differently. Global functions are typically required as webhook receivers when providers do not support the registration of webhooks at the installation (OCP account) level. Instead, a single webhook is used for all accounts with installation information provided as part of the http request via a query string parameter, http head, post body field, etc. The main purpose of a global function is to provide routing to regular function endpoints defined in your application.

Versioning is very different from versioning of regular functions. The global function implementation that is executed will always be the highest version of your application currently deployed within OCP. This is an important detail and care should be taken when new versions of your application are deployed to ensure that they are always backwards compatible.

The Basics

Like regular functions, global functions must be defined in your application's app.yml file and marked as global using the global property.

functions:
  handle_event_global:
    entry_point: HandleEventGlobal
    description: Relays handle_event calls the appropriate install function
    global: true

Global functions that are defined in the app.yaml are provided a public URL in the following format:

https://function.zaius.app/<app_id>/<global_fn_name>

Global functions have access to the request just like a regular function but are limited to only the shared Key Value Store storage instance. In addition, account context information is missing and all API calls via the ODP node-sdk are not permitted.

Example Function

/**
 * Relays an event to a function.  Setup here is during the Lifecycle#onInstall 
 * hook a record of the external tracker id -> zaius installation id is persisted in
 * the shared key value store.  This information is used by the global function to
 * lookup the correct endpoint url of the function and relay the request to it.
 */
export class HandleEventGlobal extends App.GlobalFunction {
  /**
   * Relay an event to an install fn
   * @returns App.Response as the HTTP response
   */
  public async perform(): Promise<App.Response> {
    // ODP account information is provided in the query string of the hook 
    // request
    const trackerId = this.request.params['tracker_id'] as string;
    logger.info(`HandleEventGlobal call for tracker ${trackerId}`);
    if (!trackerId) {
      return new App.Response(400, 'Missing required tracker_id parameter');
    }

    // find the installation id
    const installation = await storage.sharedKvStore.get(trackerId);
    if (!installation) {
      return new App.Response(404, `Install not found for tracker ${trackerId}`);
    }

    return this.relay(installation.installId as number);
  }

  private async relay(installId: number): Promise<App.Response> {
    // get all the hook endpoints for the installation
    const fns = await App.functions.getEndpoints(installId);
    logger.info(
      `Relaying hook for install ${installId} to: ${fns.handle_event}?email=${this.request.params['email']}`
    );

    // relay the request to the handle_event fn endpoint
    const result = await fetch(`${fns.handle_event}?email=${this.request.params['email']}`, {
      method: 'POST',
      body: this.request.body
    });

    // return resulting info in the response
    return new App.Response(result.status, result.body);
  }
}