Content Dialog

  1. The problem
  2. A flexible solution
  3. An interactive UI layer
  4. What it does
  5. How it works
  6. Merge tags
  7. Special links
  8. Merge contents
  9. Display conditions
  10. Custom rows
  11. Save rows

The problem

When designing a message or a landing page with the BEE editor, there might be cases in which users of your application insert a merge tag, add a link to an image, or apply a conditional statement.

It’s all good, until…

  • What if you have 400 merge tags? You can feed an array of merge tags to the editor, but that’s not going to cut it.
  • What if it’s a 6,000 product database? How will they locate the right one? Special Links is not the right fit.
  • And what if a display condition needs to be built on-the-fly?

A flexible solution

Since the BEE editor is used in hundreds of applications, and since each of them is facing different user experience challenges like the examples mentioned above, we decided that this was really a case where one size does not fit all.

So we engineered a solution that puts you in control.

If your users want to insert a merge tag or a display condition, you control how that will happen. You can overlay a window on top of the editor, for example, and display a simple search box, a list of categories to browse or a complex configurator to build an advanced conditional statement.

We call this feature Content Dialog.

Content Dialog

An interactive UI layer

Content Dialog allows you to build user interfaces for your users to locate & insert merge tags, links, and conditional statements. I lets you establish an interaction layer between the editor and your application (e.g. you show a pop-up window) that allows your users to locate/build/insert specific content (merge tags, links, conditional statements). And you’re in full control of the UI.

For example, imagine you want your customers to be able to quickly locate a link to a product page and assign that link to a button, image, or text. Content Dialog will let you build the right user experience.

Here is a visual example of what you could accomplish in that find a product link scenario.

Content Dialog feature in BEE Plugin

The user experience in this interaction layer is entirely up to you. In the example above, the user clicked on “Find a product” (or alike) in the editor, and a modal window was shown, with a search box in it. Since you decide what the user experience will be like, you are fully in control of how users will select and insert:

For each type of content, you can define the action that will be triggered in your application (e.g. display a modal window), and the text that will be displayed in the BEE editor’s UI to trigger that action (e.g. “Locate a merge tag”), keeping a consistent UX with other areas of your application.

What it does

Content Dialog introduces new call-to-actions in the editor UI. Depending on the type of content, the call-to-action will be rendered as a button, a link or a drop-down choice (see below a detailed list of UI changes).

The text for the action is defined by the host application, so you can use your own wording to provide a better experience.

An example of a possible workflow when the user clicks on a content dialog action:

  1. The editor will start waiting mode (same as when the save action is triggered)
    • This mode prevents from editing and keeps the focus on the user selection
    • The waiting mode is interrupted if the host application cancels the action
  2. The host application will display to the user a UI element to select or define a content item
  3. When the selection is done, the host application closes the UI and passes it to the editor
  4. The editor receives from the host application the selected content and exits waiting mode
  5. The content is applied to the selected item

The same example applied to special links (link to a product) in a text selection:

  1. The editor starts waiting mode
  2. The host application displays an overlay that hides the editor and lists the categories of products to link. The user browses them to find the desired product and selects it.
  3. The editor receives the link and exits waiting mode
  4. The link is applied to the selected text

 

How it works

To set up the content dialogs you will need to add the contentDialog object to beeConfig:

 




contentDialog: {
	specialLinks: {
		label: 'Custom text for links',
		handler: function(resolve, reject) {
			// Your function
		}
	},
	mergeTags: {
		label: 'Custom text for merge tags',
		handler: function(resolve, reject) {
			// Your function
		}
	},
	mergeContents: {
		label: 'Custom text for merge contents',
		handler: function(resolve, reject) {
			// Your function
		}
	},
	rowDisplayConditions: {
		label: 'Custom text for display conditions',
		handler: function(resolve, reject) {
			// Your function
		}
	},
	externalContentURLs: {
            label: 'Custom text for custom rows',
            handler: function(resolve, reject) {
                // Your function
        }
    },
	saveRow: {
    	handler: function (resolve, reject, args) {
        	// Your function
    	}
	}
}


You can add all the dialogs, some of them or only one. Is up to your application to create them for all the users or a segment, as there are no related server-side settings, you can customize them for each editor start.

All the dialogs use the same pattern, but the returned object must match the element pattern (described in the following section).

 

label

Defines the text displayed in the editor UI.

 

handler

Is a function with a Promise-like signature.
This function lets you use your own logic to retrieve the desired value.
Once the value is available, you must call the resolve(value) function to pass it to the editor.
In case you want to cancel the operation, call the reject() function.

A resolve or reject call is mandatory. If you miss this step, the editor will remain in waiting mode.
Error management on the host application must call the reject function to unblock the editor.

 

Examples

Simple application of a link action



contentDialog: {
  specialLinks: {
    label: 'Add an Example Link',
    handler: function(resolve, reject) {
      resolve({
        type: 'custom',
        label: 'external special link',
        link: 'http://www.example.com'
      })
    }
  },
}


A very simple example of how to apply a Special link.

When the user clicks on Add an Example Link, the URL http://www.example.com is applied to the selection (a button, an image or a text).

The waiting mode will not be perceived, and there is no cancel action.

 

Apply a link with a delay



contentDialog: {
  specialLinks: {
    label: 'Add an Example Link after 2 seconds',
    handler: function(resolve, reject) {
      setTimeout(function() {
        resolve({
          type: 'custom',
          label: 'external special link',
          link: 'http://www.example.com'
        })
      }, 2000)
    }
  },
}


Same as the previous example, but the waiting mode will display for two seconds before applying the URL.

 

Opening a dialog UI element



contentDialog: {
  specialLinks: {
    label: 'Custom text for links',
    handler: function(resolve, reject) {
      openMySpecialLinkDialog() // Replace this with your application function
        .then(specialLink => resolve(specialLink))
        .catch(() => reject())
    }
  },
},


In this example the openMySpecialLinkDialog() should be replaced with a function that opens a modal window (or other element) of the host application, where the user can select or build a link.

The selection is then returned as the value of specialLink to the resolve() function.

A cancel action will trigger the reject() function instead.

Returned value syntax

Values must use the same pattern used in the beeConfig object.

The returned object is validated against the expected format.

If the validation fails, an error will be returned in the browser console:

E.g., Error getting content rowDisplayConditions, the item is malformed.

These errors will not trigger any visible notification in the UI.

Merge tags

Configuration



contentDialog: {
	mergeTags: {
		label: 'Apply dynamic syntax',
		handler: function(resolve, reject) {
			//your function goes here
		}
	},
},


You can add a new action, available in the text toolbar, and associated with the merge tag element in BEE:

Most common use cases:

  • Your application has a high number of placeholders and needs to provide a categorization or search form
  • Placeholder availability depends on options that the user can select while building the message
  • You want to display the same UI your users already know and use in your application
  • You need to separate merge tags from other text placeholders

 

Value



{
	name: 'Placeholder name', // Will not be shown
	value: '{{ syntax }}' // Text string that will be added
}


The name parameter may be later displayed if the user selection is saved and loaded in beeConfig on subsequent requests.

Here is a visual example of a hypothetical user experience:

Configuration



contentDialog: {
	specialLinks: {
		label: 'Search a post link',
		handler: function(resolve, reject) {
			//your function goes here
		}
	},
},


Links are applied to different contents, so, when you define a link dialog action, it will be displayed in:

The text-toolbar, as happens with merge tags

An image or button action

Most common use cases:

  • Apply links to products or news using a categories pattern, a search form or a visual browser
  • Apply special parameters or configuration to certain links with a wizard or form
  • You want to display the same UI your users already know and use in your application

 

Value



{
    type: 'A link type', // will not be shown
    label: 'Text', // Will be used as default text when text is not selected
	link: 'http://...' // The URL that will be applied. Placeholders can be used
}


The type parameter may be lately displayed if the user selection is saved and loaded in beeConfig on later requests.

Merge contents

Configuration



contentDialog: {
	mergeContents: {
		label: 'Set up a new product recommendation',
		handler: function(resolve, reject) {
			//your function goes here
		}
	},
},


The content dialog adds a button to the merge content list:

Most common use cases:

  • Set up the content and/or layout for a product recommendation
  • Set up the content and/or layout for a dynamic advertising
  • Set up the content and/or layout for another type of targeted content

Notice that, to display the Dynamic content tile in the contents panel, you must configure mergeContents in beeConfig with at least one predefined item.

 

Value



{
	name: 'Content name', // Will be displayed in the editor UI and in the message
	value: '{{ syntax }}' // Text string that will be added to the HTML output (will be show in the preview)
}


Display conditions

Configuration



contentDialog: {
	rowDisplayConditions: {
		label: 'Open builder',
        handler: function(resolve, reject) {
			//your function goes here
        }
    },
},


A new button will be available in the display condition widget. In this example, the button says “Open builder”, which is the label shown in the JSON configuration file shown above.

Most common use cases:

  • Display a condition builder or form to target a segment of recipients
  • Display a form to create a loop with the row dynamic contents, as product recommendations

 

Value



{
	type: 'A category for this condition', // Will not be shown
	label: 'Condition', // Will be displayed as the condition name
	description: 'Small text describing what the condition does', // Will be displayed in the editor UI to identify the condition action
	before: '{% if something == \'Condition\' %}', // Will be added before the selected row
	after: '{% endif %}', // Will be added after the selected row
}


The type parameter may be later displayed if the user selection is saved and loaded in beeConfig on subsequent requests.

An example

In this example, a window is shown to users when they click on the button to open the builder.

Custom builder of display conditions

The UI is entirely up to the hosting application. Here, the developer decided to offer some fields at the top where the Display Condition can be named and described, an area below it where parameters, values, and operators can be selected, and a preview on the right.

When users click on “Confirm”, the information is passed back to the editor and shown in the properties panel.

Custom display condition

Of course, it can be edited in the editor like any other Display condition, if the user has the rights to do so.

Edit custom display condition

And here is another, visual example of a hypothetical user experience of Content Dialog applied to Display Conditions:

Custom rows

Configuration



contentDialog: {
    externalContentURLs: {
            label: 'Search products',
            handler: function(resolve, reject) {
                // Your function
        }
    }
}


The content dialog adds a new item, using your text label, in the Rows drop-down:

Most common use cases:

  • Import a set of products or news, as custom rows, using a categories pattern, a search form or a visual browser
  • Set up the row layout for a set of predefined contents
  • Set up rows with dynamic content to build dynamic sections that provide product recommendations, QR or bar codes, advertising content, etc.

 

Value



{
    "name":"Results name", // Will be added as a new choice in the rows drop-down
    "value":"https://..." // Will be used to get the list of rows
}


This response will:

  1. Create a new drop-down choice with the provided name
  2.  Display the rows provided by the URL in the rows panel

Notice that in the rows list, names returned by the content dialog display as highlighted elements to give them further visibility over starting choices.

The content dialog can be used as many times as the user needs and, depending on the response, the behavior may change:

1. Returning the same name

This overwrites the existing results, keeping the same name in the drop-down.
This behavior perfectly matches our example above, where the host application returns “Your search results” every time the content dialog is resolved.

2. Returning a new name

This creates a new drop-down choice, keeping the previous results as selectable elements. Previous results are available directly in the drop-down.
Usage example:

A more complex implementation

In this screencast, you will see a more complex implementation of Content Dialog applied to Custom Rows: users search a content library for blog posts, find the blog posts they want to use in their newsletter, and find them in the editor as new rows that can be dragged and dropped.

Save rows

Configuration



contentDialog: {
    saveRow: {
        handler: function (resolve, reject, args) {
            // Your function
        }
    }
}


Unlike the rest of content dialog configurations, Save rows doesn’t use the label parameter as the UI element is a save icon displayed on the selected row (and in the row’s properties panel):

The save rows content dialog is a mandatory step in the Save rows workflow.

The resolve function must return metadata for the selected row. The metadata section of the rows schema allows you to keep track of row-specific information.

The args object in the handler function returns to the host application metadata already applied to the selected row.

Value



{
    "name":"Row name", // Mandatory metadata
    "Category":"A row category" // If you provide category management for saved rows
    "...":"..." // You can add as metadata as your application needs
}


This response will provide metadata that is added to the row in the message before it’s provided through the Save Rows callback.

The row name is the only required metadata and it’s displayed as the row title in the Rows panel:

  • A string of plain text that identifies the row.
  • Displayed in the row card when the row is shown in the Rows panel.
  • Used for text searches within the Rows panel

 Check the Saved rows metadata section for further details on recommended metadata.