Dev Guide
Dev GuideUser GuideGitHubNuGetDevCommunityDoc feedbackLog In

Functions

Describes Optimizely Connect Platform (OCP) functions, which are stored in the src unctions directory for your app.

Functions are small, executable blocks of code typically triggered off of a real-time event. An app can have any number of functions stored in the src/functions directory. Common examples of functions include:

  • Subscription to a list
  • Order purchase/refund/cancellation
  • Marketing consent update survey submission
  • Product review/rating

Typically, functions are triggered by an HTTP request (a webhook), although you can also use functions to populate app settings form fields. This document covers functions for handling webhooks. For more information about how to use functions as a data source in app settings forms, see Remote select options.

Define functions

Define functions in your application's app.yaml file, for example:

functions:
  event_handler: #<-- name used for form sources and reference within the app
    entry_point: Event #<-- File and Class name from src/functions folder
    description: Processes incoming events

Below are the requirements for any functions you define in your app.yaml file:

Example function:

import * as App from '@zaiusinc/app-sdk';

export class Event extends App.Function {
  public async perform(): Promise<App.Response> {
    
    // processing logic here
    
    return new App.Response(200);
  }
}

Webhook URLs for functions

Functions that you define in the app.yaml file are provided a public URL in the following format: https://[REGIONAL_DOMAIN]/[APP_ID]/[FUNCTION]/[UUIDv4]

For development and testing purposes, you can get the exact URL of an app's functions using the ocp directory list-functions command. For example:

$ ocp directory list-functions ocp_shakedown vdl
https://function.zaius.app/ocp_shakedown/shakedown/e8533888-b63e-4270-9c52-************

In the app code, you can get the URL using the App-SDK getEndpoints method. For example:

import { functions } from '@zaiusinc/app-sdk';
let webhookURL = (await functions.getEndpoints())['event_handler']

You should then register the URL with the source of the event. The process for registering the URL depends on the third-party service that sends events.

🚧

Important

You must define any publicly available functions (for example, webhooks) in the app.yml file.

Functions have access to the HTTP request path, query parameters, headers, and body. For example, the base URL for a function may look like the following: https://function.staging.zaius.app/my_app/cart/5f57ecbb-ef28-4a25-9056-3ea98994e2a5/

You can support additional paths and query parameters added to your URL. For example: https://function.staging.zaius.app/my_app/cart/5f57ecbb-ef28-4a25-9056-3ea98994e2a5/update?cart-id=12345

The path and query parameters are accessible to your function as well as the body and headers of the HTTP request. For example:

import * as OCP from '@zaiusinc/app-sdk';

export class Event extends OCP.Function {
  public async perform(): Promise<App.Response> {
    const path = this.request.path; // "/update"
    const cartId = this.request.params['cart-id']; // "12345"
    const body = this.request.bodyJSON || {}; // '{"request_id":"12345","products":[...], ...}'
    const headers = this.request.headers; // { "Content-Type": "application/json", ... }

    // processing logic here

    return new App.Response(200);
  }
}

Function example

import * as App from '@zaiusinc/app-sdk';
import {logger} from '@zaiusinc/app-sdk';
import {z} from '@zaiusinc/node-sdk';
import {IncomingEvent} from '../data/IncomingEvents';
import {transformToCustomer} from '../lib/transformToCustomer';

/**
 * Example event handler.
 * Expects a request in the form:
 *  url: https://[webhook-url]/?email=<email>
 * with a JSON body.
 * Fires an ODP event and updates the customer's name in ODP
 */
export class HandleEvent extends App.Function {
  /**
   * Handle a request to the handle_event function URL
   * this.request contains the request information
   * @returns App.Response as the HTTP response
   */
  public async perform(): Promise<App.Response> {

    const email = this.request.params['email'] as string;

    if (!email) {
      return new App.Response(400, 'Missing required email parameter');
    } else {
      try {
        const event = this.request.bodyJSON as IncomingEvent;

        // TODO: transform your event data into ODP API calls
        if (event.customer) {
          await z.customer(transformToCustomer(event.customer));
        }
        await z.event({
          type: event.type,
          identifiers: {
            email
          },
          data: {
            action: event.action
          }
        });

        // return the appropriate status/response
        return new App.Response(200);
      } catch (e) {
        logger.error(e);
        return new App.Response(500, `An unexpected error occurred: ${e}`);
      }
    }
  }
}