Custom events are a way to define a workflow in your page that can be reused multiple times ("functions" in a code-driven language).
As a general rule in programming, whether it's on Bubble or in a traditional, code-driven language, you want to limit as much as you can redundant instructions, workflows, or lines of code. This helps having a leaner application and makes debugging, modifications, and maintenance much easier.
If you find yourself repeating the same logic, in other words the same sequence of actions, in more than one workflow, you can optimize your design by using a "custom event" that you will trigger in more than one workflow. For instance, if a user has two ways to sign up to a service, and the sign up flow does more than simply signing the user up, but also sends an email, some analytics, etc., this would be great candidate for a custom event. You would move the repeated sequence of actions into a custom event and use a Trigger custom event action in both workflows that sign the user up.
Defining a custom event is similar to defining a regular workflow. You pick an event and then add some actions. The event type here is 'Custom event', which is similar to other events, and can have a condition applied to it. One particular field is the ability to define a type of thing for this workflow. For people familiar with traditional programming languages, the custom event is a function and the data you send can be compared to the parameter. The type of thing for the custom event can be a database type you have defined in your app, or a simple type like text, number, etc.
As soon as you have defined a type of thing for the custom event, you will be able to access 'this thing' in the Expression Composer in the following actions. For instance, if a custom event takes a user, you will be able to send an email to 'This Workflow User's email'. This expression will be evaluated with the user that was actually sent with the triggering action. If you want to reuse the same custom event in more than one page, you can add the custom event in a reusable element. Doing so, any page that has this reusable element will have access to the custom event.
Once a custom event has been defined, you can add some actions to your workflows to use this workflow. Just pick the 'Trigger custom event action' (or the 'Trigger custom event action from a reusable element' action if you added the event in a reusable element).
If a type of thing has been defined, you will have to pick a thing to send for each action. The type of the thing needs to match the type of thing that was defined as the workflow level, and type inconsistencies will be flagged as issues. Note that the thing is not optional and has to be filled (since the custom event may access the 'Current Workflow Item').
You can also schedule a custom event to occur at a later time.
You may wonder whether there's a difference between triggering a custom event and scheduling a custom event to occur with 0 delay. Yes, there is.
Let's say you have a parent workflow that has some actions, then a "Trigger a custom event" action, then some more actions. When the parent runs that Trigger action, the parent will pause and wait for the custom event to complete before running the actions that come after it. This is convenient in part because the custom event will be able to see the context of what happened in the actions before it in the parent workflow.
In contrast, if you schedule the custom event to occur with delay 0, that custom event could end up running in parallel to the rest of the parent workflow.
When a workflow is triggered in Run-mode and hits a trigger a custom event action, the first workflow will pause, the custom event will be run till completion, and the first workflow will resume. Using the debugger can be very helpful to understand the flow of actions if you are hitting some difficulties setting things up.