Read this page to learn more about important the core concepts of implementing Self-hosted saved rows.
This feature is available on Beefree SDK Core plan and above. If you're on the Essentials plan, upgrade a development application for free to try this and other Core-level features.
Saved Rows allows end users to select a row in a design and save it for later use. More specifically, it allows end users to submit a request to the host application to save a piece of content and turn it into a reusable element. The host application, using externalContentURLs
, can feed these saved elements back to the builder as rows that can be dragged into other designs.
In the following video tutorial, you will learn how to implement Self-hosted Saved Rows in an application that has embedded Beefree SDK.
You can also reference the sample code in our GitHub repository used throughout this video.
When the Self-hosted Saved Rows feature is enabled, a Save icon is added to the action icons when a row is selected. The following image displays an example of a row with the Save icon enabled in the upper right-hand corner.
The Save icon is also available in the Row properties panel when a row is selected. The following image displays an example of this.
By clicking on the Save icon, the end user triggers a request to the host application to store the row’s JSON document.
This JSON document includes the following:
Row structure and settings.
Contents and their settings.
All style settings.
The host application needs to determine the following:
Where to store the JSON documents that describe these saved rows.
If and how to display them to end users of the application.
Whether to allow end users to edit them individually.
When and how to feed them back to the builder, using the externalContentURLs
parameter.
Take the following steps to enable Self-hosted Saved Rows in the Beefree SDK Developer Console:
Log in to the Beefree SDK Console.
Locate the application you'd like to activate Self-hosted Saved Rows for.
Click the application's corresponding Details button.
You will be prompted to the Application Details page.
Click the View more link under the Application configuration heading.
Navigate to the Saved Rows section.
Toggle on the Self-hosted on your own infrastructure option.
Click Save on the upper right-hand corner to save your changes.
The following image displays where the toggle is located in the Beefree SDK Developer Console.
Once the feature has been turned on at the global level, in Beefree SDK Console, you may want to disable Saved Rows on a per-user basis. This can be accomplished via the client-side configuration document that you feed to an application when initializing the builder for a certain user.
Why? Because you may decide to make the feature available to different users of your application:
depending on the subscription plan that they are on (you could push users to a higher plan based on the ability to save a row for later);
depending on the purchase of an optional feature (same);
to allow “beta” users to see it while keeping it hidden from the rest of your users;
etc.
Here’s how to do so:
Enable Saved Rows in the Beefree SDK Console. as mentioned above.
Add the configuration parameter saveRows to the beeConfig document:
Set it to false for all users that cannot saved rows.
Here is a simple example:
Visit the Saved Rows section of the Reusable Content page to learn more about the end user experience with saved rows. You can also reference the white label end user documentation on Saved Rows to learn more.
The following GIF provides a quick visual example of the end user experience:
When the saved row action is triggered by the user, the builder starts the following sequence:
Metadata Content dialog Used to collect data from the host application and add it to the row object. Metadata helps your application to identify a row, overwrite a previously saved version, etc.
Saved Rows Callback. Function that returns the row to the host application.
The following describes the recommended workflow to implement saved rows in a host SaaS application.
Enable Saved Rows in the Beefree SDK Console as described above.
Load a Beefree SDK template.
Select the row you want to save and make note of the new save icon.
Click the save icon to trigger a Metadata Content Dialog. To successfully handle this step, you must complete these tasks:
Add a Metadata Content Dialog object to your beeConfig. This configures your handler.
Implement the handler method to open a dialog (e.g., modal window) to collect any metadata you wish your users to input when saving a row.
The dialog should contain a form and complete the following specs:
Save the row returned in the Metadata Content Dialog’s args object.
Collect metadata from the end-user, such as row name.
Merge the metadata with the row, so it can be immediately returned to the application.
Return a metadata object to the application so the stage can immediately use the data.
The application will update the selected row on the stage with the returned metadata.
The application will trigger the onSaveRow callback with the following details:
JSON of the selected row
HTML preview of the selected row
Page Partial of the selected row contained in a page. Use this JSON document to allow users to edit a saved row independently of any message or landing page that might use it.
The application will refresh the Rows panel to reload the selected rows data feed.
Host app will listen for onSaveRows callback and update the previously saved records with the HTML preview.
To display saved rows in the Rows tab, add them to the list of rows available to users by leveraging Custom Rows.
The rows are organized in lists that are displayed based on your rows configuration. Use the metadata submitted by your users to categorize them, creating multiple lists of rows: this can significantly improve the user experience.
The following code sample shows an example of a rowsConfiguration
that displays saved rows organized by category:
In this code snippet example, the Rows tab will show:
Empty rows
Default rows
Headers
Footers
Product grids
Main article
… retrieving the arrays of JSON documents for custom rows (externalContentURLs) from the URLs specified.
These custom rows names (Headers, Footers, Product grids, etc.) could be the result of a “Category” metadata entered by the user at the time the row was saved. The input could be the result of:
The user writing a new category name for the selected row.
The user selecting from a list of existing categories, previously created by the user, or set up by you.
Here is another example that shows saved rows organized in the Rows tab based on the campaign type:
You can set a category's maximum rows using the following configuration"
For more information on setting a category's maximum rows, visit Manage Reusable Content.
Accessing, and organizing saved rows is intuitive with Saved Rows Management. With this feature, we’ve introduced a new action in the list of saved rows that your application can intercept to handle changes in this list itself. This means you can now delete, rename, or re-organize your saved rows, right inside the builder.
Visit the Saved Row Management Actions section of the Manage Reusable page to learn how to configure edit and delete row options for your application's end users.
Saved Rows Management also comes with the ability to load any external rows via an instance method instead of an external URL. In addition, since you can now access rows through your application, you don’t need to perform authentication.
To start, define a hook in your application configuration. The hook method should be named getRows
and will be nested under the hooks
object, as follows:
Following that, amend your rowsConfiguration
object with the additional parameters:
The handle
parameter to utilize in your getRows
handler from the previous step
The isLocal
parameter to let the application know to use the hook handler
When the getRows method is invoked, utilize the 3rd parameter to obtain an argument containing the handle value of the row being requested. Use the handle to determine which set of rows should be returned.
Finally, we can call the resolve method, passing in an array of savedRows.
If you are using a React application, be sure to pass a new rows array and not a reference to a row state. Otherwise, the rows state may be “stale” and won’t update in the side panel.
The following is the basic structure of the row’s JSON schema. Simply put, the schema is the structure of your saved rows data feed.
NOTE: The row schema is complex and we do not recommend creating rows programmatically. Therefore, there is no schema reference of the row itself. However, you can add your own parameters to the row’s metadata or use our Simplified Row Schema to generate them programmatically from existing content.
The metadata section of the rows schema allows you to keep track of row-specific information.
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
category A category can be useful for organizing your feeds on the Rows tab.
id A handle that identifies the row in the host application’s data storage.
idParent Useful to track rows that were saved from previously saved rows. Keeping track of where a row came from allows you to implement additional editing features.
dateCreated The date the row was created: useful for filtering/sorting rows for content management purposes in your application. It can also help with technical support tasks.
dateModified The date a saved row was updated: useful for filtering/sorting rows for content management purposes in your application. It can also help with technical support tasks.
userId To let your application decide whom can edit or saved rows.
tags Useful to create filters, management, search, and in general to organize the content in your application.
The metadata content dialog is triggered by the save icon in Beefree SDK. This step is required to provide Beefree SDK with information about the row, such as its name and/or id. The Metadata Content Dialog is added in the same manner as other Content Dialogs, such as Merge Tags. Please review the Content Dialog section for more details about how to use Beefree SDK’s Content Dialog feature.
An example Metadata Content Dialog configuration can be found below.
The metadata resolve function now accepts an options
object in which you can pass the property synced
to determine if the row needs to be saved and treated by the builder as synced.
When the Metadata Content Dialog is completed, the application triggers the Saved Rows callback. The callback returns the following details:
rowJSON JSON of the selected row.
rowHTML HTML preview of the selected row
pageJSON Page Partial of the selected row contained in a page (for editing a row as an independent piece of content).
With Edit Single Row mode you can offer an easy way for your end users to edit saved rows individually, using a tailored UI built to modify the row structure, content, and style settings without worrying about messing up with the overall design of the email campaign, landing page, or pop-up.
Enabling a more modular approach to saved rows simplifies how users can design and act on content: updating small details in a saved row, saving it, then deploying it to existing templates becomes a matter of minutes. If you want to learn more about how to leverage Edit Single Row mode to safely modify a Saved Row, take a look at the dedicated technical documentation.
This feature is available on Beefree SDK and above. If you're on the Essentials plan, for free to try this and other Core-level features.
This page provides an overview of Saved Rows and their key benefits.
Saved Rows in Beefree SDK optimize the content creation process by allowing users to save, categorize, and manage reusable rows for future use. When this feature is enabled, users can simply click the Save icon on a row within their design and store it for later. This ensures quick access to preferred layouts and design elements across multiple projects.
Save Rows are particularly helpful in the following scenarios:
Standardizing Footers: Save a footer row with contact details, social media links, and copyright information. Use it across multiple email templates to ensure consistency.
Designing E-Commerce Product Grids: Create reusable rows showcasing product images, descriptions, and call-to-action buttons. Pull these rows dynamically from an e-commerce catalog for up-to-date content.
Creating Promotional Banners: Save promotional rows with pre-configured styles and messaging. Reuse them across campaigns to maintain branding and reduce setup time.
There are several benefits to utilizing saved rows. This section outlines benefits for both end users and the host applications.
Saved Rows enable end users to:
Save and reuse content: Create emails, landing pages, and popups, apply their own style and brand guidelines, and save all of that hard work inside of a row and reuse it at a later date. After saving a row, they can still edit the row and make any adjustments to the content blocks inside of it.
Flexible Categorization: Organize rows into intuitive categories to easily find and reuse them later on.
Easily Manage Rows: Edit the name and category of a saved row easily. Or, delete rows if they are no longer needed.
Saved Rows enable host applications to:
Enhance the User Experience: Enable users to save, categorize, and manage rows efficiently.
Customize Permissions: Enable or disable end user permissions to delete, edit, manage, or add Saved Rows.
Make Saved Rows Available to Select Users: Control which users can and cannot save rows.
When enabled, Saved Rows allow end users to select a row in their design and save it. This process involves:
Selecting a row in the builder.
Clicking the Save icon in the toolbar or row properties panel.
Storing the row’s structure, content, and styles as a JSON document in your chosen storage solution.*
Once created and saved, end users can reuse saved rows through the builder’s ROWS tab.
There, users can:
Browse saved rows by category.
Search for rows using metadata like row names or descriptions.
Drag and drop rows into their designs for immediate use.
There are two paths you can take to activate and store Saved Rows for your application:
Read this page to learn more about the core concepts of implementing self-hosted saved rows, and to follow along in a tutorial with an example of how to implement it.
Clone the the sample project demo to follow along with the steps outlined on this page.
In this guide you will:
Enable the saved rows feature in your developer console.
Configure the Beefree SDK with the proper hooks.
Build a frontend with content dialogs (for saving, editing, and deleting rows).
Manage metadata (names, categories) for each saved row.
Create API endpoints (GET, POST, PUT, DELETE) on your backend.
Set up a database to store row data.
Connect your frontend with the backend through these endpoints.
Test your endpoints using tools like Postman or Insomnia.
Each step below is designed to build upon the previous ones, guiding you from initial setup to the final integration. This guide explains not only what to do, but also why each step is important and how it interacts with the other parts of the overall solution.
Note: Self-hosted saved rows is a highly customizable feature. While this guide provides one approach to implementing Self-hosted saved rows, it is important to note that there are several ways you can customize this implementation based on your application's needs. While this guide mentions core implementation concepts, such as toggling the feature on, setting up the beeConfig
accordingly, and so on, it is also important to note it mentions approaches that you can customize, such as designing frontend modals, configuring your database, and so on.
Overview and Context
Creating the user interface for end users to create, save, and manage saved rows.
Creating, configuring, and connecting your own database to store the saved rows data.
Creating CRUD operations with your own API endpoints.
Enabling this toggle is a prerequisite for all the integration steps outlined in the subsequent sections. Without this toggle, none of the custom hooks or API endpoints will function properly.
Steps to Complete
To enable Self-hosted saved rows for your application, follow these steps:
Navigate to the application you'd like to configure Self-hosted saved rows for.
Click on Details.
Navigate to Application configuration and click View more.
Scroll to the Saved Rows section.
Toggle on the Self-hosted on your own infrastructure option.
This step ensures your environment is configured to use self-hosted rows.
Overview and Context
The Beefree SDK must be configured with custom hooks to handle your saved rows. This involves defining a client configuration type and setting up a configuration object that includes your custom getRows
handler. This step is crucial because it connects the SDK with your backend API, allowing it to fetch and update saved rows dynamically.
Code Snippet
Reference the Type Definition & Client Config in the following code snippet.
Inline comments explain each key property. This configuration connects Beefree SDK to your backend via the custom hook, ensuring that saved rows are properly managed.
Additional Context
By correctly configuring Beefree SDK, you guarantee that the editor will know how to fetch and display saved rows. The getRows
hook becomes the bridge between the editor and your data source, while the rowsConfiguration
object provides the necessary settings for displaying external content based on categories.
Overview and Context
Next, you will create the user interface (using a framework like React) that interacts with Beefree SDK. This step involves building modals for saving, editing, and deleting rows. The frontend is responsible for gathering user input and communicating with the backend, so the UX needs to be both responsive and intuitive.
Key Tasks
This step covers the following key tasks:
Create a React component (e.g., SavedRowsEditor
) that will render the Beefree SDK editor.
Fetch saved rows and categories during the component's mounting phase.
Implement modal dialogs that capture user input (e.g., row name, category) and trigger backend updates.
Code Snippet
The following code snippet is for the Save Row Modal.
This snippet demonstrates the creation of a modal dialog that collects user input for a new row. Inline comments detail each part of the process.
Code Snippet
The following code snippet shows the React Component Skeleton.
Additional Context
This step ties together your user interface with the Beefree SDK and backend. By using modal dialogs for CRUD actions, users can interact with the saved rows feature directly within the Beefree SDK editor. The React component handles data fetching and state updates, ensuring that the UI remains in sync with the backend.
Overview and Context
Managing metadata is critical for organizing and retrieving saved rows. Metadata such as the row's ID, name, and category allow you to group rows, edit them, and build dynamic external content URLs. In this step, you'll update and refresh external content URLs based on current categories and see how the Beefree SDK configuration uses this data.
Key Tasks
Define the metadata structure (ID, name, category) in your saved rows.
Create a function to update the external content URLs whenever categories change.
Ensure that the Beefree SDK's configuration (rowsConfiguration
) is dynamically updated with these URLs.
Code Snippet
The following code snippet shows an example of Updating External URLs.
This snippet illustrates how to construct the array of external content URLs based on the list of categories fetched from your backend.
Supplementary Code Snippet
The following code snippet shows an example Beefree SDK Row Configuration.
Inline comments explain that the rowsConfiguration
object receives a dynamically generated array from the updateExternalContentURLs
function. This integration ensures that the Beefree SDK editor always uses the latest category data.
Additional Context
Managing metadata effectively allows you to organize saved rows into logical groups. When a new category is added or updated, refreshing the external content URLs ensures that the editor displays the correct endpoints for fetching rows. This dynamic behavior is crucial for maintaining data consistency across your frontend and backend.
Overview and Context
The backend API endpoints serve as the communication bridge between your frontend and database. These endpoints are responsible for creating, reading, updating, and deleting saved rows. Proper endpoint implementation ensures that user actions in the frontend correctly update the database and that the Beefree SDK editor receives the latest data.
Key Tasks
This section covers the following key tasks:
Set up an Express server.
Implement CRUD endpoints (GET, POST, PUT, DELETE) to handle row operations.
Validate incoming data to ensure that required metadata (name and category) is present.
Code Snippet
The following code snippet shows a POST Endpoint example.
Additional Context
Overview and Context
Using SQLite in this example, you must set up a database to persist saved rows. Creating the appropriate table schema ensures that all necessary data (such as metadata and row content) is stored reliably. This database will be accessed by your API endpoints to perform CRUD operations.
Code Snippet
The following code shows shows the SQLite Table Creation.
Additional Context
A well-defined database schema is essential for data consistency and performance. In a production environment, you might choose another database system, but this SQLite example provides a simple starting point to demonstrate the concept.
Overview and Context
To enable real-time data interactions, your frontend must connect to the backend via HTTP requests. This connection allows the Beefree SDK editor to fetch saved rows and update data based on user actions. The integration of fetch calls in your React component ensures that the user interface is always synchronized with the underlying data store.
Code Snippet
The following code snippet shows Connecting via Fetch.
Additional Context
By establishing these fetch connections, the frontend remains dynamic and responsive. Changes in the backend are quickly reflected in the UI, which is crucial for maintaining a seamless user experience.
Overview and Context
Before deploying your solution, it's critical to test all endpoints to verify that CRUD operations work as expected. Using tools like Postman or Insomnia allows you to simulate API requests and ensure that both the backend and frontend are interacting correctly. Comprehensive testing helps catch potential errors early.
Testing Steps
Take the following steps to test your endpoints.
GET /rows: Verify that all saved rows are returned.
GET /rows/:category: Confirm that rows for a specific category are fetched.
GET /categories: Check that the unique list of categories is correct.
POST /rows: Ensure that a new row is added when metadata is provided.
PUT /rows/:id Validate that an existing row is updated correctly.
DELETE /rows/:id Confirm that a row is removed successfully.
By following this guide you have:
Enabled self-hosted saved rows in your developer console.
Configured the Beefree SDK with a custom getRows
hook.
Built a user-friendly React component with modals to save, edit, and delete rows.
Managed metadata (name and category) for each row, and integrated dynamic external content URLs into the Beefree SDK configuration.
Created complete API endpoints (GET, POST, PUT, DELETE) on your Express backend.
Set up an SQLite database (or your preferred database) to store row data.
Connected your frontend to the backend using standard HTTP requests.
Tested your endpoints to ensure a smooth integration.
Multiple Storage Options: Activate, store, and manage Saved Rows using either or options.
*Beefree SDK offers for this: or .
Both paths provide their own set of benefits and limitations. It is important to familiarize yourself with the benefits and limitations of each option to choose the storage and activation solution that is best for you and your application's needs. For more detailed information on both activation routes, reference and Implement .
Learn more about to discover the best option for you.
Important: This guide includes sample code snippets from a . You can reference the code for this sample integration in . As you read along in this tutorial, you can copy, edit, and customize the sample code for your own use and experimentation.
Before writing any code changes, ensure you first activate the Self-hosted on your own infrastructure toggle in your . This global setting tells Beefree SDK that your application will handle:
This is in contrast to the other toggle in the Saved Rows section of the Application Configurations within the Developer console, which .
Log in to the .
This endpoint not only creates new rows but also validates incoming data, ensuring data integrity. Similar endpoints (PUT, DELETE, GET) must be implemented to support full CRUD functionality. You can reference the full code for each endpoint in the sever.js file in .
Each step is interconnected: enabling the feature makes it available in Beefree SDK, the frontend's modals interact with backend endpoints, and the dynamic configuration ensures that data remains consistent and up-to-date. The full code files (including the complete React component, server code, and configuration files) are available in the . This guide shows smaller, focused snippets to help you quickly understand the implementation while leaving the complete examples for your reference in the repository.
This feature is available on Beefree SDK Core plan and above.
With Hosted Saved Rows, you can provide your end users with the option to save and manage reusable content directly within the builder. Hosted Saved Rows can be activated through a toggle within the Developer Console, which makes it an excellent option for those who are interested in a fast implementation of Saved Rows. Once you toggle this feature on, your end users will be able to save the rows they create within the builder, and reuse them easily in the future. They can also perform actions to manage the rows that they save, such as renaming them, deleting them, categorizing, or recategorizing them. This page covers the steps you need to take to successfully implement Hosted Saved Rows.
The following video tutorial discusses what Saved Rows are, how reusable content can support your end users throughout their content creation journeys, and how you can implement Hosted Saved Rows in your application.
To enable Hosted Saved Rows for your application, follow these steps:
Log in to the Developer Console.
Navigate to the application you'd like to configure Hosted Saved Rows for.
Click on Details.
Navigate to Application configuration and click View more.
Scroll to the Saved Rows section.
Toggle on the Hosted on the Beefree SDK Infrastructure option.
Read the pricing information in the popup closely, because additional fees may apply.*
If you'd like to proceed, confirm you read and understand the pricing to activate the feature.
Important: Keep in mind that charges apply for saved rows that are hosted not only in your production applications, but also for your development applications.
*Hosted Saved Rows have the following pricing structure:
Allotment
Not available
Not available
100 Hosted Rows
250 Hosted Rows
1000 Hosted Rows
Price for extra unit
$0.35/Hosted Rows
$0.25/Hosted Row
$0.20/Hosted Row
Note: Visit our Usage-based fees article to learn more about Hosted Saved Rows pricing.
Once you've successfully enabled Hosted Saved Rows in the Developer Console, you'll access the following:
Rows saved by your application's end users will be stored and hosted in the Beefree SDK storage option.
End users can save rows directly to the hosted infrastructure and retrieve them as needed.
Once you successfully enable Hosted Saved Rows within the Developer Console, your application's end users will have access to a new Save icon for each row, and other options for managing the rows they save.
The Hosted Saved Rows UI includes the following experience for end users:
End users can save a row using the Save icon.
They have the ability to name and categorize rows.
They can edit a row's name or category and save those changes.
End users can decide to reuse or delete rows through the Rows tab in the side panel.
They can also use the vertical three dots to add and manage categories.
Reference the Hosted Saved Rows end user documentation for more information on the end user steps and experience.
Hosted Saved Rows includes advanced permissions to control how rows and categories are accessed and managed. These permissions allow you to define user capabilities, such as editing or deleting rows.
The permissions you can control for Hosted Saved Rows through Advanced Permissions are the following:
canDeleteHostedRow
: Allows or prevents deleting hosted rows.
canEditHostedRow
: Enables or disables editing of hosted rows.
canManageHostedRowCategory
: Controls whether end users can manage row categories.
canAddHostedRowCategory
: Determines if end users can add new categories.
Keep the following behaviors in mind when setting advanced permissions:
If both canDeleteHostedRow
and canEditHostedRow
are set to false
, the row menu will be hidden.
If both canManageHostedRowCategory
and canAddHostedRowCategory
are set to false
, the category management menu will be hidden.
The following configuration displays an example of the rows
object inside of advancedPermissions
:
Once Saved Rows is enabled globally in the Developer Console, you can disable it for specific users using the saveRows
parameter in the beeConfig
document. This lets you control access based on subscription plans, feature purchases, or beta testing.
Take the following step to disable access for specific users:
Set saveRows
to false
for users who shouldn’t have access.
The following code provides a simple example of how to add the saveRows
configuration parameter and set it to false
to make the feature unavailable to select users.
The following image shows the save icon when the end user clicks on the row.
The following image does not show the save icon when the end user clicks on the row. This behavior occurs after adding saveRows
to your beeConfig
and setting it to false
.
Similar to how you may want to restrict which end users can save rows based on subscription type, plan type, and so on, you can also control which users have access to the ROWS tab within the builder altogether. By default, the ROWS tab is available within the builder.
You can remove the ROWS tab by:
Add the defaultTabsOrder
parameter to your beeConfig
and set it to: ['content', 'settings']
or ['settings', 'content']
.
Note: The only difference between these two options is the order in which they will appear in the builder.
Keep in mind the defaultTabsOrder
is a string array (string[]
).
The tab order represented in the snippet below with content
first and settings
second, results in the visualization displayed in the image after.
In the following image, the ROWS tab is no longer available to the end user. In the following image, the ROWS tab is no longer available to the end user and the order of the tabs are Content first and Settings second.
The tab order represented in the snippet below with settings
first and content
second, results in the visualization displayed in the image after.
In the following image, the ROWS tab is no longer available to the end user and the order of the tabs are Settings first and Content second.
Reference the Hosted Saved Rows Webinar to learn more about other customizations that are compatible with Hosted Saved Rows. The webinar discusses the following topics:
How to enable Hosted Saved Rows
How to use Advanced Permissions with Hosted Saved Rows
How to restrict which end users can save rows
How to customize the modals related to Hosted Saved Rows
How to use Hosted Saved Rows with Content Services API
Reference the sample code in this GitHub repository to follow along with the webinar tutorial.
Visit the Hosted Saved Rows page to also learn more about the following topics: