Build AddOns with Content Dialog

Overview

The Content Dialog Method is the simplest way to build Custom AddOns when your AddOn logic and UI are hosted within the same application as the Beefree SDK editor. This method allows you to use JavaScript handler functions that run in your application's context, giving you direct access to your app's data, services, and UI components without the complexity of iframe communication.

Quick Setup

1. Create AddOn in Console

Before writing any code, you must first create the addon configuration in the Beefree SDK Developer Console. This establishes the addon's identity and settings that your code will reference.

Log into developers.beefree.io:

  • Navigate to your app → AddOnsCreate a custom AddOn

  • Fill out the form (Name, Type, Handle, etc.)

  • Method: Select Content Dialog

  • Handle: Remember this! You'll need it in code

2. Configure beeConfig

The beeConfig object is where you define how Beefree SDK behaves, including your addon handlers. The contentDialog.addOn.handler function is called whenever users interact with your addon, and it receives three parameters: resolve (to insert content), reject (to cancel), and args (context information). This handler function is the heart of the Content Dialog method—it's where you determine what content gets inserted based on your business logic.

Add your handler to beeConfig:

const beeConfig = {
  container: 'bee-editor',
  
  contentDialog: {
    addOn: {
      handler: (resolve, reject, args) => {
        // Check which addon triggered this handler
        if (args.contentDialogId === 'my-addon-handle') {
          // Your addon logic goes here
          // Call resolve() with a content object to insert content
          // Call reject() to cancel the operation
          
          resolve({
            type: 'html',
            value: {
              html: '<div>Hello World!</div>'
            }
          });
        }
      }
    }
  }
};

3. Initialize Beefree SDK

Once your beeConfig is defined with the handler, you initialize the Beefree SDK with your authentication token and configuration. The bee.start() method loads the editor with an optional template parameter, which can be a saved email template JSON or undefined for a blank canvas. This initialization connects your handler function to the Beefree editor, making your addon functional.

Handler Function

The handler is called when users interact with your AddOn. Understanding the handler function signature is crucial—it follows a promise-like pattern where you either resolve with content to insert or reject to abort. The args parameter provides valuable context like which specific addon was triggered and whether it was opened automatically via Direct Open, allowing you to create sophisticated conditional logic.

Handler Arguments

The args object contains contextual information about how and why your handler was invoked. The contentDialogId matches the handle you created in the Developer Console, allowing a single handler to manage multiple addons. The hasOpenOnDrop boolean indicates if the addon was triggered via Direct Open (automatic on drop) versus manual opening. The metadata property contains any previously saved custom data if the user is editing existing content, enabling stateful addons that remember their configuration.

Implementation Patterns

Pattern 1: Immediate Resolution

This pattern resolves instantly without user interaction, perfect for addons that generate or fetch content programmatically. When the handler is called, it immediately creates a content object and resolves, inserting the content into the editor. This is ideal for auto-generated content like timestamps, random images, pre-formatted text blocks, or any content that doesn't require user configuration.

Insert content immediately without user interaction:

Use when: Content doesn't require user input (e.g., auto-generated content, default blocks, timestamps).

Pattern 2: With Modal Dialog

This pattern shows a custom UI for user input before inserting content. Your handler opens a modal or dialog (using your application's UI framework), waits for the user to make selections or provide input, then resolves with the configured content when they confirm. If they cancel, you call reject() to abort the insertion. This gives users full control over what content is inserted while maintaining a guided workflow.

Show a dialog for user input, then resolve:

Use when: Users need to make selections or provide input (e.g., text editors, image selectors, configuration dialogs).

Pattern 3: Multiple AddOns

When you have multiple custom addons registered in the Developer Console, you can handle them all in a single handler function by checking args.contentDialogId. The switch statement routes each addon to its appropriate logic, keeping your code organized while supporting diverse addon types. This pattern is particularly useful when different addons share common functionality or data sources—you can reuse helper functions and maintain all addon logic in one place.

Handle different AddOns with a switch statement:

Use when: Managing multiple Custom AddOns in one handler.

Pattern 4: Conditional Logic with Direct Open

The Direct Open feature allows addons to insert content automatically when dragged onto the stage, without requiring the user to manually open a dialog. This pattern detects whether the addon was triggered via Direct Open (args.hasOpenOnDrop === true) and provides different behavior: automatic insertion with default content for drag-and-drop, or opening a full configuration dialog when manually triggered. This creates an efficient workflow where users can quickly insert default content but still have access to full customization when needed.

Different behavior based on how AddOn was triggered:

Use when: Combining Direct Open with manual triggering for flexible user workflows.

Content Object Structure

Every call to resolve() must include a properly formatted content object that matches Beefree's schema for the addon type. The type property specifies what kind of content you're inserting (image, html, button, etc.), the value object contains the type-specific properties and configuration, and the optional mergeTags array defines personalization fields for dynamic content. Understanding these schemas is critical—incorrect structures will cause insertion to fail silently or produce unexpected results.

Every resolve() call requires a properly formatted content object:

Examples by Type

Each addon type has its own specific schema requirements. Below are examples showing the minimal required properties for common addon types—these are the building blocks you'll use in your handler's resolve() calls.

Image:

HTML:

Button:

Paragraph:

Mixed Content:

See AddOn Types for complete schemas.

Complete Example

This comprehensive example demonstrates a working implementation with multiple addons, Direct Open support, conditional logic, and error handling. It shows how to structure your beeConfig with the addOns array for Direct Open configuration and a unified handler that manages different addon types with appropriate workflows. This pattern represents real-world addon development—multiple addons with different behaviors, user interaction patterns, and error handling all working together in one cohesive system.

Error Handling

Proper error handling is essential for production addons—it prevents silent failures, provides useful debugging information, and gives users clear feedback when something goes wrong. Always wrap async operations in try-catch blocks, validate that your content objects have the required properties before resolving, and provide meaningful error messages. Calling reject() with an error ensures Beefree knows the operation failed and can respond appropriately.

Always handle errors properly:

Using Custom Metadata

Custom metadata allows you to store additional information with your content that persists when users save and reopen their emails. This is incredibly powerful for creating stateful addons that remember their configuration, track content sources, or maintain relationships with external systems. When a user edits content that was inserted by your addon, Beefree provides the original metadata in args.metadata, allowing you to reconstruct the addon's state and pre-fill your UI with the previous configuration.

Store custom data with your content:

Troubleshooting

Issue
Solution

AddOn not appearing

Verify plan level supports custom addons, check that handle matches Developer Console exactly

Dialog not opening

Check browser console for errors, verify handler function is defined in beeConfig

Content not inserting

Validate content object schema matches addon type, check for missing required properties

Multiple clicks needed

Ensure resolve() or reject() is always called exactly once in all code paths

Button not displaying

Verify padding and border-radius values are numbers, not strings

Last updated

Was this helpful?