Frontend Events

Use frontend events to make sure your interface responds to Flow changes quickly and reliable

The Embedding Flow section introduced how to add Flow to your webpack and launch a session. The library provides a bit more functionality on top that you can use to polish your integration:

Closing the modal

If you want to close the Flow modal programatically, you can at any time by calling

flow.close();

Events

The Flow client provides a simple events API that emits updates about what is happening inside the modal. The examples below includes the TypeScript types associated with each event:

UI Events

interface OpenEvent {
  topic: "ui";
  action: "opened";
}

interface CloseEvent {
  topic: "ui";
  action: "closed";
}

// Receive events about when the Flow UI opens and closes
flow.on("ui", (event: OpenEvent | CloseEvent) => {
  if (event.action === "closed") {
    console.log("Modal closed");
  } else {
    console.log("Modal opened");
  }
});

Error Events

interface ErrorEvent {
  topic: "error";
  message: string;
}

// Receive events about errors launching flow
flow.on("errors", (event: ErrorEvent) => {
  errorTracker.notify(`Flow error! ${event.message}`);
});

Session Events

interface CreateEvent {
  topic: "session";
  action: "created";

  data: {
    id: FlowSessionID;
  };
}

interface ResumeEvent {
  topic: "session";
  action: "resumed";

  data: {
    id: FlowSessionID;
  };
}

interface PassEvent {
  topic: "session";
  action: "passed";
}

interface FailEvent {
  topic: "session";
  action: "failed";
}

type SessionEvent = CreateEvent | ResumeEvent | PassEvent | FailEvent;

flow.on("session", (event: SessionEvent) => {
  switch (event.action) {
    case "created":
      console.log("User started a new flow session");
      break;

    case "resumed":
      console.log("User resumed an existing flow session");
      break;

    case "passed":
      console.log("User successfully completed their flow session");
      window.location.pathname = "/verified";
      break;

    case "failed":
      console.log("User failed their flow session");
      window.location.pathname = "/contact_support";
      break;
  }
});

Step Events

type Step =
  | "accept_tos"
  | "kyc_screen"
  | "kyc_check"
  | "verify_sms"
  | "screening";

interface StartEvent {
  topic: "step";
  action: "started";

  data: {
    name: Step;
  };
}

interface PassEvent {
  topic: "step";
  action: "passed";

  data: {
    name: Step;
  };
}

interface FailEvent {
  topic: "step";
  action: "failed";

  data: {
    name: Step;
  };
}

interface PendingReviewEvent {
  topic: "step";
  action: "pending_review";

  data: {
    name: Step;
  };
}

type StepEvent = StartEvent | PassEvent | FailEvent | PendingReviewEvent;

flow.on("step", (event: SessionEvent) => {
  console.log(`User ${event.action} the ${event.data.name} step!`);
  // Output would be something like:
  //
  //    "User started the accept_tos step!"
  //    "User passed the accept_tos step!"
  //    "User started the verify_sms step!"
  //    "User passed the verify_sms step!"
  //    "User started the kyc_check step!"
  //    "User failed the kyc_check step!"
  //
});

Event Firehose

If you want to directly listen to all of these events, you can hook the event firehose like so:

flow.on("all", event => {
  console.log("Received event!", event);
});

NOTE: We provide this events API so that your app's frontend can listen, track errors, pipe information to analytics tools, and enhance your frontend experience so you know how to pick back up once your customer is done with Flow. You should not use Flow events to update your backend state, since the frontend javascript environment is an untrusted environment. An attacker could easily, for example, inject fake events or just forge requests to your backend if you misuse frontend events.