Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Learn how to create an application within the Beefree SDK Developer Console.
In this article, we will discuss how to sign up for an account in the Beefree SDK Developer Console, create an application, and obtain your Client ID and Client Secret.
This article will cover steps for the following processes:
The first step to embedding Beefree’s visual builders in your software is to sign up for a Beefree SDK account.
Take the following steps to sign up for a Beefree SDK account and subscribe to the Free plan:
Navigate to the Developer Console Sign Up page.
Note: If you already have an account, navigate to the Developer Console Login page instead.
Complete the required information to sign up or login.
You will be redirected to the dashboard.
In the dashboard, click Add new subscription.
You will be redirected to a page that asks you to provide a name for your new subscription.
Type in a name and click Next.
You will be redirected to a page that asks you to select a subscription plan. If you'd like to subscribe to the Free version, click on the corresponding Select plan button Free plan type. If you'd like to subscribe to a paid plan, select the paid option that works best for your needs.
A confirmation message will appear confirming that you selected the Free plan and that you will not be charged anything. Click Confirm to confirm your subscription the the free plan.
While the plan is free, ensure that you familiarize yourself with the scenarios in which charges would apply. The following image shows a plan summary displaying instances of when charges apply.
Enter and confirm your billing address.
Enter and confirm your card information by clicking Place Order.
You will be redirected your new Free plan subscription.
Once that’s done, you will be able to log into the Beefree SDK Console. Your dashboard will look like the following image.
You will have the option to activate any or all of the following applications:
Take the following steps to create an application:
Click the Activate button that corresponds with the application you'd like to create.
Type in a name for your new application.
Click Create.
Your application will look like the following in the dashboard once it is activated:
You have successfully created an application. Now, you can enter the application Details and obtain your Client ID and Client Secret.
Click on your application's Details button to view your Client ID and Client Secret. Use these to authenticate when you initialize it.
With your Client ID and Client Secret, you can use our Sample Code to experiment with a simple integration of Beefree SDK. You can also get started with your own implementation of Beefree SDK.
Reference the following related topics to learn more about customizing your applications, creating development instances, and referencing sample code.
Inside the Beefree Developer Console, you have the option to regenerate the Client Secret for your application. To regenerate your application's Client Secret, take the following steps:
Log in to the Beefree SDK Console.
Navigate to the application you'd like to update the Client Secret for.
Click on the application's Details button.
Navigate to Application keys within the application's details.
Click Regenerate to generate a new Client Secret.
You will be prompted to a modal and asked to confirm your application's name.
Complete the App Name field and click Regenerate to complete the action.
Your new Client Secret is now available and ready to use. Your old Client Secret will expire 24 hours after creating the new one. Ensure you replace it in all the necessary environments prior to its expiration.
For 24 hours after regenerating a new Client Secret, you will temporarily have access to two Client Secrets—your old one and your new one. After 24 hours, you will only have access to the new Client Secret for your application.
Create development applications
The Form Block within Beefree SDK allows you to easily create and integrate customizable forms into your application. This feature is particularly useful for capturing user information, feedback, and other data directly through interactive forms. With various pre-built templates and customization options, the Form Block is easy to integrate for developers and intuitive to use for end users.
into page or popup builders is straightforward. The SDK provides intuitive methods to embed forms within your web pages or popups. With drag-and-drop functionality and predefined settings, adding a form to a design can be accomplished in just a few steps, enhancing workflow efficiency for your application's end users.
The Form Block supports a wide range of input types, such as text fields, radio buttons, checkboxes, and dropdown menus. This flexibility ensures that end users can gather the exact type of information they need from the form. Additionally, form submissions can be easily configured to trigger actions, such as email notifications or data storage, providing a robust and integrated data collection solution.
Learn more about to use and integrate Form Block in the following section:
When you load a Beefree application inside the host application, you pass a configuration object with multiple sections that define the characteristics of the UI, UX, and available elements. However, there are cases when you may want to reload this configuration without the need to reload the Beefree application. In these cases, you can use a specific event to update the configuration while the editor is open.
With this event, you can make on-the-fly changes to the user experience. For example:
Updating available categories for Saved rows
Refreshing a Custom header for authorization
Changing Advanced permissions for the current user
Updating settings for the editor’s Content defaults
You can load the configuration changes via a new instance event. Here’s an example:
var newConfig = {
advancedPermissions: {
// new permissions
}
}
bee.loadConfig(newConfig)
Welcome to the Beefree SDK technical documentation!
Beefree SDK is an embeddable no-code email, landing page, and popup builder. It enables your end users to achieve their design goals without writing a single line of code. By embedding Beefree SDK into your application, you'll provide your end users with access to a full suite of design features that include the following and more:
Email builder: A no-code email creation environment that helps end users quickly create beautiful emails. This environment supports your end users in following email creation best practices recommended by industry experts.
Page builder: A no-code landing page creation environment that empowers end users to build visually stunning landing pages. They can use a landing page as a link for a call-to-action (CTA) inside emails, to embed forms and capture information, or to create standalone pages.
Popup builder: The popup builder is a no-code environment that provides end users with the tools they need to build compelling popups that capture attention.
File manager: A tool to manage media assets (images, PDFs, and so on).
Template catalog: A design template catalog that integrates industry best practices to support end users in quickly getting across the finish line with their creations and achieving quick design wins.
AI Writing Assistant: A helpful AI assistant to help end users write their design content.
These builders can easily integrate into your application in minutes. Browse this documentation's latest sample code and implementation guides to get started.
Take the following steps to get started with Beefree SDK in a few minutes:
Create an account to access the Developer Console and obtain your credentials.
Create a new subscription to get started. Beefree SDK offers a generous Free plan that includes each builder type mentioned in the previous section.
Create an application and obtain your Client ID and Client Secret.
Clone the beefree-sdk-sample-client repository, which includes the code for email and popup builder implementations.
Add your credentials, the Client ID and Client Secret from step three, inside the placeholders in the code.
Once the email builder, or popup builder, depending on which environment you chose, opens, you can start experimenting with the SDK's configuration by customizing the configuration parameters in the beeConfig
section of the code.
You can also customize the SDK's configuration inside the Developer Console under the Application configuration section of the application you created.
Learn more about our three embeddable builders.
In addition to our drag-and-drop editors, we also offer a standalone File Manager application, which can be used alongside any of the builders. The File Manager is specifically designed to simplify the organization and management of digital assets, which might happen outside of a content editing session. It is an image and document management user interface that can be launched as a standalone application. This allows your customers to quickly upload or manage assets, without having to load one of the builders.
Learn more about our File Manager and File Storage Options.
Learn more about how our builder AddOns can help you customize your application's offerings.
The Content Services API allows you to perform a number of tasks (e.g. refreshing the HTML for a certain asset) and add features to your application (e.g. converting an email to a PDF document). We continue to release new API methods to help you enrich and personalize the content design experience for your customers.
The Template Catalog API enables you to incorporate design templates into your application. With this API, you can browse, retrieve, and utilize a variety of pre-designed templates to enhance your user's content creation experience. It gives you the flexibility to offer customized design solutions directly within your platform.
Learn more about Content Services API and Template Catalog API.
Browse our sample code to experiment and gain hands-on experience. Get up and running quickly with a simple implementation.
Get your free Client ID and Client Secret in the Developer Console to get started. Experiment with customizing a configuration in the playground. When you're ready, install Beefree SDK.
These products share the same, unique combination of design flexibility and ease of use. Note that the majority of the documentation applies to all builders (and in many cases to the File Manger too), unless otherwise specified.
Saving your end users time when creating designs is more important than ever—especially as AI continues to reshape expectations. Today’s users want to move fast, and increasingly expect to generate polished, on-brand designs with just a prompt or a click. is built to meet that demand. It provides you with the building blocks you need to construct an AI-driven content creation experience for your end users. This provides them with a faster, more flexible way to build emails, landing pages, and popups instantly inside your application.
empowers your team to unlock AI-driven design creation and headless template generation—making it easier than ever to build designs programmatically, and 100% outside of Beefree SDK's visual builders. Whether you're building emails, landing pages, or popups, you can leverage Simple Schema as a lightweight, intuitive format that AI models can easily understand and generate.
is designed for flexibility, making it ideal for AI-assisted and headless workflows. Imagine a tool where users describe the design they want in plain language, and submit that description to an AI agent. On the backend:
An AI model receives the description and generates a Simple Schema-compatible template.
This template is passed to the /v1/conversion/simple-to-full-json
.
The API returns the complete Beefree JSON for the entire template.
The template is loaded in the builder, and the end user can start applying edits in a no-code environment.
The following image displays an example UI with a basic AI Email Design Assistant that connects to Simple Schema on the backend. By building your own UI and AI agent, you can leverage Simple Schema on the backend to programmatically build templates and load them in the Beefree SDK builder for your end users to use.
In the following image, the programmatically-created email template is loaded within the Beefree SDK builder, and ready for editing.
Using for AI-driven design creation offers the following benefits:
AI-ready: A simplified format perfect for machine-generated layouts.
Headless by default: Build and deploy templates entirely outside the visual builder.
Production-ready: Easily convert to Beefree JSON with a single API call.
Efficient: Reduced payload size and faster AI generation.
This endpoint is essential for converting AI-generated or manually assembled Simple Schema templates into full, builder-compatible Beefree JSON. Learn more about how to use this endpoint in the .
Here is a list of terms used frequently throughout the Beefree SDK technical documentation. Things can get a bit tricky when embedding a software application within another software application, so this page is an attempt to create as much clarity as possible. We hope we find it useful. If anything sounds confusing or if you have any suggestions for improvement, please .
Beefree SDK A toolkit that includes white-label, no-code builders for emails, landing pages, and popups. The toolkit also provides a range of components, APIs, sample code, and support services to help you seamlessly integrate into your software a content creation workflow that your customers will love.
Beefree SDK subscription A subscription to the Beefree SDK. There are different , starting with a Free plan. Once you have a subscription, you can create one or more Beefree applications.
Beefree application An instance of any of the no-code tools that can be embedded in your software. They include:
Email Builder
Page Builder
Popup Builder
File Manager
Beefree SDK Console A multi-user administration panel where you can sign up for a Beefree SDK subscription, manage the subscription, and create and configure a Beefree application within a subscription.
Production application An instance of a Beefree application used in your production environment.
Development application An instance of a Beefree application used for development, QA or staging environments. You can create multiple, development applications under a production application.
Host application Your software application, which will host one or more Beefree applications.
Beefree system The backend system that interacts with your Beefree application to provide services such as application authorization.
Content Services API A set of in the Beefree system that allow you to perform a variety of tasks connected to the implementation of a content creation workflow.
This page lists and describes the Row Processing category of endpoints within the Content Services API. It also includes interactive testing environments for each endpoint in this category.
The merge
method allows you to update a row across multiple templates. Specifically, it enables the host application to modify an element within an existing JSON document. This means you can implement a feature that updates templates in the background—without requiring any action from your users. It's ideal for merging shared content () into templates that use it—for example, updating the same footer across 30 different email or page templates.
URL: https://api.getbee.io/v1/{collection}/merge
URL: https://api.getbee.io/v1/{collection}/merge-rows
URL: https://api.getbee.io/v1/{collection}/synced-rows
What if a footer is shared by 10 messages and needs to be updated in all of them? The feature was created precisely to address the scenario of content that is shared across multiple emails, pages, or popups, and it is used in conjunction with the Content Services API.
The index
method in the Content Services API lets you retrieve a list of assets that include a specific saved row. This method is essential for determining which assets need to be updated using the merge
method.
Typical Use Cases
Updating shared headers or footers across multiple templates
Modifying expiration dates in seasonal campaigns
Applying price or link changes to reused promotional content
Making any update to shared blocks without manually editing each message
Use the index
method first to locate all impacted assets, then apply changes with the merge
method to ensure content is updated consistently.
This page lists and describes the Designers category of endpoints within the Template Catalog API. It also includes interactive testing environments for each endpoint in this category.
/v1/catalog/designers
HTTP Method: GET
Description: Access a complete list of all Designers in the catalog.
The response is paginated, with a standard display of 200 items per page. You can manipulate the ‘pagesize’ request parameter to control the number of items shown per page.
The following table displays request parameters.
/v1/catalog/designers/:slug
HTTP Method: GET
Description: Retrieve detailed information for a specific Designer, identified by the unique slug present in the URL. This enables the procurement of comprehensive data pertaining to the particular designer, including their portfolio of templates and any associated metadata within the catalog.
This page lists and describes the Tags category of endpoints within the Template Catalog API. It also includes interactive testing environments for each endpoint in this category.
/v1/catalog/tags
HTTP Method: GET
Description: Retrieve a full list of all the Tags in the catalog. Tags are keywords tied to templates, helping you find and sort templates based on certain themes or attributes.
The following table displays request parameters.
Learn how to manage users within the Beefree SDK Developer Console.
You can invite additional users to your Beefree SDK Console. To do so, go to Manage users from the personal menu in the top right.
The user that initially created the account is identified as the account owner and can add users from this page.
Additional users will be identified as admins. The owner may limit access to certain production apps when creating or editing an admin.
The account owner has these additional privileges, compared to admins:
add, edit or delete users, as described above;
turn on , using tokens provided by mobile apps like Google Authenticator or Authy. 2FA can be enabled either for specific users, or account-wide from the Settings & Security section in the personal area ();
change the company’s name, also in Settings & Security.
Learn how to authenticate to access the Template Catalog API's resources.
Beefree SDK's Content Services API uses bearer tokens to authenticate requests. You can create, view, and manage your bearer token in the . All requests must be made over HTTPS and contain the following HTTP Header:
To use the Template Catalog API you will first need to obtain a your API Key—the bearer token you will use to authenticate to make API calls—from the Beefree SDK Developer Console.
To obtain an API Key, take the following steps:
Log in to the .
Navigate to the application you'd like to activate the Template Catalog API for.
Click on the corresponding Details button.
Navigate to the Content Services API section of the Details page.
Click Create New API Key.
A pop up will appear asking you to confirm that you understand may apply.
Click Create Key.
Your API key will appear under the Template Catalog API section of your application details.
We understand that each company has its own unique needs. For that reason, we offer the flexibility of adding multiple Beefree SDK subscriptions within the Developer Console. Through this option, you can take advantage of multiple subscriptions to our product for your teams, business units, and so on.
You can create an additional subscription within the Beefree SDK Developer Console.
To achieve this, take the following steps:
Log in to the
Navigate to your dashboard
Click Add new subscription on the upper right-hand side of the screen
Type a name for your next subscription and click Next
Choose a plan and click Select plan
Confirm the plan you selected
Finalize your additional subscription
This page lists and describes the Categories category of endpoints within the Template Catalog API. It also includes interactive testing environments for each endpoint in this category.
/v1/catalog/categories
HTTP Method: GET
Description: Retrieve a list of all the Templates within the catalog, applying filters based on request parameters.
You can extract a list of all the Categories present within the catalog. This comprehensive list includes all categories under which templates are classified.
The response that you receive is paginated for ease of reading and navigation. It displays 200 items per page by default, providing a comprehensive view of the catalog content.
However, if you wish to adjust the number of items shown on each page, you can use the ‘pagesize’ request parameter.
The following table displays request parameters.
/v1/catalog/categories/:slug
HTTP Method: GET
Description: Retrieve a list of all the Templates within the catalog, applying filters based on request parameters.
Retrieve detailed information about a specific Category using its unique identifier, or slug, which can be found in the URL. This method allows you to access in-depth data related to that particular category, such as its associated templates and related metadata.
Learn how to authenticate to access the Content Services API's resources.
Beefree SDK's Content Services API uses bearer tokens to authenticate requests. You can create, view, and manage your bearer token in the . All requests must be made over HTTPS and contain the following HTTP Header:
To use the Content Services API you will first need to obtain a your API Key—the bearer token you will use to authenticate to make API calls—from the Beefree SDK Developer Console.
To obtain an API Key, take the following steps:
Log in to the .
Navigate to the application you'd like to activate the Content Services API for.
Click on the corresponding Details button.
Navigate to the Content Services API section of the Details page.
Click Create New API Key.
A pop up will appear asking you to confirm that you understand may apply.
Click Create Key.
Your API key will appear under the Content services API section of your application details.
Self-Hosted Saved Rows allow you to control where and how your rows are stored and managed, offering flexibility to meet your application's unique requirements. This option is ideal for teams with development resources who want to integrate row storage into their existing infrastructure.
When users save rows, the data includes layout, content, and style settings. This data needs to be stored and managed, typically in your own database, to make rows available for reuse within your design builder.
Storage Use a database or storage solution to house self-hosted saved rows. Examples of a few options include:
Cloud databases (e.g., AWS RDS, Google Cloud Firestore)
Local databases (e.g., MySQL, PostgreSQL)
Document-based databases (e.g., MongoDB)
Development Resources Ensure your team has the capability to connect your storage to your application. This includes:
Setting up secure storage with proper access controls.
Implementing any necessary API endpoints or backend logic to retrieve, save, and manage rows.
You can directly save and retrieve rows using your own database.
For teams that prefer not to handle row storage and development in-house, we offer . This solution stores rows for you and provides your end users with a UI for saving rows throughout their designing experience. This eliminates the need to create a custom infrastructure.
An overview of page builder within Beefree SDK.
Beefree SDK Page Builder will help your customers create beautiful, responsive landing pages, complete with forms and embedded videos. Combined with our Email Builder, you’ll have the power to deliver to your customers a single, optimized user experience for designing both emails and web pages.
With the Page Builder, your customers can create landing pages and one page sites with
In addition, you will find exclusive features that make sense for web pages, such as forms, embedded videos, and the ability to paste scripts, like an embeddable SurveyMonkey or Typeform survey.
Here are a few examples of web pages your customers can build with:
Product showcase or teaser
Disclaimer (e.g. age verification)
Registration (e.g. events, gated content)
Newsletter subscription
Customer survey
Booking request
Portfolio
They can also create fantastic one page websites, i.e. sites where all the content usually spread in different pages fits nicely into an easy-to-scroll page, complete with menu and anchors to navigate it.
We are constantly improving the user experience: we see the Page Builder as a long-term, ongoing project at Beefree SDK.
MIME types are a standardized way to indicate the nature and format of a file, specifying what kind of data it contains. Groups are categories that aggregate these MIME types for simplified handling and management in applications like File manager. This organization allows for custom limitations and processing based on file type.
The following list shows which specific mime types are mapped to our group names for custom limitations on File manager.
Note: Beefree SDK does not manage heic files at this time.
When working with files, mime types and groups, ensure you consider the following:
The default maximum file size you can upload is 20MB.
If you upload an image wider than 1920 pixels, when the image is uploaded or imported, it will be resized to fit within 1920px. This may cause issues with the image's appearance, including colors that change and GIFs that lose frames. Ensure your images are no wider than 1920px to avoid these issues.
Learn more about .
This page lists and describes the AI Collection category of endpoints within the Content Services API. It also includes interactive testing environments for each endpoint in this category.
The resources in the AI collection accept your template JSON and use generative AI to return text within a JSON object to you.
Prior to getting started with the resources in this collection, ensure you have the following:
Superpowers subscription or higher.
An configured within the .
Content Services API key.
v1/ai/metadata
v1/ai/sms
v1/ai/summary
The debug
parameter in the beeConfig
is an optional object that enables internal debugging features within the Beefree SDK editor. It's designed to help developers inspect configurations, , and more easily during development.
You can pass the debug
parameter directly in your beeConfig
object when initializing the editor. Alternatively, you can set or update it live using the loadConfig
method—no need to refresh the editor.
Example (in beeConfig
):
Set it live (no refresh needed):
The debug
parameter in the Beefree SDK configuration accepts the following parameters:
all
(boolean
): Enables all available debug options (inspectJson
and showTranslationKeys
). Use this during heavy debugging sessions.
inspectJson
(boolean
): Adds an eye icon in the toolbar that allows you to inspect the specific JSON used for that element. Useful for understanding how your configuration is being rendered.
showTranslationKeys
(boolean
): Replaces localized strings with their translation keys throughout the UI. This is especially helpful when debugging i18n issues or checking for missing .
The debug parameter is particularly helpful in the following scenarios:
You're troubleshooting UI rendering issues tied to configuration JSON.
You need to inspect what exact data is being used for rows/modules.
You're working on translations and want to ensure correct keys are being used.
image:
image/*
text:
text/*
video:
video/*
audio:
audio/*
office:
application/msword
application/vnd.lotus-organize,
application/vnd.ms-*
application/vnd.oasis.opendocument*
application/vnd.openxmlformats-*
application/rtf
xml:
application/xml
zip:
application/zip
epub:
application/epub+zip
pdf:
application/pdf
postscript:
application/postscript
font:
application/x-font-otf
application/x-font-ttf
const beeConfig = {
debug: {
all: true, // Enables all debug features
inspectJson: true, // Shows an eye icon to inspect JSON data for rows/modules
showTranslationKeys: true // Displays translation keys instead of localized strings
}
};
beeInstance.loadConfig({
debug: {
all: true
}
});
Authorization: Bearer {token}
Authorization: Bearer {token}
Email Builder: An email editor that makes building gorgeous, mobile-ready emails a breeze.
Page Builder: A delightful tool to design beautiful, effective landing pages in minutes, without writing a single line of code.
Popup Builder: An easy to deploy, true WYSIWYG solution for designing standout popups.
File Manager
Storage Options
Configure Your AWS S3 Bucket
AI Writing Assistant with Multiple Provider Options
Partner AddOns
Custom AddOns
Content Services: Export plain text, transform JSON to HTML, and manage brand styles.
Template Catalog: Add templates to your application.
AI Collection: Use the AI collection to get metadata, SMS, and summary text.
Full-stack application built with NextJS
Official NPM package of Beefree SDK
A simple HTML sample client to start playing with Beefree SDK
Beefree SDK simple React starter
Templates to accelerate the set-up of your Beefree SDK integration.
Explore methods
Developer Console
Playground
Install Beefree SDK
Configuration Parameters
Create an Application
Authorization Process
Learn more about what the Release Candidate Environment is, how to get started with it, and how to integrate it into your development life cycle.
A Release Candidate (RC) Environment is a crucial part of the deployment workflow designed to provide Enterprise customers with additional stability and assurance before a feature reaches full production. Unlike standard releases, which immediately roll out updates to all users, the RC environment acts as an intermediate step. It allows selected customers to access a production-ready version of the latest code before it becomes available to the wider user base. This controlled rollout process mitigates risks associated with unforeseen bugs and ensures a smoother transition. It also mitigates the risk of regressions and rollbacks. By implementing an RC environment, Beefree SDK enables Enterprise customers to conduct their own QA testing on new features, reducing potential disruptions when updates go live.
The following list includes some of the most commonly referenced benefits of utilizing the Release Candidate Environment.
Risk Mitigation: Enterprise customers can validate new updates in a stable, production-like setting before they are fully deployed.
Enhanced Quality Assurance: QA teams can test features in real-world scenarios, catching regressions before broader release.
Predictable Deployment Schedule: A structured release cadence (RC → General → Delayed) ensures smoother rollouts with fewer surprises.
Reduced Need for Rollbacks: The phased approach minimizes critical failures in production, lessening the necessity for emergency rollbacks.
Customer Control: Enterprise customers have additional time to adjust workflows and prepare internal documentation before full adoption.
The RC environment operates within a structured release cycle, ensuring that new updates are progressively introduced. When a new feature is ready for release, it is first deployed to the RC environment. Only Developer applications linked to the RC version can access this release. After a one week waiting period—assuming no major regressions are found—the update moves to the stable version, making it available to non-Enterprise customers. After a week, the update reaches the Delayed version, which is linked to Enterprise Production applications. This phased approach ensures that issues are detected early while maintaining a predictable release schedule.
Reference the following requirements for accessing the Release Candidate Environment prior to getting started with it.
Only available to Enterprise plan customers with Developer applications.
Contact the Beefree SDK team using this contact form and request access to the Release Candidate Environment.
Customers must be aware that while the RC version is production-ready, it is still subject to final testing and potential bug fixes.
The program does not allow for customized release schedules per customer; all Enterprise customers follow the same cycle. Customized release schedules are available on VPC plans. For more information, contact the Beefree SDK team using this contact form and request more information about customized release schedules with VPC plans.
The Release Candidate Environment is specifically designed for frontend features, the JSON-to-HTML parser, and the JSON Bumper. Backend services are not currently covered under this process. Bug fixes, while critical, may bypass the RC process when necessary to expedite resolutions. By adopting the Release Candidate process, Beefree SDK provides Enterprise customers with greater predictability, quality assurance, and peace of mind in managing their integrations.
Synced Rows expands on the foundational capabilities of Save Rows and Edit Single Row Mode, helping users manage rows more effectively. Using the merge-rows
and synced-rows
methods in the Content Services API (CSAPI), you can create an efficient row management workflow. This ensures that when users update content in one row marked as “synced,” those updates are reflected across all connected designs using that synced row.
Cross-design synchronization: Sync saved row contents across multiple linked designs.
Design consistency: Lock rows in linked designs to keep designs uniform.
Editing flexibility: Convert rows from synced to unsynced, making individual changes as needed.
Intuitive edit indicator: Look for the pencil icon at the top-right of synced rows, which provides access to editing options
Auto-updating contacts: Change a contact in one email, and it updates across multiple campaigns.
Effortless re-branding: Edit your logo once and watch it reflect across all designs.
Unified transactional footers: Update details like copyright or social links, and it automatically updates in all relevant email templates.
Row details: This includes structure, settings, and styles.
Content details: Settings and styles of individual content blocks.
Metadata: Any metadata tied to the saved row.
With Edit Single Row Mode you can offer an easier way for your end users to modify a single row with a tailored UI built to edit the row structure, content, and style settings without interfering in the overall design of the email campaign, landing page, or pop-up.
Edit Single Row mode complements both Saved Rows and Synced Rows, because it allows complete control over the content of an individual row (for example, a footer that requires an update) without the need to intervene in a full template's design. This will help you in implementing a more effective way to manage libraries of Saved Rows and Synced Rows with a streamlined design and editing process.
Learn more about injecting custom JS libraries into your Beefree SDK integration.
Enterprise customers can request to inject external JavaScript libraries, like FullStory or Heap, into Beefree SDK when the integration is initialized as part of the server-side configuration.
Custom JavaScript requires a complete technical evaluation by the Beefree SDK development team. The assessment will undergo security, technical and compatibility assessments.
Contact our Sales team and ask to run a script to get started with custom JS libraries injection. Once you contact us, we will take the following steps to complete your request:
Our representative will forward your request to our development team
The development team will review the script and approve it
The script is enabled by our development team
pagesize
int
Set the item number per page
pagesize
int
Set the item number per page
pagesize
int
Set the item number per page
When you log into the Beefree SDK Console you can immediately see what type of applications you have already created under your Beefree SDK subscriptions. To create a Popup application, head over to the Popup Builder Application section and click on Activate.
Once created, head over to “Details” for all server-side configurations. Paid applications allow you to create child development applications, to ease new feature testing, development, and maintenance.
All builders share the same core functionalities, including authentication and configuration. If you have already integrated our Email builder, you can re-use most of your work using the same configuration and callbacks.
Out-of-the-box, the setup and configuration are the same as Email and Page Builder. This section will cover the settings specific to Popup Builder. Check out our Getting Started guide if you’re new to Beefree SDK or unfamiliar with the configuration basics (as seen in the example below).
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
...
}
Loading Popup Builder with no additional settings will give the end-user a beautifully designed popup and workspace to design their content. However, Popup Builder comes with an additional, robust set of configuration options to customize the workspace. This allows the host application to build a workspace that matches their popup’s look and feel and that of the destination page.
For example, the host app can customize…
The popup workspace background to view how the popup will look “in context” on the destination page.
The theme and position of the popup for both desktop and mobile design modes.
Continue reading to learn more on how to customize the workspace, starting with the common settings and working up to a full custom layout.
In Email and Page Builder, the Beefree SDK HTML parser service converts your template into an HTML document customized for email or pages, respectively. However, the Popup Builder will not return a full HTML page because the host application is the final destination. In addition, Beefree SDK Popup Builder doesn’t provide the scripts to control the popup’s behavior, such as opening and closing. Rather, Popup Builder provides the HTML “partials” to embed within your popup’s content area or body.
The HTML partial will come with all the CSS required to look as it did in the preview mode. The parser service will wrap the content with a special container to clear all the host application styles and prevent style conflicts. The HTML output is designed to be embedded into any popup framework or application and still render the way it appears in the builder.
Our Github account has some resources that might help you out when testing and integrating the Popup Builder.
Examples of different implementations and configurations that you can draw from to speed up your development.
A collection of ready-made templates that you can use right away and add to your application.
When you create an application in the Beefree SDK Console, you’ll be asked to select either Page or Email Builder. Paid applications allow you to create child development applications, to ease new feature testing, development, and maintenance.
Page and Email builders share the same core functionalities, including authentication and configuration. If you already integrated our Email builder, you can re-use most of your work by using the same configuration and callbacks. If this is your first approach to our builders, just follow the Installation section in our documentation. All the documentation in this site applies to both products, except where noted.
All builders are available to Beefree SDK customers under the same all-in-one pricing. Please contact your Customer Success Manager for more details.
We aim to provide the foundations needed to build a delightful page building experience. We started with the basic features that are already provided to design awesome email messages and tweaked them to work for Web pages.
Once launched as Page Builder, an application will have a few but noticeable differences from the Email builder experience:
width for pages can be expanded up to 1440px;
the stage can be scrolled horizontally;
the sidebar can be collapsed to provide more workspace – useful when working with larger widths;
there’s a new 6-columns row layout, to take advantage of larger widths;
the preview includes viewport resize, to test responsiveness on various screen sizes;
the HTML block allows using scripts, for improved compatibility with embedded content like surveys. This also includes Javascript, although it cannot be executed within the builder.
If you’re on a paid plan, you will also get support for forms and embedded videos.
You can define and pass forms to the builder, and use the form content block to retrieve and style those forms.
You can use the video content block to embed and playback videos hosted on Youtube and Vimeo, or point to a hosted video in MP4 format.
Managing forms with the Page Builder
A quick primer on how to include forms in a web page.
Our Github account hosts useful resources, including sample code to quick start your integrations.
This page lists and describes the Templates category of endpoints within the Template Catalog API. It also includes interactive testing environments for each endpoint in this category.
/v1/catalog/templates
HTTP Method: GET
Description: Retrieve a list of all the Templates within the catalog, applying filters based on request parameters.
You can execute a search by providing a series of terms within the ‘search’ request parameter. This search will operate on template title, description, category name, collection name, designer name, publication date (‘published_at’), and tags.
The response will encompass a ‘facets’ field, outlining the count of existing Templates across each Category, Collections, Designers, and Tags fields and their sub-fields, considering any applied filters and searches.
The response is paginated, presenting 20 items per page by default. The ‘pagesize’ request parameter enables control over the page size.
The following table displays a list of request parameters.
search
activity, beach, summer
List of terms to search, separated by comma
category
small-business
Filter by category slug
collection
e-commerce
Filter by collection slug
designer
bee-team
Filter by designer slug
tag
activity, beach, summer
Filter by tag name
template_type
Filter by template_type. Choiches are "email" or "page"
pagesize
20
Set the item number per page
published_after
2023-01-01
Filter by published_at after given date
published_before
2023-01-01
Filter by published_at before given date
/v1/catalog/templates/:slug
HTTP Method: GET
Description: Fetch a single template identified by its slug (in the URL).
The Page Builder includes an expanded Video content block for optimized usage of videos on web pages. Videos are added inside an iframe via the HTML5 video tag.
There are multiple ways to add a video to a page built with Beefree SDK. Additional settings allow the video progress bar and loop playback to be turned on or off.
The Embedded mode allows video playback inside the page. It requires the URL of a video hosted on YouTube, YouTube Shorts, or Vimeo.
Same as the embedded option, but the URL provided must point to a self-hosted video in MP4 format. Settings for hiding controls and loop playback apply as well. Please note that the player interface your visitors will experience might slightly vary based on the browser they use.
As a fallback, you may also use the video block for generating a thumbnail, the same way the block works when building emails. Just enter the URL for a video hosted on YouTube, YouTube Shorts, or Vimeo. A thumbnail linked to the video will be created. You may also style the overlay play icon.
YouTube (16:9 aspect ratio)
Public Videos
Unlisted Videos
Videos starting at a certain time
YouTube Shorts (16:9 aspect ratio)
Vimeo
Public Videos
Unlisted Videos
Cinemascope (21:9 aspect ratio)
This page lists and describes the Collections category of endpoints within the Template Catalog API. It also includes interactive testing environments for each endpoint in this category.
/v1/catalog/collections
HTTP Method: GET
Description: You can pull up a full list of all Collections in the catalog. Collections are groups of templates with similar attributes or purposes. This overview can help you understand the types of template groupings available.
The response will be paginated, with 200 items per page default for easy navigation. However, you can change this default by adjusting the ‘pagesize’ request parameter to suit your viewing preferences.
The following table displays request parameters.
pagesize
int
Set the item number per page
/v1/catalog/collections/:slug
HTTP Method: GET
Description: Access a specific Collection using its unique slug found in the URL. This lets you view detailed information about this particular group of templates, including its associated templates and any related details.
Besides the client-side configuration parameters that you can set for your instance of Beefree SDK, you also can specify some server-side configuration options.
To access server-side configurations, log into your Beefree SDK Console and select the application that you wish to configure.
In the application’s details page, locate the area called Application configuration.
Manage roles is used to manage user roles. For details on this feature, see “user roles and permissions“.
Click on Open configuration to manage the server-side settings like:
Toolbar options: affect the UI of the editor
Storage options: determine where the File Manager will store & retrieve images
Content options: define whether certain content elements (e.g. HTML block) are active or inactive
Service options: define whether additional services (e.g. photo search) are active or inactive
is based on the concept of unique users of the editor. A unique user is one that is identified by a unique UID, as described below. The system counts unique UIDs within a billing period, and resets the count to zero at the start of the next billing period.
The UID parameter:
Is an alphanumeric string passed to Beefree SDK throughout the .
Has a minimum length of 3 characters.
Can contain letters from a to z (uppercase or lowercase), numbers and the special characters “_” (underscore) and “-” (dash).
Make sure that you pass a string, not a numeric value. So even if your UID is a number, pass "12345"
and not 12345
.
The UID should not be Personal Data, as indicated in the Beefree SDK License Agreement. Further information about how your use of a Beefree SDK service relates to the EU’s General Data Protection Regulation (GDPR) may be found . Our Privacy Policy, which describes the processing activities carried out by Beefree SDK as Data Controller, is available .
It uniquely identifies a user of the application. When we say “uniquely”, we mean that:
It will be counted as a unique user for .
Images (and other files) used by the user when creating and editing messages will be associated with it and not visible to other users (when using the default storage).
It’s entirely up to you, as the host application, to determine when to use a new UID at the time you initialize the editor for your users. In 99% of the cases: one UID = one CLIENT ACCOUNT in your application. Sub-users of a client account typically share the same UID.
A quick example to help you visualize this.
We use the UID in the File Manager to identify where images will be stored
You typically don’t want client ABC to see client XYZ’s images
So you will use a certain UID for client ABC and another UID for client XYZ
If there are 5 users within client ABC account in your application, however, it’s OK that they see the same images, since they are likely collaborating on the same emails or landing pages, so you don’t need to use a different UID: all 5 will share the same UID.
UIDs in production are counted separately from UIDs in a . For example, if you have the following UID in both a production and development application, the unique UID will be counted twice toward your plan's allotment.
In this scenario, Beefree SDK will treat these as two distinct users, and count this UID twice—once for each environment. Reference for more information on Beefree SDK plan types and their corresponding uid
allotments.
Saved Rows in Beefree SDK empower users to save, reuse, and organize design elements efficiently, which optimizes the creation process for emails, pages, and popups. With Saved Rows, users can categorize rows by themes or criteria, ensuring easy access and consistency across projects.
Beefree SDK offers two hosting options: and . Each option has unique advantages suited to specific organizational needs, resources, and technical requirements. This guide compares the options, helping you choose the best fit for your team.
Hosted Saved Rows offers a fully managed solution, eliminating the need to set up and maintain backend systems. With this option, Beefree SDK handles storage, security, scaling, and updates, allowing your team to focus on delivering a great user experience. In addition to managing storage, this option also provides you with a ready-to-go user interface made available to your application's end users through a toggle in the Developer Console.
This ready-to-go UI enables application end users to:
Save a row and make it available for reuse in the future
Add new saved row categories to organize the rows they save
Edit a saved row's existing name and category
Delete a saved row
Update existing saved rows with the option to save them as new saved rows
Fully managed by Beefree SDK, and activated through a toggle in the Developer Console.
Ideal for teams that want a quick setup without maintaining backend systems.
Offers centralized storage, security, and reliability, while also providing a user interface to save and reuse rows within your application.
Self-Hosted Saved Rows gives teams complete control over how Saved Rows are stored, managed, and secured. This option is best for organizations with specific compliance or integration requirements, and those with the resources to manage backend systems effectively.
Allows full control over where and how rows are stored.
Suitable for teams with specific compliance or integration needs.
Requires development resources for managing row storage, and creating a user interface to manage and reuse rows.
Both options allow end users to save and reuse rows on the frontend, but the best hosting option for your team will depend on your priorities concerning setup complexity, development resources (for storage and building a UI), and ongoing maintenance.
Explore
Explore
Setting up two-factor authentication will keep your developer account extra secure. Two-factor authentication means that users will need to provide two different identifications to log in to their : their regular login credentials, and a token generated by a two-factor authentication app.
When 2FA is set up, users will need to:
download a two-factor authentication app to their mobile device (e.g. , , , and others);
use their device and the app to generate a token and log in.
If you’re an account owner (i.e. the user who created the Beefree SDK account), you may require all account users to use two-factor authentication to log in. To do so, go to the Setting & Security section in your personal area and enable Require two-factor authentication at login.
After saving the setting, you will be prompted to scan a QR code with a 2FA application to generate a security token to complete the setup.
When this setting is ON:
every user will need to enter an authentication token, generated with a 2FA mobile app, to log into the account;
when you create a new user, the 2FA toggle will be set to ON by default.
When adding or editing a user, you may also decide to turn on or off 2FA for that user, in order to:
turn on 2FA, when 2FA is OFF at the account level;
turn off 2FA, when 2FA is ON at the account level.
If 2FA is OFF at the account level, additional users, i.e. admins, can turn on 2FA for themselves, for their peace of mind. They can go to the “Profile” section of their personal area and turn it on.
uid: 'test1-clientside' // production uid and development application uid
Control
Managed by Beefree SDK
Full control over storage and management
Setup Complexity
Done through a toggle in the Developer Console
Higher setup complexity requiring backend development
Ready-to-go user interface for end users to create and manage Saved Rows
Done through a toggle in the Developer Console
Requires development and use of Content Dialog
Security Responsibility
Managed by Beefree SDK
Fully managed by your team
Maintenance
Beefree SDK handles scaling and updates
Ongoing maintenance and updates required
Time-to-Market
Faster due to managed solution
Longer due to backend and frontend setup
Let’s start by looking at some of the peculiarities of the Popup builder.
In Email and Page Builder, the content area width is saved in the template. For example, if you start with an empty template, a default width that works for most scenarios is chosen, but the designer can adjust the message width slider. If you start with an existing template, the content width was chosen by the template’s designer using the message width slider in the builder Settings tab.
With Popup Builder, the same template may have multiple contexts, and each context will likely have specific size requirements. For example, an exit-intent popup may have a max-width of 600px on a desktop with a classical layout centered on the screen. On the other hand, the host app may display the same template on mobile in the bar style docked at the bottom of the screen with a restricted width of 300px.
Since the content area’s width is tightly coupled to the context and layout, no one size fits all width is saved in the template. Instead, the host app will specify the width settings when the builder loads, based on the context of using the template. Here is a quick example:
workspace: {
popup: {
contentWidth: 600,
contentWidthMobile: 300
}
}
Two final notes:
Popup Builder does not currently support fluid 100% width content.
If you don’t specify a width, the application will apply a default one.
As mentioned before, you will receive a ready-to-go design experience when no settings are provided. The default layout is a classic centered modal with a fixed width.
If the default popup style and layout suit your needs, then your customers are all set to start designing! You can load the builder without additional configuration and use the same standard controls and callbacks to access the HTML and JSON template.
What if you like most of the defaults but want to do some minor adjustments? We have you covered!
You can easily change the background to make the workspace look like the destination page where your customer will embed the popup.
beeConfig: {
...
workspace: {
popup: {
backgroundImage: 'https://.../background.png',
backgroundImageMobile: 'https://.../background.png',
...
}
}
}
If this option is not set, then we will provide a default skeleton layout. It’s worth noting at this point that you can apply every setting for both desktop and mobile design modes. That means you can have a different background when editing in Mobile Design Mode.
One of the most common needs is changing the popup’s default-centered position to better match the end-user’s use case. Out-of-the-box, the Popup Builder comes with many of the most common popup layouts preconfigured. You can use any available presets “as is” or use them as starting points that you can fine-tune to your satisfaction.
beeConfig: {
...
workspace: {
popup: {
layout: 'bar-top'
}
}
}
Here is a complete list of preset layouts:
Classic Popup
classic-center
classic-top-right
classic-top-left
classic-bottom-right
classic-bottom-left
This is our default layout and works great for alerts and exit intents.
Drawer or Slide-in panel
drawer-left
drawer-right
Side panels, or drawers, can be used to design menus or display ads.
Bar or Docker
bar-bottom
bar-top
This is great for cookie approval dialogs.
Learn about the different environments available through Beefree SDK and how to get started to with each.
Development applications are available with any Beefree SDK paid plan.
A development application is a child application that is linked to your parent application within the Beefree SDK console. The purpose of these child applications is to create development, QA, or any other type of applications that you can merge your application’s changes to prior to pushing them to production. This empowers you to test new features, even on a higher plan, within a controlled environment prior to releasing them to your application’s end users.
You can create a development application within your Beefree SDK console. Prior to creating a development application, ensure you have a paid plan with Beefree SDK. Development applications are only available on paid plans.
To create a development application, take the following steps:
Log in to your Beefree SDK Developer Console
Create a new application
Navigate to your dashboard where the new application is located
Click the + next to Add a development instance
Type in the name of your development application, for example “development environment” or “QA environment”
Click Create
View the new development application available in your Beefree SDK dashboard
There are multiple benefits to utilizing development applications. A few of these benefits are the following:
Merge and test changes to your application prior to releasing them to your end users.
Create an environment for different contributors in your development cycle, for example QA Engineers, frontend developers, backend developers, and so on.
Access next tier Beefree SDK features in your development applications.
Create as many child development applications linked to your parent production environment as you’d like.
Consider the information outlined in this section when working with development applications.
Beefree SDK lets you explore higher-tier features in your development environment for testing purposes. However, these features cannot be deployed to production unless they are included in your current subscription plan.
To use higher-tier features in production, you must upgrade to the appropriate plan.
Development apps inherit the same plan that your production app is on. If you wish to test features that are available on a higher plan, go the application details and click “CHANGE PLAN” in the upper right.
While setting up a development application is a feature on paid plans, please note that usage-based fees still apply. If, in your development application, you're using any of the Beefree SDK features that generate usage-based fees, that usage will count towards your plan's monthly allotment. You'll be charged usage-based fees if your usage (across production and development applications) exceeds your plan's allotment. Learn more about usage-based fees. You can view usage statistics for your development applications by logging into the Beefree SDK Developer Console, locating the development application you are working with, and looking at the Statistics widget on the application details page.
Our builders offer ready-to-go rows to your end-users, which provide both structure and content to create contents faster. With Edit Single Row mode you can offer an easier way for your users to modify a single row with a tailored UI built to edit 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.
Edit Single Row mode complements the Saved Rows as it allows a complete control over the content of individual rows (e.g. the footer that requires to be updated) without the need to intervene into a full template, this will help you in implementing a more effective way to manage libraries of Saved Rows with a streamlined design process.
type ClientConfig = {
workspace?: {
editSingleRow?: boolean
// ....
}
// ....
}
const beeConfig: ClientConfig = {
workspace:{
editSingleRow: true
// ....
}
// ....
}
// Create the instance
function BeePlugin.create(token, beeConfig, (beePluginInstance) => {
//....
beePluginInstance.start(template, { shared: false })
}
When a builder application is initialized with this mode enabled the UI will show to the user only properties that pertain to editing a single row, therefore:
the options to insert custom rows, saved rows, or new default rows are disabled,
the Settings tab is unavailable, as those properties are specific to the entire document,
when a row is selected on the editing stage, the action to Delete, Duplicate, Comment, Save are not available.
The following describes the recommended workflow to implement the Save action in your host SaaS application when the Single Edit Row mode is enabled.
In case your application uses the default Toolbar, you can leverage the save button to trigger the sequence of action to correctly save the row, the workflow is the same as the one documented in saving-rows-workflow-for-developers, in short :
The user clicks on the save button
A contentDialog of type saveRow will be triggered.
In case your application doesn’t use the default Toolbar you will need to handle the row saving in a different way, following a couple of examples:
Calling the save method. It will trigger the on onSave event with two arguments, one of them is the full message JSON that can be saved as a Saved Row (it’s the same JSON returned by the onSaveRow event).
myCustomToolbarButton.onClick(() => beePluginInstance.save())
...
onSave: function (json, html) {
myCustomApi.saveRow(json)
},
Listening to the onChange event. It will receive the updated full message JSON which again can be saved as a Saved Row.
onChange: function (json, response) {
myCustomApi.saveRow(json)
},
An effective way to update saved rows across multiple templates is by implementing the save action in combination with the Content Services API, to handle a row update across multiple existing templates.
Many digital marketing campaigns start with an attention-grabbing popup. In fact, many such campaigns include a popup, a landing page, and one or more emails.
A cool popup highlights something that the reader may be interested in
A landing page provides more information and includes some sort of signup form
Emails are sent to follow up.
Emails, pages, popups: three pillars of all sorts of digital marketing initiatives. Since Email Builder and Page Builder were already part of the Beefree SDK family, the natural next step was to create a Popup Builder. So here it is! This new version of the builder brings effortless popup creation inside your application.
A popup is a small window that appears on a website visitor’s screen, asking for an email address in the most basic interaction or other actionable messages when using more sophisticated strategies (targeted promotions, social evidence messages, shopping cart recovery, etc.).
Popups are one of the most used online marketing tools. When done right, they capture visitors’ attention at the right moment, and push them forward in the customer journey. Despite attracting criticism in the past because they create a barrier between visitors and content, there’s plenty of evidence that they work. They will continue to play a strong part in any modern-day marketing strategy. if you’re interested in learning more.
With this in mind, we have developed an embeddable solution for designing popups that you can easily deploy because:
it’s built from the ground up to integrate seamlessly with your application;
it’s easy to use, offers tons of design flexibility, and builds upon the same UX your customers already know from our Email & Page Builders;
all data stays in your application, and you don’t have to ask your customers to use 3rd party tools for building popups. You can leverage our to add forms to popups
In terms of packaging the final output, Beefree SDK takes care of the Popup design and returns a solid HTML output ready to be injected on a website. On top of that, you can enrich the building experience by creating a workflow that will add to that output:
Showing/closing behavior (e.g. display after N seconds, exit intent)
“Additional” styles, for things like
Close button
Border radius
Drop shadows
The good thing: you can pass additional styles to your application, so they will reflect into the editing experience. You will then take the HTML produced by Beefree SDK and apply these styles for the final output.
Our drag&drop experience, loved by millions of users
There are over 4,500,000 sessions of our drag-n-drop email & landing page builders every month, across hundreds of applications around the world. Popup builder brings the same, great user experience that transforms non-designers in masterful content creators.
You can load your customers' website home page as a background, so they can design a popup in the exact context where it will be used. And with Mobile design mode, your users are one click awaying to seeing and perfecting how the popup looks on mobile devices.
Position, size, background color, and more. Customize the builder each time to match how your customer configured their popup inside your application. What this means for you is flexibility, peace of mind, and implementation speed.
Get a solid HTML output ready to be injected on your customer’s website. Your application controls the display and behavior conditions, Beefree SDK takes care of the content.
Personalization is the secret weapon to attract any audience. With Merge tags and Display conditions your customers can show the right message at the right time, with use cases like product recommendations and personalized discount codes.
Your customers will never have to recreate the same content over and over again. They can apply the same saved rows already available for emails, landing pages or other popups. Plus, you may also provide custom rows with ready-made dynamic content like coupon codes and best-selling items.
Learn more about using the HTML Importer API endpoint.
This page discusses how to use the HTML Importer API endpoint. Follow the instructions outlined in this page to successfully perform API calls.
Prior to performing an API call, ensure the HTML you are using in the body of the POST
request meets the following requirements:
DOCTYPE
declaration
Include html
and body
elements
To prevent character encoding issues during the conversion, include the <meta charset="UTF-8">
tag in the head
section of your HTML before converting it.
Take the following steps to perform the conversion:
Ensure your API method is set to POST
Enter the endpoint URL: https://api.getbee.io/v1/conversion/html-to-json
Note: You can do this by setting {collection}
equal to conversion
in the following url: https://api.getbee.io/v1/{collection}/html-to-json
Authenticate by entering your API key as a Bearer Token in the Auth Type field
Ensure your request body's Content-Type
is set to text/html
Paste the HTML you'd like to convert into the request body field and ensure it meets the requirements outlined in the
Click Send
Within a few seconds, you should receive a response containing the Beefree JSON.
You can test the endpoint in the following interactive environment. Ensure you follow the steps outlined in the to successfully execute the API call after clicking the Test it button. You can copy and paste the HTML in the Sample HTML Template to Convert expandable section below, or use your own HTML as a request body for experimenting with the Test it feature.
Required: Ensure you manually type in text/html
in the Content-Type
field prior to making the API call.
Note: You will still need to authenticate in the Test it environment before making an API call. Visit the to obtain your API key and enter it in the bearerAuth
field.
A reference of form fields that can be edited and that cannot be edited.
The following table provides an overview of the form fields that support the edit form field modal, including a description of each field and an example of its content.
The following table provides an overview of the form fields that do not support the edit form field modal, including a description of each field and an example of its content.
Hosted Saved Rows offers a fully managed solution, eliminating the need to set up and maintain backend systems. With this option, Beefree SDK handles storage, security, scaling, and updates, allowing your team to focus on delivering a great user experience. In addition to managing storage, this option also provides you with a made available to your application's end users through a toggle in the .
This enables application end users to:
Save a row and make it available for reuse in the future.
Add new saved row categories to organize the rows they save.
Edit a saved row's existing name and category.
Delete a saved row.
Update existing saved rows with the option to save them as new saved rows.
Fully managed by Beefree SDK, and activated through a toggle in the Developer Console.
Ideal for teams that want a quick setup without maintaining backend systems.
Offers centralized storage, security, and reliability, while also providing a user interface to save and reuse rows within your application.
Allows for advanced controls through configuring .
Learn more about how to enable and customize Hosted Saved Rows in the following video. The webinar discusses:
How to enable Hosted Saved Rows
How to use 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
Reference the to follow along with the webinar tutorial.
To enable Hosted Saved Rows for your application, follow these steps:
Log in to the .
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.
*Hosted Saved Rows have the following pricing structure:
Note: Visit our to learn more about Hosted Saved Rows pricing.
Once you've successfully enabled Hosted Saved Rows in the , 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.
If you decide to deactivate Hosted Saved Rows:
Return to the Beefree SDK Console.
Toggle the Hosted on the Beefree SDK Infrastructure option to off.
Save your changes.
Hosted Saved Rows are removed from visibility in the builder.
After 90 days, all Hosted Saved Rows data is permanently deleted unless the feature is reactivated.
Yes, if reactivated within 90 days, previously Hosted Saved Rows will be restored. To fully restore rows across all applications, re-enable Hosted Saved Rows for each application.
Beefree SDK has introduced an updated version of the popular Saved Rows feature called Hosted Saved Rows. With this feature, Beefree SDK is responsible for storing Saved Rows in its own S3 Bucket and handling all the necessary steps for allowing your users to save and reuse rows.
End users can now easily save and reuse rows across multiple designs, including emails, pages, and popups. They can quickly find and manage Hosted Saved Rows by category.
The benefit for your users remains the same—they can save and reuse rows instead of rebuilding them every time. The only difference is that with Hosted Saved Rows, you don't have to develop all the necessary steps within your application on your own. All you need to do is activate the feature through a toggle in the .
We will store your end users' Hosted Saved Rows in a Beefree S3 Bucket. Each row will be exclusively used for the given UID belonging to the subscription.
The builder’s color palette gathers a list of the default colors to display from multiple sources in order to create a convenient palette of color selections when the editor loads.
Specifically, colors are gathered as follows:
3 colors from the body (message background, content background, link) + black (#000000)
custom colors (as many as customers want)
7 most recently used colors
Use the options outlined below to customize the default color palette.
The builder allows you to configure a custom color palette (per user), by modifying the client-side configuration. This, for instance, allows you to provide users with easy access to their company’s brand colors.
If no color profile is provided, then the builder will continue to suggest a color palette based on the colors used in the template that is being loaded.
Through setting for the color picker, you can control the visibility of, and access to, color codes, the slider, and swatches that appear within builder. These customization options enable you to control access to various elements of the color picker for different end users of your application.
A few of the benefits of applying advanced permissions to the Color Picker are the following:
Enhanced brand control – Gain granular control over color selection to ensure brand consistency.
Improved user experience – Streamline the interface by showing only necessary elements.
A few scenarios in which these advanced permissions are particularly helpful include the following:
Customizing the color picker UI based on user roles or workflows.
Hiding unnecessary UI elements to improve accessibility and reduce distractions.
Enforcing strict brand color guidelines by limiting available color options.
Take the following steps
Update the beeConfig
File: Open the beeConfig
file and locate the section for advancedPermissions
. Within this section, ensure there is a field for components
and add a new entry specifically for the colorPicker
.
Define Permission Settings: Within the color picker section, specify the necessary parameters that determine user access. Set the relevant parameters to either true
or false
, depending on whether the feature should be enabled or restricted for the end user.
The following code sample displays an example of how to add advanced permissions for the color picker to your configuration.
The table below outlines the configurable parameters for the color picker.
The builder will remember recently selected colors and add them to your color palette. If the browser’s privacy settings allow it, the color picker history will be saved in the browser’s local storage.
If you want the color palette to be static such that recently selected colors are not included, then you can disable the history in your configuration.
The builder by default adds colors found in the template’s body section to the color palette.
If you want the color palette to only show the colors you pass in via the bee config document, then you must disable the base colors.
With Meta Tags, you can now apply various tags to your HTML that can greatly benefit your SEO and accessibility needs.
These Meta Tags include:
Title
Description
Subject
Preheader
Language Attributes
For the Email Builder, Meta Tags promote improved deliverability performance. For the Page Builder, Meta Tags promote greater customization and improved search engine results.
The following image displays the Title and Description fields from within the page builder.
A page title, also known as a Title tag, is a short description of a webpage that appears at the top of a browser window and in SERPs (Search engine results page). This is an important element of an optimized SEO page, as it affects the page ranking in search engines. The title tag will be located within the <title> element of a page’s HTML output, and its value will be saved inside the JSON template.
Here is an example of what a Title Tag inside Beefree SDK’s HTML output might look like:
The description tag is located within the <meta> tag element of a page’s HTML, and it has a limit of 190 characters. The tag will be located within the <meta> element of the page’s HTML output, and its value will be saved inside the JSON template.
Here is an example of what a description tag inside Beefree SDK’s HTML output might look like:
The following code snippet is an example of what the Meta Tags will look like inside the JSON.
The following image displays the Subject and Preheader fields from within the email builder.
The subject field has a maximum of 190 characters. Here is an example of what a subject tag inside Beefree SDK’s HTML output might look like:
The preheader field has a maximum of 130 characters. Here is an example of what a preheader tag inside Beefree SDK’s HTML output might look like:
The following code snippet is an example of what the Meta Tags will look like inside the JSON.
The HTML lang attribute is used to identify the language of text content on the web. This information helps search engines return language-specific results, and it is also used by screen readers that switch language profiles to provide the correct accent and pronunciation for accessibility purposes.
When loading the builder, the host application can specify in the configuration a list of languages for their users to choose from (e.g. en-US), see the example below where the only option “Italian, it-IT” is provided. If there are no values provided via configuration file, a standard list of common languages will be provided.
Here is an example of what a language attribute inside Beefree SDK’s HTML output might look like:
The File Manager can be launched as a standalone application. This means that users can access the File Manager directly, without having to first launch the builder application. This is useful for situations where a user needs to quickly upload or manage assets, but doesn’t need to create a full email, landing page, or popup.
Instead of having to switch between different applications or tools, they can access everything they need from one centralized location. This can make the asset management process more streamlined and efficient, which can ultimately help users be more productive.
When you create an application in the , you’ll have the option to create a File Manager application.
Paid applications also include the option to create child development applications. These child applications can be used for new feature testing, development, and maintenance. By creating a child application, developers can easily test and iterate on new features without affecting the main application. This can help to minimize downtime and reduce the risk of introducing bugs or errors into the production environment.
The child applications can also be used for ongoing maintenance and updates. Instead of making changes directly to the production environment, developers can make updates and improvements in the child application, test them thoroughly, and then deploy the changes to the main application once they have been fully vetted. This can help to ensure that the main application remains stable and functional, even as new features and updates are introduced.
File manager applications share the same core functionalities as all other builders. These functionalities include authentication and configuration, which are necessary for the development process. If you have already integrated another builder into your workflow, you can easily re-use most of your work by using the same configuration for the file manager application.
For those who are new to our platform, our documentation includes a comprehensive section that provides detailed instructions on how to set up and use our builders. This section is applicable to all products.
File Manager and all builders are available to customers under the same Please contact your Customer Success Manager for more details.
This section outlines steps to add the “Insert” and “X” buttons to your application’s user interface. These steps are specifically for the file manager.
Take the following steps to define the `onFilePickerInsert` and `onFilePickerCancel` properties to enable an “Insert” button and “X” button in the file manager user interface:
Ensure that you have initialized the Beefree SDK and have a reference to the SDK instance (`bee`).
Define the `onFilePickerInsert`
property with a callback function that will be invoked when the user wants to insert a file. This function will receive the selected file data as the only parameter. You can use this data to perform any necessary actions, such as inserting the file into the editor or displaying a preview.
Here is an example of how the callback function can be defined:
Define the `onFilePickerCancel`
property with a callback function that will be invoked when the user wants to cancel the file picker. This function does not receive any parameters. You can use this callback to perform any cleanup actions or provide feedback to the user.
Here’s an example of how the callback function can be defined:
Assign the defined `onFilePickerInsert`
and `onFilePickerCancel`
callbacks to the corresponding properties in the Beefree SDK configuration. Make sure to include these properties when initializing the Beefree SDK.
Here is an example:
By following these steps, you will be able to define the `onFilePickerInsert`
and `onFilePickerCancel`
properties in the Beefree SDK configuration and enable the “Insert” and “X” buttons in the file manager user interface. You can customize the callback functions to suit your specific needs and perform any desired actions with the selected file data or when the file picker is canceled.
When configuring a builder application with Beefree SDK, you have four image and file storage options:
Beefree SDK Storage: Default option. Images are hosted in Beefree SDK’s AWS S3 bucket. Potential fees apply for usage beyond the included limits.
Existing Storage Application: Connect your builder to an existing storage application to share storage resources.
Own AWS S3 Bucket: Use your own AWS S3 bucket instead of Beefree SDK’s. Follow the documentation to configure this option.
Own File System: Integrate your application’s existing file system for storage. This option is available on Beefree SDK paid plans.
Reference the to learn more about how to configure storage for your File manager application.
Your users will have the ability to rewind and fast-forward to any point in their recent edit history. Once Undo is enabled in the , the application immediately begins tracking changes. Behind the scenes, this is accomplished via a new callback event – – which can also be used “stand-alone” without enabling Undo. No client-side configuration is required to use this feature. Continue reading to learn how to activate and use Undo. And if you can’t wait to try it yourself, you can immediately do so at
When changes are detected, a compact Undo widget displays in the bottom left corner of the stage:
The widget displays 3 actions:
Undo and Redo arrows that offer the classic pattern to move back and forth between changes.
A history icon that expands a timeline of the latest changes:
The timeline allows the user to browse through the most recent changes.
All the steps display:
An icon to identify the content element type (an image, text, etc.)
A description of what changed, giving the new property value (if any)
The exact time it happened
All these details provide enough information for users to understand what modification was applied, and, if desired, rewind the message to that state:
When the user selects a previous step, the content or row that triggered the history record displays as the selected item, providing further context.
The timeline for more recent changes is still available, allowing the user to move forward without losing any changes:
The Undo widget currently displays the last 15 edits in the timeline, but users can always rewind to the Message opened state to undo all changes since the message was initially opened in the builder.
We are also doing additional testing to see if the number of recent edits can be increased beyond 15 without negatively impacting the browser’s performance. We will update this section if the number is increased.
The last saved edits are only available at the session level, so they reset every time the builder is loaded. If you need to provide a complete message history, you can build a custom one based on the onSave and onChange events (see below).
The Undo option is available at the application level in the . Select your application from the list and open the Application configuration in the bottom-right. The option to enable this widget is available in the Services list:
The widget uses the information to work. However, it doesn’t need a client-side configuration for the callback: once Undo is enabled, the application starts tracking changes even if the is not set in .
In the Toolbar Options tab you can:
control individual settings that affect the top toolbar in the builder
decide whether to hide the toolbar completely
The toolbar contains all the actions not related directly with content edition, like save, send a test or preview.
You can decide the inner elements from it, from hiding our brand to removing the save button, to create the builder version that better fits in your application.
Not enough? Remove the toolbar completely and offer all the actions with your own UI elements.
For example, in our MailUp App for Shopify, we hide the toolbar completely and control the builder (Show preview, Send test, Save) from buttons in the app UI (not in the builder). Here is how it looks.
If you decide to go this route, use the to control the builder from your UI.
Smart merge tags provide a better way for your customers to leverage personalization when creating content with Beefree SDK.
With Smart merge tags, users can:
quickly identify merge tags through a specific highlighting
see human-friendly names instead of the raw syntax – e.g., Customer Name instead of {%customer.name%}.
select, replace, and style merge tags with just one click
get sample content for each merge tag, both during editing and preview.
After enabling Smart merge tags, the builder will:
highlight merge tags with a dotted border
display the tag name you passed instead of the raw syntax
When users click on a tag, its border will become solid to signify that it has been selected. After selection, users can style, replace, or delete the merge tag with just one click.
Smart merge tags are easier to identify inside the content you’ve created and will save users tons of time. Furthermore, hiding the syntax will make it impossible for a user to break it while interacting with the overall text element.
On top of this, you can pass sample content for each merge tag, so that users can see an example of the data that will take the place of the merge tags when the web content is rendered:
Smart merge tags are disabled by default. If your application doesn’t have Smart merge tags, you need to activate it. It takes just a few clicks:
Click Details next to the application you want to configure
We recommend you first familiarize yourself with this feature under a DEV or QA application
Click view more under Application configuration.
Under the Services section, toggle Enable Smart merge tags ON and click the Save button.
Notice that, at this point, you will be prompted to enable the merge tag preview in the toolbar. You can skip this option when your integration is not using the or you’re not passing sample content for your .
After enabling Smart merge tags from your developer account, you need to apply a minor change to the merge tags’ .
The optional previewValue
parameter is used to pass to the editor a sample content (text string) for every merge tag.
The value of this new parameter will replace the merge tag in the editor preview, meaning that there’s no need to build a custom preview to display the final result of an email or landing page with rich personalization strings.
Sample content strings are not limited to the preview, but can be displayed in the editor’s stage as mentioned above.
The way to do this depends on how your integration manages the .
In this case, you can simply enable the option “Show ‘Merge tag preview’ in toolbar” mentioned above.
When this option is active, the toolbar displays a new action to the user:
The option works as a toggle that alternates between displaying the previewValue
and the name parameter inside the merge tag UI.
As with all the actions available in the toolbar, to control this option from your own UI:
Use this method to replicate the behavior described for the standard toolbar.
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.
Multiple Storage Options: Activate, store, and manage Saved Rows using either or options.
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:
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.
Special Links and Merge Tags
Content Dialog
Custom Color Palette
Font management
Roles and Permissions
Smart Merge Tags
Commenting
Custom Attributes
Meta Tags
Custom Languages
Display Conditions
Advanced Permissions
Custom File Picker
Custom Headers
Checkbox
Allows the user to select one or more options.
"Subscribe to newsletter"
Color
Allows the user to select a color from a palette.
"#ff5733"
Date
Allows the user to input a date.
"2024-09-21"
Allows the user to input an email address.
Number
Allows the user to input a numerical value.
"42"
Radio
Allows the user to select one option from a set.
"Option 1"
Select
Provides a dropdown menu for the user to choose from.
"Choice A"
Tel
Allows the user to input a phone number.
"(555) 123-4567"
Text
Allows the user to input a single line of text.
"John Doe"
Textarea
Allows the user to input multiple lines of text.
"This is a message..."
URL
Allows the user to input a web address.
"https://example.com"
Submit
Creates a button that submits the form.
"Submit"
Datalist
Provides a list of predefined options for an input field.
"Option 1, Option 2"
Datetime
Allows the user to input both a date and time.
"2024-09-21T14:30"
File
Allows the user to upload a file.
"Upload a document"
Hidden
Stores hidden data that the user does not see.
"userID=12345"
Image
Displays an image as a form button.
"Submit (image icon)"
Label
Defines a label for an input element.
"Username"
Month
Allows the user to input a month and year.
"2024-09"
Password
Allows the user to input a password.
"********"
Range
Allows the user to input a value within a range.
"50 (from 0 to 100)"
Search
Allows the user to input search text.
"Search query"
Time
Allows the user to input a time.
"14:30"
Week
Allows the user to input a week and year.
"2024-W38"
var beeConfig = {
uid: config.uid,
defaultColors: ['#ffffff', '#000000', '#95d24f', '#ff00dd'],
...
const advancedPermissions = {
...,
components: {
...,
colorPicker: {
canViewColorInput: true,
canViewSliders: true,
canViewSwatches: true,
}
}
}
canViewColorInput
boolean
Hides or shows the text input for the color picker in the sidebar.
Default value is true.
canViewSliders
boolean
Hides or shows the sliders inside the color picker popover.
Default value is true.
canViewSwatches
boolean
Hides or shows the swatches inside the color picker popover.
Default value is true.
var beeConfig = {
uid: config.uid,
disableColorHistory: true,
...
var beeConfig = {
uid: config.uid,
disableBaseColors: true,
...
<title>Done with love using BeefreeSDK</title>
<meta name="description"
content="This is an example of a meta description.
This will often show up in search results.">
},
"title": "Empty Template",
"head": {
"meta": {
"title": "The Legendary Elephant King: A Tale of Love, Loss, and Redemption",
"description": "Experience the timeless story of the elephant king and elephant son as they navigate through tragedy, friendship, and destiny in the elephant kingdom."
}
}
},
<title>🐘 Experience the Epic Tale of an Elephant King!</title>
<div class="preheader" style="font-size:1px;line-height:1px;display:none;color:#fff;max-height:0;max-width:0;opacity:0;overflow:hidden">
Join the elephant son on a journey of love, loss, and redemption in the animal kingdom. 🌍
</div>
},
"title": "Empty Template",
"head": {
"meta": {
"subject": "🐘 Experience the Epic Tale of an Elephant King!",
"preheader": "Join the elephant son on a journey of love, loss, and redemption in the animal kingdom. 🌍"
}
}
},
beeConfig: {
...
metadata: {
languages: [
{ value: 'it-IT', label: 'Italian' },
...
]
}
}
<html lang="it-IT">
onFilePickerInsert: function (data) {
// Handle the selected file data
console.log("File Inserted:", data);
// Perform any necessary actions with the file data
},
JAVASCRIPTCopy
onFilePickerCancel: function () {
// Handle file picker cancellation
console.log("File Picker Canceled");
// Perform any necessary actions when the file picker is canceled
},
var beeConfig = {
// Other configuration options...
onFilePickerInsert: function (data) {
// Handle the selected file data
},
onFilePickerCancel: function () {
// Handle file picker cancellation
},
};
// Initialize the Beefree SDK with the configuration
bee.start(beeConfig);
Show toolbar
Is the main option: if is not active, the elements listed bellow get hidden
Show Beefree SDK logo
Show our logo and links our site
Show preview
Trigger the preview window
Show send test
Trigger the function for sending a test
Show save as template
Is used to save only the editable version of the message
Show save button
If you don’t have a external one, better not to hide this 🙂
Show auto-save icon
This tiny icon alert the user every time the auto-save works
Show help link
This option is special, because you can also introduce your custom help URL
Show Multi-Language Templates
Use this to enable a custom top bar that allows the end user to change the language.
{
name: 'first name',
value: '[first-name]',
previewValue: 'John',
}
beePluginInstance.toggleMergeTagsPreview()
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adopt a Dog</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-color: #f9f9f9;
color: #333;
text-align: center;
}
.container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
img {
max-width: 100%;
height: auto;
border-radius: 8px;
}
p {
font-size: 16px;
line-height: 1.5;
}
.cta {
margin-top: 20px;
}
.cta a {
display: inline-block;
padding: 10px 20px;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
}
.cta a:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<img src="https://s3.amazonaws.com/cdn-origin-etr.akc.org/wp-content/uploads/2019/09/28115848/Shih-Tzu-snuggling-on-a-babys-lap-outdoors.jpg" alt="Adopt a Dog">
<p>
Dogs are everyone's best friend. They bring joy, love, and loyalty into our lives. <br>
Consider adopting one today and give a furry friend a forever home.
</p>
<div class="cta">
<a href="https://www.petfinder.com/" target="_blank">Adopt Now</a>
</div>
</div>
</body>
</html>
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
Beefree SDK offers a comprehensive suite of features that enable your application's end users to save and manage reusable content. Rows are a core feature of the visual builders within Beefree SDK that provide end users with an intuitive avenue for saving and reusing content throughout their design creation workflows. They provide a structured method to house various types of content such as headers, paragraphs, images, and buttons.
Rows are also a fundamental part of how designs are built and structured within the visual builders. In the following GIF, you can see how each row functions as a component of a continuous design.
Rows allow end users to add multiples types of content to a section of a design. End users can either create their own rows from scratch (and save them for reuse on a later day), or they can use pre-designed rows that are pre-loaded into the host application and ready for use. Pre-loaded rows are helpful when providing a template structure that end users can customize as they build their designs.
Providing end users with the option to easily reuse content comes with a host of benefits, including:
Pre-designed and customizable content: End users can select from rows that already contain content, which they can then customize for their specific needs.
Flexible structure: Rows help organize different content types in a structured layout, which promotes a clean and efficient design.
Drag-and-drop functionality: Rows can easily be dragged and dropped onto the stage.
Continuity with current user experience: End users can add empty structures, which preserves creativity and allows them to build and design from scratch.
Option to disable empty rows: If preferred, end users can opt to work solely with pre-made rows, focusing on content customization without the need to build layouts from the ground up.
In addition to rows offering a variety of benefits for end users, there are also clear benefits for the host application, including:
Ready-to-go content delivery: The host application can pass pre-built, ready-to-go rows directly into the builder, reducing the need for end users to create content from scratch.
Customization control: Host applications can offer a variety of customizable rows, ensuring users follow design guidelines while still providing creative freedom.
Improved user experience: Pre-designed rows simplify the user interface, making the builder more intuitive and less complex for users.
Optional removal of empty structures: Host applications can disable empty row options if desired, encouraging users to focus on modifying pre-existing content.
Efficient content management: Rows enable the host to provide consistent, reusable content blocks that can be updated globally, streamlining content management and maintaining design consistency across the platform.
This section outlines the different row-related features available within Beefree SDK. Throughout the following pages of the Rows section, we will discuss each of these different row-related features in depth, including what they are, how they look, and how to implement them if they are a good fit for your application and end users.
The purpose of Custom Rows is to provide pre-configured rows that your end users can drag-and-drop into the builder and start customizing.
The following GIF provides a visual of how Custom Rows look to end users:
Custom Rows are integrated by adding the rowsConfiguration
parameter to your beeConfig
. The following code snippet is the one used to configure the row in the GIF above.
rowsConfiguration : {
"externalContentURLs": [
{
"name": "External resource",
"value": "https://bee-playground-backend.getbee.io/api/customrows?ids=1,2,3,4"
}
]
}
Visit the Beefree SDK playground to experiment more with the Custom Rows configuration, and visit the Implement Custom Rows page to learn more about integrating this feature within your application.
Hosted Saved Rows allow your end users to save and manage their own rows to be used later–a powerful way to help them streamline their workflows!
Also, Hosted Saved Rows simultaneously provides both a storage solution and user interface your application's end users can engage with to save and manage their rows.
In the following GIF, with Hosted Saved Rows, Beefree SDK provides the user interface and infrastructure to power Saved Rows so you can bring this feature to your end users instantly.
Implementing Hosted Saved Rows takes only a few seconds, because it activated through a toggle in the Beefree SDK Developer Console. The following image shows how the toggle looks like in the Developer Console.
Visit the Implement Hosted Saved Rows page to learn more about customization options and integration details.
Self-hosted Saved Rows are similar to Hosted Saved Rows on the frontend, but require you to connect your own database on the backend. This feature also provides you with more customization options on the frontend if you'd more granular control over customizing your end user's experience saving and managing rows.
The following GIF shows an example of a customized modal for saving a row within an application. This modal uses both saved rows and content dialog for the customized experience.
The purpose of Synced Rows is to maintain consistency by synchronizing row updates across multiple designs. A synced row can be reused across multiple designs and each design is updated whenever a synced row is updated. When you edit a synced row, you a redirected to Edit Single Row Mode.
The purpose of Edit Single Row Mode is to allow precise editing of rows inside of a dedicated row builder. The GIF above displays an example of Edit Single Row Mode. Visit Initialize Edit Single Row Mode to learn more about how to implement this feature.
This page includes instructions on how to obtain your API key for the HTML Importer API.
Beefree SDK's HTML Importer API uses bearer tokens to authenticate requests. You can create, view, and manage your bearer token in the Beefree SDK Developer Console. All requests must be made over HTTPS and contain the following HTTP Header:
Authorization: Bearer {token}
To use the HTML Importer API, you will need an API Key, which is the bearer token you will use to authenticate, from the Beefree SDK Developer Console.
Take the following steps to obtain your API key:
Log in to the Beefree SDK Developer Console.
Navigate to the application you'd like to activate the HTML Importer API for.
Click on the corresponding Details button.
Navigate to the HTML Importer API section of the Details page.
Click Create New API Key.
A pop up will appear asking you to confirm that you understand usage-based fees apply.
Click Create Key.
Your API key will appear under the HTML Importer API section of your application details.
Install Beefree SDK to get started with your implementation.
Congratulations on ! Now it’s time to install it. The first step is to add the Beefree SDK library to your application. You can use our to add it. This guide discusses how you can set up a local environment, install the package, authenticate, and get started with Beefree SDK.
Beefree SDK is an embeddable no-code content builder that enables your end users to build stunning marketing assets, such as emails, landing pages, and popups, without writing a single line of code.
The following list includes a few key features within Beefree SDK:
Drag-and-drop visual editors
File manager
Multi-user collaboration
Responsive design capabilities
Extensive template library
Secure authentication workflow
This guide provides comprehensive instructions and best practices for implementing Beefree SDK.
This section discusses how to get started with Beefree SDK.
Prior to integrating Beefree SDK, ensure you have:
A Beefree SDK .
Node.js (v14 or higher) installed.
A modern web browser (Chrome, Firefox, Safari, Edge).
To test the SDK locally before production deployment:
Clone the demo repository:
Install dependencies:
Configure environment:
Start the dev server:
Access at http://localhost:8081
You can install Beefree SDK using either or :
Using npm
Using Yarn
Package Details:
TypeScript Support: Included
License: Apache-2.0
Repository:
This section discusses the authentication process.
The secure authentication flow requires a server-to-server call to obtain a JWT token. This process ensures your client credentials remain protected.
Authentication Endpoint
Required Parameters
The following table lists and descibes the required authentication parameters.
Example Implementation (Node.js)
Important Notes:
The UID must be consistent between authentication and SDK configuration.
Tokens are valid for 12 hours.
Ensure client_secret and client_id aren't exposed in the client-side code.
JSON Authorization Response
This section discusses how to initialize Beefree SDK.
Create a container element in your HTML where the editor will render:
Beefree SDK requires a configuration object with the following essential property:
Full Configuration Reference
The following table explains the container property.
Initialize the editor with a template JSON object:
Reference the in GitHub for example templates.
The following table lists template management methods that are important for getting started.
The instance method bee.start(template)
does not need to be called immediately after create
. In a SPA (Single Page Application) or React app, you can create
the editor in a hidden global state but then call the start
method when the template is selected and available. The application loads quickly when all steps are completed consecutively. However, by separating the loading workflow into two parts, the end-user will perceive loading in a fraction of the overall time. Remember, if the client_id
belongs to a File Manager application, bee.start()
can be called without any parameters.
Implement automatic token refresh to maintain uninterrupted sessions:
How to use:
Get a fresh token from your backend
Pass it to updateToken()
Enable real-time collaboration with these additional methods:
How to use:
Generate a unique session-id
on your server
Call join()
with the same ID for all collaborators
The following list includes the most common issues and steps for troubleshooting them.
Authentication Failures
Verify client_id
and client_secret
Ensure UID matches between auth and config
Check network connectivity to auth.getbee.io
Editor Not Loading
Confirm container element exists
Verify container ID matches config
Check for JavaScript errors in console
Token Expiration Issues
Implement onTokenExpired
callback
Test token refresh flow
Q: Can I use the SDK without server-side authentication? A: While possible for testing, production implementations must use server-side auth for security.
Q: How do I customize the editor's appearance? A: The SDK supports UI customization through configuration options. Refer to the advanced documentation.
Q: What happens when the token expires? A: When your token expires after 12 hours:
The editor will become unresponsive
You must proactively:
Best practice is to refresh tokens before expiration (recommended at 11 hours)
Q: Where can I find sample templates? A: Visit our for examples.
This comprehensive guide covers all aspects of Beefree SDK integration, from initial setup to advanced features.
Remember to:
Always use server-side authentication
Implement proper token refresh logic
Test thoroughly before production deployment
Monitor for SDK updates and new features
This page lists and describes the Export category of endpoints within the Content Services API. It also includes interactive testing environments for each endpoint in this category.
URL: https://api.getbee.io/v1/{collection}/html
This endpoint allows you to retrieve the full or partial HTML output of a template (email, page, or popup).
To generate HTML from a template's JSON:
Capture or store the latest JSON output from the builder using such as onChange
or autosave
.
Send this JSON payload to the HTML endpoint.
Receive the HTML string as the response.
page
(object, required): The full template structure in Beefree JSON format. This is the same structure returned by the builder or captured from its callbacks.
This endpoint bypasses the need for the onSave
callback and can be used at any time post-editing.
Partial HTML rendering is also supported for specific components or modules (if required by your use case).
The output HTML reflects the current rendering engine used by Beefree, ensuring up-to-date compatibility.
URL: https://api.getbee.io/v1/{collection}/html
This endpoint allows you to retrieve the full or partial HTML output of a template (email, page, or popup).
To generate plain text from a template's JSON:
Capture or store the latest JSON output from the builder using such as onChange
or autosave
.
Send this JSON payload to the /plain-text
endpoint.
Receive the plain text as the response.
URL: https://api.getbee.io/v1/{collection}/pdf
You can generate a PDF file from valid HTML content using the dedicated PDF generation endpoint. This operation requires a JSON payload with specific fields to configure the output.
Field Descriptions
html
(string, required): The full HTML content to convert to a PDF. You can obtain the HTML output of a template by calling the and copying its response into this field.
page_orientation
(string, required): Sets the orientation of the generated PDF pages.
Accepted values:
"portrait"
: vertical layout.
"landscape"
: horizontal layout.
page_size
(string, required): Defines the dimensions of the PDF output.
Accepted values:
"Letter"
: US Letter format.
"A4"
: A4 paper size.
"A3"
: A3 paper size.
"Full"
: a single continuous page with fixed width (900px) and height determined proportionally to the content.
When using "Letter"
, "A4"
, or "A3"
, the content is automatically split across multiple pages.
Using "Full"
produces a single, unpaginated scrollable PDF.
To generate a PDF from a template:
Call the /html
endpoint to retrieve the template's HTML.
Insert that HTML into the "html"
field of the request payload.
Set your preferred "page_orientation"
and "page_size"
.
Send the payload to the PDF generation endpoint.
URL: https://api.getbee.io/v1/{collection}/image
This endpoint allows you to generate an image file (for example, PNG) from a template's HTML. You can control the image output by specifying the dimensions.
The HTML is rendered using a fixed-size browser window to simulate a real-world preview. Here are the key rendering parameters:
Window Size: 1920 x 1080
pixels (used for clipping/screenshot area)
Default Viewports:
Mobile: 320px
width
Desktop: 1024px
width
Clipping Region: defaults to 1920 x 1080
pixels
Scale Factor: Automatically calculated to match viewport and clipping dimensions.
You may override the clipping size if your layout requires a custom viewport. If your content exceeds the clipping area, it may be cropped. For improved results, using auto height with the size parameter is recommended.
Use the to generate the HTML version of your template.
Set the html
field in your image request payload to the HTML generated.
Provide a width
and height
values, or a size
value.
Send the payload to the image endpoint.
Learn more about the Template Catalog API offering in Beefree SDK.
Beefree SDK includes a comprehensive API offering designed to expand upon the builder's capabilities. By leveraging Beefree SDK's APIs, you can extend the builder's functionality into other aspects of your application.
Beefree SDK's API offering includes three APIs. They are the following:
This section of the documentation discusses the , which includes resources for programmatically adding a catalog of pre-existing email, page, and popup templates to your application. These pre-existing templates were carefully constructed by professional designers with the goal of inspiring your end users' creativity.
The Template Catalog API is a -based API that enables Beefree SDK integrators to programmatically access a catalog of pre-made templates for emails and pages. This catalog is a useful resource for integrators looking to provide their end users with pre-made templates created by professional designers. These templates serve as a starting point for the design and creation workflow, and offer end users with visual inspiration for their campaigns. The Template Catalog API is built to follow predictable resource url patterns, and to utilize standard HTTP response codes and methods.
Beefree SDK requires that you prior to accessing the Template Catalog API's resources. You can generate API keys for both production and . API keys associated with development applications are intended for pre-production environments and endpoint testing. They should not be used in production environments.
There are five categories of resources within the Template Catalog API. Each of these categories includes a group of endpoints with resources to support various workflows.
To get an idea of the template catalog offering, you can reference the . This page includes a few examples of email and page templates included in the Template Catalog API.
The Template Catalog API provides the following features:
Fetch templates from the Template Catalog API by applying filters such as "category", "industry", and so on.
Sort and customize templates to match your application’s requirements and end user preferences.
The Template Catalog API offers the following resources:
Templates: Individual email templates that users can browse, select, and use. Each template contains metadata such as title, description, thumbnail image, and design structure.
Categories: Groupings of templates based on their use case or theme (e.g., Newsletters, Promotions, Events), helping users quickly find relevant templates.
Collections: Curated sets of templates bundled together around a specific topic, brand, or style, providing thematic consistency across multiple communications.
Designers: Information about the creators of templates, including designer profiles and links to the templates they have authored.
Tags: Keywords associated with templates, making it easier to filter and search based on specific styles, industries, or content types (e.g., Minimal, E-commerce, Holiday).
In this Template Catalog Reference, you will learn more about a personalized template catalog for your SaaS applications. Through this API, you can integrate a diverse range of email and page templates, promoting enhanced user engagement while optimizing the design process within your platform.
The Template Catalog API is available for Core, Superpowers, and Enterprise plans. Activating the Template Catalog API varies by plan type.
Enterprise: Self-service activation through the Beefree SDK Developer Console.
Superpower: Self-service activation through the Beefree SDK Developer Console.
Core: Contact your Customer Success Manager (CSM) to activate this API.
To enhance the performance and user experience of your template catalog, we recommend following these best practices.
Implement caching mechanisms to reduce API calls and minimize user loading times. Template data do not change often, so you can use a cache TTL of some minutes (10 for example, but even more) without issues.
Handle errors gracefully and provide clear error messages to assist in resolving any issues. These endpoints have the following rate limits:
Per minute: 500 requests;
Per second: 100 requests.
Therefore, we recommend not enforcing excessive automatic tries when you get an error message, otherwise, you may exceed the limit and won’t be able to proceed with more requests.
The API is a read-only API. The only method is GET
.
Find answers to common queries related to the Template Catalog API, its features, and integration.
Reference answers to the most frequently asked questions in this section.
No, they are included in your subscription. The catalog will be updated with the latest trends at no extra charge.
We are committed to making fresh new templates available every quarter.
Storing the JSON Template source file is totally in your control. The media assets referenced inside the template are kept in the Beefree SDK S3 Bucket and provisioned using the CDN.
No. There are no additional fees or usage-based limits when using the Template Catalog API.
With Custom Attributes, your end users can easily append additional information to HTML tags in emails and web pages, at the same moment they are creating their content in Beefree SDK. These attributes can be applied to links, both in text blocks and buttons, and images, and they serve a variety of scenarios: personalization, segmentation, styling, accessibility, etc.
Custom attributes enable a wide array of use cases, depending on your application’s capabilities and your users’ needs. Here are a few examples:
flagging specific links so that user activity for those won’t be tracked (e.g. clicktracking="off”
in SendGrid);
handling internal statistical segmentation or reporting (e.g. data-reportingname="October_promo" data-reportingtags="promo,iphone"
);
adding conditions to a single content element (using an attribute such as condition="customer_exists"
);
embedding a single image by adding an attribute like embedded="true"
, processed when the message is sent;
adding custom CSS classes for custom CSS;
adding WAI-ARIA attributes for accessibility requirements.
The host application can provide the editor with a list of attributes that will be available to the user through the UI. How the attribute value is formatted impacts how the builder UI displays it and how the user interacts with it.
Custom attributes can be applied to:
Links in text blocks
Links in buttons
Images (including thumbnails generated by the Video block)
For images and buttons, these attributes will be visible in the editor sidebar, under the new “ATTRIBUTES” section.
For links in text blocks, they will be part of the dialog window for creating a link.
You can provide the editor with a list of attributes that will be available to the user through the UI. How the attribute value is formatted impacts how the builder UI displays it and how the user interacts with it.
Depending on how custom attributes are implemented, users may:
add a custom attribute from a list of attributes already defined, and specify the value of the attribute, if appliable:
from a predefined list
in a text input
defining a boolean property (yes/no, true/false, etc.)
add a “custom” custom attribute by manually specifying both name and value
open an additional interface, through a content dialog, where users have complete freedom on how to build custom attributes.
Regardless of how a custom attribute is added, it will be included in the a
or img
tag when HTML is generated for an email/page, like the segment attribute in this hyperlink:
Custom attributes are a client-side configuration that needs to be passed when initializing the editor. There are different shades of implementation complexity, based on the outcome you want to obtain. These approaches can be combined as preferred.
The easiest implementation is to just pass a simple configuration at startup:
With this setup, users can indicate a “Custom” custom attribute by manually specifying Name and Value. Please note that users must know exactly what they are doing, as there will be no guidance in the editor.
You can pass the necessary custom attributes in the initial configuration. Those attributes will be available in the interface, and the user will be able to specify the value for these attributes, if possible.
Let’s look through the attributes defined in the example above, and how they will look like in the builder.
The Deeplink
attribute has a single, predefined value, so when added in the builder it will look like this:
The Segment
attribute has two possible values, which can be selected by the user:
The Class
attribute has no defined value, so the user can enter anything in a text input:
You can totally customize the UX of adding attributes by invoking a that will take over the editor’s UI. The dialog will need to return the attribute that needs to be applied.
Integrate custom fonts and resized images into your designs. It saves custom fonts within the template's JSON, ensuring the correct font is displayed. It also handles image resizing, particularly when the image's initial template width is narrower than the saved row's destination template.
The collection ID or name
A string field for rowIdentifierLabel
Replace or update content in a Beefree template using a specific path and value. Compatible with Email and Page builders.
The collection ID or name
Retrieve a list of synced rows from a template.
The collection ID or name
A string field for rowIdentifierLabel
Get a list of designers from the catalog.
{"count":34,"next":null,"previous":null,"results":[{"available":true,"avatar_url":"https://d1oco4z2z1fhwp.cloudfront.net/designers/LuanaLiguori.png","base":"Naples, Italy (GMT+2)","description":"Hello, I'm Luana, a graphic and web designer with 8+ years of experience, specializing in email and landing page design. My approach is marked by precision, proactive problem-solving, and strong collaboration. I create visually impactful designs that align with marketing strategies, including social media graphics, blog covers, and presentations. I also offer custom design services tailored to clients' unique needs.","short_description":"","display_name":"Luana Liguori","email":"[email protected]","first_name":"Luana","highlighted":false,"hobby":"","id":"luana-liguori","last_name":"Liguori","position":"Beefree In-House Designer","social_behance":"","social_dribbble":"","social_linkedin":"","website":"https://www.ilas.com/portfolio/20538400/luana-liguori"}]}
Get a specific designer from the catalog.
{"available":true,"avatar_url":"https://d1oco4z2z1fhwp.cloudfront.net/designers/LuanaLiguori.png","base":"Naples, Italy (GMT+2)","description":"Hello, I'm Luana, a graphic and web designer with 8+ years of experience, specializing in email and landing page design. My approach is marked by precision, proactive problem-solving, and strong collaboration. I create visually impactful designs that align with marketing strategies, including social media graphics, blog covers, and presentations. I also offer custom design services tailored to clients' unique needs.","short_description":"","display_name":"Luana Liguori","email":"[email protected]","first_name":"Luana","highlighted":false,"hobby":"","id":"luana-liguori","last_name":"Liguori","position":"Beefree In-House Designer","social_behance":"","social_dribbble":"","social_linkedin":"","website":"https://www.ilas.com/portfolio/20538400/luana-liguori"}
Get a list of tags from the catalog.
{"message":"Success"}
Get a list of categories from the catalog.
{"count":114,"next":null,"previous":null,"results":[{"bg_color":"#F8F8F8","fb_color":"#333A45","highlighted":false,"icon":null,"id":"leap-year","image":null,"name":"Leap Year","description":"Make every extra day count with our Leap Year email templates. Whether you're celebrating a special promotion, organizing an exclusive event, or simply seizing the opportunity for a unique marketing campaign, our templates are designed to make your Leap Year messages stand out.","short_description":"Engage your audience with visually appealing designs that capture the essence of this rare occurrence.","parent":"seasonal"}]}
Use AI and this endpoint to generate metadata, which includes preheaders and subject lines, automatically.
The collection ID or name
Submit your JSON template as the request body to generate a custom SMS using AI.
The collection ID or name
Submit your JSON template as the request body to generate a custom and concise summary using AI.
The collection ID or name
GET /v1/catalog/designers HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"count": 34,
"next": null,
"previous": null,
"results": [
{
"available": true,
"avatar_url": "https://d1oco4z2z1fhwp.cloudfront.net/designers/LuanaLiguori.png",
"base": "Naples, Italy (GMT+2)",
"description": "Hello, I'm Luana, a graphic and web designer with 8+ years of experience, specializing in email and landing page design. My approach is marked by precision, proactive problem-solving, and strong collaboration. I create visually impactful designs that align with marketing strategies, including social media graphics, blog covers, and presentations. I also offer custom design services tailored to clients' unique needs.",
"short_description": "",
"display_name": "Luana Liguori",
"email": "[email protected]",
"first_name": "Luana",
"highlighted": false,
"hobby": "",
"id": "luana-liguori",
"last_name": "Liguori",
"position": "Beefree In-House Designer",
"social_behance": "",
"social_dribbble": "",
"social_linkedin": "",
"website": "https://www.ilas.com/portfolio/20538400/luana-liguori"
}
]
}
GET /v1/designers/:slug HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"available": true,
"avatar_url": "https://d1oco4z2z1fhwp.cloudfront.net/designers/LuanaLiguori.png",
"base": "Naples, Italy (GMT+2)",
"description": "Hello, I'm Luana, a graphic and web designer with 8+ years of experience, specializing in email and landing page design. My approach is marked by precision, proactive problem-solving, and strong collaboration. I create visually impactful designs that align with marketing strategies, including social media graphics, blog covers, and presentations. I also offer custom design services tailored to clients' unique needs.",
"short_description": "",
"display_name": "Luana Liguori",
"email": "[email protected]",
"first_name": "Luana",
"highlighted": false,
"hobby": "",
"id": "luana-liguori",
"last_name": "Liguori",
"position": "Beefree In-House Designer",
"social_behance": "",
"social_dribbble": "",
"social_linkedin": "",
"website": "https://www.ilas.com/portfolio/20538400/luana-liguori"
}
GET /v1/catalog/tags HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"message": "Success"
}
POST /v1/{collection}/metadata HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 19924
{
"options": {
"model": "gpt-3.5-turbo",
"toneOfVoice": "",
"instructions": "Try to use a pun.",
"reportUsage": true,
"language": ""
},
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#fff",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"background-size": "auto"
}
},
"content": {
"computedStyle": {
"linkColor": "#8a3b8f",
"messageBackgroundColor": "transparent",
"messageWidth": "650px"
},
"style": {
"color": "#000000",
"font-family": "Lato, Tahoma, Verdana, Segoe, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Lato', Tahoma, Verdana, Segoe, sans-serif",
"name": "Lato",
"url": "https://fonts.googleapis.com/css?family=Lato"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "10px",
"width": "100%"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "b89c3d25-dbec-439a-8ad1-4939a28678e9"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
},
"uuid": "3bd72010-5175-4326-b848-8beacea852d6"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:49:32.875165Z",
"dateModified": "2022-01-20T09:49:32.875165Z",
"description": "",
"idParent": null,
"name": "Pre header purple row",
"slug": "pre-header-purple-row",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_small.jpg",
"uuid": "8b99691b-8e39-47a7-8773-4540cd7ff113"
},
"synced": false,
"type": "one-column-empty",
"uuid": "7fa3e6c4-ac4f-421f-b9eb-db1b9f629fb3"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "162.5px"
},
"image": {
"alt": "BEE Pro Logo",
"height": "109px",
"href": "https://beefree.io/",
"percWidth": 25,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/BEEPro_logo_2.png",
"target": "_self",
"width": "291px"
},
"style": {
"padding-bottom": "40px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "20px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "cc54124d-97bd-44e0-b15e-710a577840ec"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "20px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "2cd36842-fbe8-4f43-9688-ff6c964aaa89"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>Hi 🙂</p>\n<p><strong>Would you be interested to participate in a user research project with us?</strong></p>\n<p>The research will consist of a video call. It usually takes 30 to 45 minutes maximum, but we schedule 1 hour in case we need more time. We'll be asking questions about you, your team, and your email/page creation workflow. The idea is for us to understand how BEE Pro fits in your work day.</p>\n<p><strong>Sounds good?</strong> Pick a time slot at your convenience using <a href=\"https://calendly.com/beepro-product-team/beepro-interview?month=2022-06\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration: underline;\">this link ↗</a></p>\n<p>Look forward to hearing back from you.</p>\n<p>Best,</p>\n<p>Dalila from the Product Team 💜</p>\n<p>P.S. Probably your colleagues that use BEE Pro have received this email too. If you'd like you can add one guest to the booking link and participate together, or you can join us alone. We would love to talk to you in any case. </p>",
"style": {
"color": "#000000",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
},
"translations": {
"de-DE": {
"html": "<p>Hallo 🙂<br /><br />Is het interessant om deel te nemen aan een onderzoek naar nieuwe gebruikersonderzoeken?<br /><br />Het onderzoek bestaat uit een videofilm. Wacht tussen 30 en 45 minuten als het maximum, maar het programma duurt 1 uur voordat u meer tijd nodig heeft. De haremos worden nu gebruikt, uw uitrusting en uw vloeiende creatie van pagina's/correos elektronische. Het idee is dat BEE Pro op zijn werk werkt.<br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br />Groot,<br /><br />Dalila del equipo de producto 💜<br /><br /><br />PD Waarschijnlijk is uw partner die BEE Pro gebruikt, deze recibido is elektrisch correct. Als je dit hebt gedaan, kun je een uitnodiging voor het reserveren en de deelname aan de wedstrijd verzamelen, of je kunt een nieuwe solo spelen. Geen enkele gebeurtenis wordt in een ander geval verwisseld.</p>"
},
"es-ES": {
"html": "<p>Hola 🙂<br /><br />¿Estaría interesado en participar en un proyecto de investigación de usuarios con nosotros?<br /><br />La investigación consistirá en una videollamada. Suele tardar entre 30 y 45 minutos como máximo, pero programamos 1 hora por si necesitamos más tiempo. Le haremos preguntas sobre usted, su equipo y su flujo de trabajo de creación de páginas/correos electrónicos. La idea es que entendamos cómo encaja BEE Pro en su jornada laboral.<br /><br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br /><br />Mejor,<br /><br />Dalila del equipo de producto 💜<br /><br /><br /><br />PD Probablemente tus compañeros que utilizan BEE Pro también hayan recibido este correo electrónico. Si lo desea, puede agregar un invitado al enlace de reserva y participar juntos, o puede unirse a nosotros solo. Nos encantaría hablar con usted en cualquier caso.</p>"
}
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "0456f2de-7125-475c-b016-41f77b3fda47"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "5px"
},
"uuid": "61614a04-eb36-4d98-b28e-c6c9e048877d"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:51:57.896884Z",
"dateModified": "2022-01-20T09:51:57.896884Z",
"description": "",
"idParent": null,
"name": "body with: logo + pre title + title + subtitle + body",
"slug": "body-with-logo-pre-title-title-subtitle-body",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_small.jpg",
"uuid": "35d02430-32b2-41d6-a115-68d7bb476d64"
},
"synced": false,
"type": "two-columns-empty",
"uuid": "f57920be-d9e4-41c0-a009-eb85fd2a8034"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "30px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "ab4460e6-1206-45c1-ba56-9f6d6409508e"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "6ac459ef-5e34-468a-b064-07ea57e1e37c"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2021-06-29T08:19:25.800829Z",
"dateModified": "2021-06-29T08:19:27.572522Z",
"description": "",
"idParent": null,
"name": "Footer Line",
"slug": "footer-line",
"uuid": "77127825-a508-4127-9155-b5161f9e1703"
},
"synced": false,
"type": "row-1-columns-12",
"uuid": "b759c29c-fb9e-4b1a-add9-a464eeb568f5"
},
{
"columns": [
{
"grid-columns": 3,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "130px"
},
"image": {
"alt": "Elena Loatelli & Dalila Bonomi",
"height": "263px",
"href": "",
"percWidth": 80,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/dalila.png",
"target": "_self",
"width": "263px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "682c9273-3090-43fb-9acc-a2e2cda857b7"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "a434440b-92d8-4841-90cc-2ab49b1afc14"
},
{
"grid-columns": 9,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "10px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:14px;line-height:16px;font-family:inherit;\" data-mce-style=\"font-size:14px;line-height:16px;font-family:inherit;\"><p style=\"font-size:14px;line-height:16px;word-break:break-word;\" data-mce-style=\"font-size:14px;line-height:16px;word-break:break-word;\"><strong><span style=\"font-size:16px;line-height:19px;\" data-mce-style=\"font-size:16px;line-height:19px;\">DALILA BONOMI</span></strong></p></div>",
"style": {
"color": "#8a3b8f",
"font-family": "inherit",
"line-height": "120%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "b37a5a73-5f40-4e2d-8d7b-6a117aa686eb"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:12px;line-height:21px;font-family:inherit;\" data-mce-style=\"font-size:12px;line-height:21px;font-family:inherit;\"><p style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\" data-mce-style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\"><strong><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">BEE | The email & page builder for everyone.</span></strong></p><p style=\"line-height:21px;word-break:break-word;\" data-mce-style=\"line-height:21px;word-break:break-word;\"><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">Design Researcher</span></p></div>",
"style": {
"color": "#454562",
"font-family": "inherit",
"line-height": "180%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "a916773b-42f4-4efc-af64-3b2a9f801015"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "bc078241-a4ab-4a26-b28b-b7aba3180d3a"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-31T09:21:17.612857Z",
"dateModified": "2022-01-31T09:21:20.633639Z",
"description": "",
"idParent": null,
"name": "Dalila single sign",
"slug": "dalila-single-sign",
"uuid": "37bceb9d-b1c9-4724-b5ad-31645653d1c2"
},
"synced": false,
"type": "two-columns-3-9-empty",
"uuid": "3218627f-a68a-4f5d-b3e9-adfa19bb82ec"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "50px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "5a247632-900c-4a38-8bf1-2307938d9bb5"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "ecfdb53f-a7a0-40dd-9fd9-67d7e2677832"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "feb66cab-ac4a-4ec2-b5d6-657eeabd1039"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "16px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "6px",
"padding-top": "5px"
},
"itemsSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "Designed with BEE",
"height": "325px",
"href": "https://beefree.io/",
"id": "1879a39d-9303-43e5-8458-990ac7b0a429",
"image": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_510656/Signature/bee_w.png",
"target": "_blank",
"text": "Designed with BEE",
"textPosition": "right",
"title": "Designed with BEE",
"width": "325px"
}
]
},
"style": {
"color": "#ffffff",
"font-family": "inherit",
"font-size": "15px",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "35f3f7a2-37aa-4471-bd26-ce2b51e6e39b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "8d6cbc30-0a36-4037-ae02-827d71033fee"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-20T09:44:21.371097Z",
"dateModified": "2022-01-20T11:01:58.708887Z",
"description": "",
"idParent": null,
"name": "Designed with BEE",
"slug": "designed-with-bee",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_small.jpg",
"uuid": "727e515b-7455-4661-8e85-22b9f7178d3f"
},
"synced": false,
"type": "one-column-empty",
"uuid": "cc615b28-4773-45ef-b0bf-4ef7ef89b1bf"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"comments": {
"31878122-0ce6-4ac0-930e-ccf6086c264c": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> ei",
"elementId": "9664b8a4-b3c0-401d-be92-6a0dc5022591",
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:54:12.900Z",
"isElementDeleted": true
},
"aa9ea85d-1cdd-49b4-90d0-a42fb87d0a44": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> test",
"elementId": null,
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:55:03.335Z",
"isElementDeleted": null
}
}
}
}
{
"message": "Success"
}
POST /v1/{collection}/sms HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 19932
{
"options": {
"model": "gpt-3.5-turbo",
"toneOfVoice": "",
"length": "detailed",
"instructions": "",
"reportUsage": true,
"language": "it-IT"
},
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#fff",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"background-size": "auto"
}
},
"content": {
"computedStyle": {
"linkColor": "#8a3b8f",
"messageBackgroundColor": "transparent",
"messageWidth": "650px"
},
"style": {
"color": "#000000",
"font-family": "Lato, Tahoma, Verdana, Segoe, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Lato', Tahoma, Verdana, Segoe, sans-serif",
"name": "Lato",
"url": "https://fonts.googleapis.com/css?family=Lato"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "10px",
"width": "100%"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "b89c3d25-dbec-439a-8ad1-4939a28678e9"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
},
"uuid": "3bd72010-5175-4326-b848-8beacea852d6"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:49:32.875165Z",
"dateModified": "2022-01-20T09:49:32.875165Z",
"description": "",
"idParent": null,
"name": "Pre header purple row",
"slug": "pre-header-purple-row",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_small.jpg",
"uuid": "8b99691b-8e39-47a7-8773-4540cd7ff113"
},
"synced": false,
"type": "one-column-empty",
"uuid": "7fa3e6c4-ac4f-421f-b9eb-db1b9f629fb3"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "162.5px"
},
"image": {
"alt": "BEE Pro Logo",
"height": "109px",
"href": "https://beefree.io/",
"percWidth": 25,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/BEEPro_logo_2.png",
"target": "_self",
"width": "291px"
},
"style": {
"padding-bottom": "40px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "20px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "cc54124d-97bd-44e0-b15e-710a577840ec"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "20px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "2cd36842-fbe8-4f43-9688-ff6c964aaa89"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>Hi 🙂</p>\n<p><strong>Would you be interested to participate in a user research project with us?</strong></p>\n<p>The research will consist of a video call. It usually takes 30 to 45 minutes maximum, but we schedule 1 hour in case we need more time. We'll be asking questions about you, your team, and your email/page creation workflow. The idea is for us to understand how BEE Pro fits in your work day.</p>\n<p><strong>Sounds good?</strong> Pick a time slot at your convenience using <a href=\"https://calendly.com/beepro-product-team/beepro-interview?month=2022-06\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration: underline;\">this link ↗</a></p>\n<p>Look forward to hearing back from you.</p>\n<p>Best,</p>\n<p>Dalila from the Product Team 💜</p>\n<p>P.S. Probably your colleagues that use BEE Pro have received this email too. If you'd like you can add one guest to the booking link and participate together, or you can join us alone. We would love to talk to you in any case. </p>",
"style": {
"color": "#000000",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
},
"translations": {
"de-DE": {
"html": "<p>Hallo 🙂<br /><br />Is het interessant om deel te nemen aan een onderzoek naar nieuwe gebruikersonderzoeken?<br /><br />Het onderzoek bestaat uit een videofilm. Wacht tussen 30 en 45 minuten als het maximum, maar het programma duurt 1 uur voordat u meer tijd nodig heeft. De haremos worden nu gebruikt, uw uitrusting en uw vloeiende creatie van pagina's/correos elektronische. Het idee is dat BEE Pro op zijn werk werkt.<br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br />Groot,<br /><br />Dalila del equipo de producto 💜<br /><br /><br />PD Waarschijnlijk is uw partner die BEE Pro gebruikt, deze recibido is elektrisch correct. Als je dit hebt gedaan, kun je een uitnodiging voor het reserveren en de deelname aan de wedstrijd verzamelen, of je kunt een nieuwe solo spelen. Geen enkele gebeurtenis wordt in een ander geval verwisseld.</p>"
},
"es-ES": {
"html": "<p>Hola 🙂<br /><br />¿Estaría interesado en participar en un proyecto de investigación de usuarios con nosotros?<br /><br />La investigación consistirá en una videollamada. Suele tardar entre 30 y 45 minutos como máximo, pero programamos 1 hora por si necesitamos más tiempo. Le haremos preguntas sobre usted, su equipo y su flujo de trabajo de creación de páginas/correos electrónicos. La idea es que entendamos cómo encaja BEE Pro en su jornada laboral.<br /><br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br /><br />Mejor,<br /><br />Dalila del equipo de producto 💜<br /><br /><br /><br />PD Probablemente tus compañeros que utilizan BEE Pro también hayan recibido este correo electrónico. Si lo desea, puede agregar un invitado al enlace de reserva y participar juntos, o puede unirse a nosotros solo. Nos encantaría hablar con usted en cualquier caso.</p>"
}
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "0456f2de-7125-475c-b016-41f77b3fda47"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "5px"
},
"uuid": "61614a04-eb36-4d98-b28e-c6c9e048877d"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:51:57.896884Z",
"dateModified": "2022-01-20T09:51:57.896884Z",
"description": "",
"idParent": null,
"name": "body with: logo + pre title + title + subtitle + body",
"slug": "body-with-logo-pre-title-title-subtitle-body",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_small.jpg",
"uuid": "35d02430-32b2-41d6-a115-68d7bb476d64"
},
"synced": false,
"type": "two-columns-empty",
"uuid": "f57920be-d9e4-41c0-a009-eb85fd2a8034"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "30px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "ab4460e6-1206-45c1-ba56-9f6d6409508e"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "6ac459ef-5e34-468a-b064-07ea57e1e37c"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2021-06-29T08:19:25.800829Z",
"dateModified": "2021-06-29T08:19:27.572522Z",
"description": "",
"idParent": null,
"name": "Footer Line",
"slug": "footer-line",
"uuid": "77127825-a508-4127-9155-b5161f9e1703"
},
"synced": false,
"type": "row-1-columns-12",
"uuid": "b759c29c-fb9e-4b1a-add9-a464eeb568f5"
},
{
"columns": [
{
"grid-columns": 3,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "130px"
},
"image": {
"alt": "Elena Loatelli & Dalila Bonomi",
"height": "263px",
"href": "",
"percWidth": 80,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/dalila.png",
"target": "_self",
"width": "263px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "682c9273-3090-43fb-9acc-a2e2cda857b7"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "a434440b-92d8-4841-90cc-2ab49b1afc14"
},
{
"grid-columns": 9,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "10px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:14px;line-height:16px;font-family:inherit;\" data-mce-style=\"font-size:14px;line-height:16px;font-family:inherit;\"><p style=\"font-size:14px;line-height:16px;word-break:break-word;\" data-mce-style=\"font-size:14px;line-height:16px;word-break:break-word;\"><strong><span style=\"font-size:16px;line-height:19px;\" data-mce-style=\"font-size:16px;line-height:19px;\">DALILA BONOMI</span></strong></p></div>",
"style": {
"color": "#8a3b8f",
"font-family": "inherit",
"line-height": "120%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "b37a5a73-5f40-4e2d-8d7b-6a117aa686eb"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:12px;line-height:21px;font-family:inherit;\" data-mce-style=\"font-size:12px;line-height:21px;font-family:inherit;\"><p style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\" data-mce-style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\"><strong><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">BEE | The email & page builder for everyone.</span></strong></p><p style=\"line-height:21px;word-break:break-word;\" data-mce-style=\"line-height:21px;word-break:break-word;\"><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">Design Researcher</span></p></div>",
"style": {
"color": "#454562",
"font-family": "inherit",
"line-height": "180%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "a916773b-42f4-4efc-af64-3b2a9f801015"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "bc078241-a4ab-4a26-b28b-b7aba3180d3a"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-31T09:21:17.612857Z",
"dateModified": "2022-01-31T09:21:20.633639Z",
"description": "",
"idParent": null,
"name": "Dalila single sign",
"slug": "dalila-single-sign",
"uuid": "37bceb9d-b1c9-4724-b5ad-31645653d1c2"
},
"synced": false,
"type": "two-columns-3-9-empty",
"uuid": "3218627f-a68a-4f5d-b3e9-adfa19bb82ec"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "50px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "5a247632-900c-4a38-8bf1-2307938d9bb5"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "ecfdb53f-a7a0-40dd-9fd9-67d7e2677832"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "feb66cab-ac4a-4ec2-b5d6-657eeabd1039"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "16px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "6px",
"padding-top": "5px"
},
"itemsSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "Designed with BEE",
"height": "325px",
"href": "https://beefree.io/",
"id": "1879a39d-9303-43e5-8458-990ac7b0a429",
"image": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_510656/Signature/bee_w.png",
"target": "_blank",
"text": "Designed with BEE",
"textPosition": "right",
"title": "Designed with BEE",
"width": "325px"
}
]
},
"style": {
"color": "#ffffff",
"font-family": "inherit",
"font-size": "15px",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "35f3f7a2-37aa-4471-bd26-ce2b51e6e39b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "8d6cbc30-0a36-4037-ae02-827d71033fee"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-20T09:44:21.371097Z",
"dateModified": "2022-01-20T11:01:58.708887Z",
"description": "",
"idParent": null,
"name": "Designed with BEE",
"slug": "designed-with-bee",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_small.jpg",
"uuid": "727e515b-7455-4661-8e85-22b9f7178d3f"
},
"synced": false,
"type": "one-column-empty",
"uuid": "cc615b28-4773-45ef-b0bf-4ef7ef89b1bf"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"comments": {
"31878122-0ce6-4ac0-930e-ccf6086c264c": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> ei",
"elementId": "9664b8a4-b3c0-401d-be92-6a0dc5022591",
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:54:12.900Z",
"isElementDeleted": true
},
"aa9ea85d-1cdd-49b4-90d0-a42fb87d0a44": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> test",
"elementId": null,
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:55:03.335Z",
"isElementDeleted": null
}
}
}
}
{
"message": "Success"
}
POST /v1/{collection}/summary HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 19931
{
"options": {
"model": "gpt-3.5-turbo",
"toneOfVoice": "",
"length": "concise",
"instructions": "",
"reportUsage": true,
"language": "it-IT"
},
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#fff",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"background-size": "auto"
}
},
"content": {
"computedStyle": {
"linkColor": "#8a3b8f",
"messageBackgroundColor": "transparent",
"messageWidth": "650px"
},
"style": {
"color": "#000000",
"font-family": "Lato, Tahoma, Verdana, Segoe, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Lato', Tahoma, Verdana, Segoe, sans-serif",
"name": "Lato",
"url": "https://fonts.googleapis.com/css?family=Lato"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "10px",
"width": "100%"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "b89c3d25-dbec-439a-8ad1-4939a28678e9"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
},
"uuid": "3bd72010-5175-4326-b848-8beacea852d6"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:49:32.875165Z",
"dateModified": "2022-01-20T09:49:32.875165Z",
"description": "",
"idParent": null,
"name": "Pre header purple row",
"slug": "pre-header-purple-row",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_small.jpg",
"uuid": "8b99691b-8e39-47a7-8773-4540cd7ff113"
},
"synced": false,
"type": "one-column-empty",
"uuid": "7fa3e6c4-ac4f-421f-b9eb-db1b9f629fb3"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "162.5px"
},
"image": {
"alt": "BEE Pro Logo",
"height": "109px",
"href": "https://beefree.io/",
"percWidth": 25,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/BEEPro_logo_2.png",
"target": "_self",
"width": "291px"
},
"style": {
"padding-bottom": "40px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "20px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "cc54124d-97bd-44e0-b15e-710a577840ec"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "20px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "2cd36842-fbe8-4f43-9688-ff6c964aaa89"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>Hi 🙂</p>\n<p><strong>Would you be interested to participate in a user research project with us?</strong></p>\n<p>The research will consist of a video call. It usually takes 30 to 45 minutes maximum, but we schedule 1 hour in case we need more time. We'll be asking questions about you, your team, and your email/page creation workflow. The idea is for us to understand how BEE Pro fits in your work day.</p>\n<p><strong>Sounds good?</strong> Pick a time slot at your convenience using <a href=\"https://calendly.com/beepro-product-team/beepro-interview?month=2022-06\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration: underline;\">this link ↗</a></p>\n<p>Look forward to hearing back from you.</p>\n<p>Best,</p>\n<p>Dalila from the Product Team 💜</p>\n<p>P.S. Probably your colleagues that use BEE Pro have received this email too. If you'd like you can add one guest to the booking link and participate together, or you can join us alone. We would love to talk to you in any case. </p>",
"style": {
"color": "#000000",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
},
"translations": {
"de-DE": {
"html": "<p>Hallo 🙂<br /><br />Is het interessant om deel te nemen aan een onderzoek naar nieuwe gebruikersonderzoeken?<br /><br />Het onderzoek bestaat uit een videofilm. Wacht tussen 30 en 45 minuten als het maximum, maar het programma duurt 1 uur voordat u meer tijd nodig heeft. De haremos worden nu gebruikt, uw uitrusting en uw vloeiende creatie van pagina's/correos elektronische. Het idee is dat BEE Pro op zijn werk werkt.<br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br />Groot,<br /><br />Dalila del equipo de producto 💜<br /><br /><br />PD Waarschijnlijk is uw partner die BEE Pro gebruikt, deze recibido is elektrisch correct. Als je dit hebt gedaan, kun je een uitnodiging voor het reserveren en de deelname aan de wedstrijd verzamelen, of je kunt een nieuwe solo spelen. Geen enkele gebeurtenis wordt in een ander geval verwisseld.</p>"
},
"es-ES": {
"html": "<p>Hola 🙂<br /><br />¿Estaría interesado en participar en un proyecto de investigación de usuarios con nosotros?<br /><br />La investigación consistirá en una videollamada. Suele tardar entre 30 y 45 minutos como máximo, pero programamos 1 hora por si necesitamos más tiempo. Le haremos preguntas sobre usted, su equipo y su flujo de trabajo de creación de páginas/correos electrónicos. La idea es que entendamos cómo encaja BEE Pro en su jornada laboral.<br /><br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br /><br />Mejor,<br /><br />Dalila del equipo de producto 💜<br /><br /><br /><br />PD Probablemente tus compañeros que utilizan BEE Pro también hayan recibido este correo electrónico. Si lo desea, puede agregar un invitado al enlace de reserva y participar juntos, o puede unirse a nosotros solo. Nos encantaría hablar con usted en cualquier caso.</p>"
}
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "0456f2de-7125-475c-b016-41f77b3fda47"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "5px"
},
"uuid": "61614a04-eb36-4d98-b28e-c6c9e048877d"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:51:57.896884Z",
"dateModified": "2022-01-20T09:51:57.896884Z",
"description": "",
"idParent": null,
"name": "body with: logo + pre title + title + subtitle + body",
"slug": "body-with-logo-pre-title-title-subtitle-body",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_small.jpg",
"uuid": "35d02430-32b2-41d6-a115-68d7bb476d64"
},
"synced": false,
"type": "two-columns-empty",
"uuid": "f57920be-d9e4-41c0-a009-eb85fd2a8034"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "30px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "ab4460e6-1206-45c1-ba56-9f6d6409508e"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "6ac459ef-5e34-468a-b064-07ea57e1e37c"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2021-06-29T08:19:25.800829Z",
"dateModified": "2021-06-29T08:19:27.572522Z",
"description": "",
"idParent": null,
"name": "Footer Line",
"slug": "footer-line",
"uuid": "77127825-a508-4127-9155-b5161f9e1703"
},
"synced": false,
"type": "row-1-columns-12",
"uuid": "b759c29c-fb9e-4b1a-add9-a464eeb568f5"
},
{
"columns": [
{
"grid-columns": 3,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "130px"
},
"image": {
"alt": "Elena Loatelli & Dalila Bonomi",
"height": "263px",
"href": "",
"percWidth": 80,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/dalila.png",
"target": "_self",
"width": "263px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "682c9273-3090-43fb-9acc-a2e2cda857b7"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "a434440b-92d8-4841-90cc-2ab49b1afc14"
},
{
"grid-columns": 9,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "10px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:14px;line-height:16px;font-family:inherit;\" data-mce-style=\"font-size:14px;line-height:16px;font-family:inherit;\"><p style=\"font-size:14px;line-height:16px;word-break:break-word;\" data-mce-style=\"font-size:14px;line-height:16px;word-break:break-word;\"><strong><span style=\"font-size:16px;line-height:19px;\" data-mce-style=\"font-size:16px;line-height:19px;\">DALILA BONOMI</span></strong></p></div>",
"style": {
"color": "#8a3b8f",
"font-family": "inherit",
"line-height": "120%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "b37a5a73-5f40-4e2d-8d7b-6a117aa686eb"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:12px;line-height:21px;font-family:inherit;\" data-mce-style=\"font-size:12px;line-height:21px;font-family:inherit;\"><p style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\" data-mce-style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\"><strong><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">BEE | The email & page builder for everyone.</span></strong></p><p style=\"line-height:21px;word-break:break-word;\" data-mce-style=\"line-height:21px;word-break:break-word;\"><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">Design Researcher</span></p></div>",
"style": {
"color": "#454562",
"font-family": "inherit",
"line-height": "180%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "a916773b-42f4-4efc-af64-3b2a9f801015"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "bc078241-a4ab-4a26-b28b-b7aba3180d3a"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-31T09:21:17.612857Z",
"dateModified": "2022-01-31T09:21:20.633639Z",
"description": "",
"idParent": null,
"name": "Dalila single sign",
"slug": "dalila-single-sign",
"uuid": "37bceb9d-b1c9-4724-b5ad-31645653d1c2"
},
"synced": false,
"type": "two-columns-3-9-empty",
"uuid": "3218627f-a68a-4f5d-b3e9-adfa19bb82ec"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "50px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "5a247632-900c-4a38-8bf1-2307938d9bb5"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "ecfdb53f-a7a0-40dd-9fd9-67d7e2677832"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "feb66cab-ac4a-4ec2-b5d6-657eeabd1039"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "16px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "6px",
"padding-top": "5px"
},
"itemsSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "Designed with BEE",
"height": "325px",
"href": "https://beefree.io/",
"id": "1879a39d-9303-43e5-8458-990ac7b0a429",
"image": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_510656/Signature/bee_w.png",
"target": "_blank",
"text": "Designed with BEE",
"textPosition": "right",
"title": "Designed with BEE",
"width": "325px"
}
]
},
"style": {
"color": "#ffffff",
"font-family": "inherit",
"font-size": "15px",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "35f3f7a2-37aa-4471-bd26-ce2b51e6e39b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "8d6cbc30-0a36-4037-ae02-827d71033fee"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-20T09:44:21.371097Z",
"dateModified": "2022-01-20T11:01:58.708887Z",
"description": "",
"idParent": null,
"name": "Designed with BEE",
"slug": "designed-with-bee",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_small.jpg",
"uuid": "727e515b-7455-4661-8e85-22b9f7178d3f"
},
"synced": false,
"type": "one-column-empty",
"uuid": "cc615b28-4773-45ef-b0bf-4ef7ef89b1bf"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"comments": {
"31878122-0ce6-4ac0-930e-ccf6086c264c": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> ei",
"elementId": "9664b8a4-b3c0-401d-be92-6a0dc5022591",
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:54:12.900Z",
"isElementDeleted": true
},
"aa9ea85d-1cdd-49b4-90d0-a42fb87d0a44": {
"author": {
"userColor": "#85b2c3",
"userHandle": "515751",
"username": "Cinzia Caleffi"
},
"content": "<code contenteditable=\"false\" data-bee-mention-uid=\"274606\">@Dalila Bonomi</code> <code contenteditable=\"false\" data-bee-mention-uid=\"264431\">@Cinzia Caleffi</code> test",
"elementId": null,
"mentions": [
"274606",
"264431"
],
"parentCommentId": null,
"responses": [],
"timestamp": "2022-08-03T06:55:03.335Z",
"isElementDeleted": null
}
}
}
}
{
"message": "Success"
}
git clone https://github.com/BeefreeSDK/beefree-sdk-npm-official.git
npm install
# or
yarn install
cp .env.sample .env
npm start
npm install @beefree.io/sdk --save
yarn add @beefree.io/sdk
POST https://auth.getbee.io/loginV2
client_id
string
Your application client ID
"abc123-client-id"
client_secret
string
Your application secret key
"xyz456-secret-key"
UID
string
Unique user identifier
"user-12345"
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
// Obtain token
var token = req.responseText;
// Call create method and pass token and beeConfig to obtain an instance of BEE Plugin
BeePlugin.create(token, beeConfig, function(beePluginInstance) {
// Call start method of bee plugin instance
beePluginInstance.start(template); // template is the json to be loaded in BEE
});
}
};
// This is a sample call to YOUR server side application that calls the loginV2 endpoint on BEE the side
req.open(
'POST', // Method
'/YOUR_BACKEND_TOKEN_ENDPOINT', // your server endpoint
false // sync request
);
{
"access_token": "...",
"v2": true
}
<div id="bee-plugin-container" style="width: 100%; height: 800px;"></div>
var config = {
container: 'string'
}
container
string
Yes
DOM element ID for the editor
// After successful initialization
const template = {
// Your template JSON here
// Sample templates available at:
// https://github.com/BeefreeSDK/beefree-sdk-assets-templates
};
bee.start(template);
load(template)
Load new template
bee.load(newTemplate)
reload(template)
Force reload template
bee.reload(updatedTemplate)
save()
Trigger save callback
bee.save()
saveAsTemplate()
Save as template
bee.saveAsTemplate()
// Refresh expired token (call before 12-hour expiry)
bee.updateToken(newToken);
// Join a co-editing session
bee.join({ uid: "user-123" }, "shared-session-id");
// 1. Get a fresh token from your backend
const newToken = await fetch('/refresh-token');
// 2. Update the SDK instance
bee.updateToken(newToken);
Import custom HTML into Beefree SDK
✅ Yes, see authentication instructions.
Export, convert, and style templates and rows. Use AI to generate metadata, SMS, and summaries.
✅ Yes, see authentication instructions.
Access Beefree's catalog of templates
✅ Yes, see authentication instructions.
Enterprise
Included
Superpowers
Included
Core
$167/mth or $2,000/yr
Essentials
Not available
Free
Not available
<a href=”https://beefree.io/” segment=”emaildesign”>Visit BEE!</a>
customAttributes: {
enableOpenFields: true
}
customAttributes:{
attributes: [
{
key: "Deeplink",
value: true,
target: "link"
},
{
key: "data-segment",
value: ['travel', 'luxury'],
target: "link"
},
{
key: "class",
target: "tag"
}
]
}
Retrieve a list of all templates in the catalog.
{"count":1726,"next":"https://api.getbee.io/v1/catalog/templates/?page=2","previous":null,"results":[{"categories":["others"],"collections":"","context":"free","description":"","short_description":"","designer":"beefree-team","id":"empty","is_blank":true,"template_type":"email","order":"99999999","published_at":"2017-08-28","tags":["black","light","promote","serif","two-column","white"],"thumbnail_large":"https://d1oco4z2z1fhwp.cloudfront.net/templates/default/1_large.jpg","thumbnail":"https://d1oco4z2z1fhwp.cloudfront.net/templates/default/1.jpg","title":"Empty"},{"categories":["others"],"collections":"","context":"free","description":"","short_description":"","designer":"beefree-team","id":"empty-page","is_blank":true,"template_type":"page","order":"99999998","published_at":"2021-07-19","tags":[],"thumbnail_large":"https://d1oco4z2z1fhwp.cloudfront.net/templates/default/4246_large.jpg","thumbnail":"https://d1oco4z2z1fhwp.cloudfront.net/templates/default/4246.jpg","title":"Empty Page"}],"facets":{"categories":[{"id":"events","name":"Events","parent":"usage","count":353},{"id":"seasonal-promotion","name":"Seasonal Promotion","parent":"seasonal","count":345},{"id":"e-commerce","name":"E-commerce","parent":"industry","count":316}]}}
GET /v1/catalog/templates HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"count": 1726,
"next": "https://api.getbee.io/v1/catalog/templates/?page=2",
"previous": null,
"results": [
{
"categories": [
"others"
],
"collections": "",
"context": "free",
"description": "",
"short_description": "",
"designer": "beefree-team",
"id": "empty",
"is_blank": true,
"template_type": "email",
"order": "99999999",
"published_at": "2017-08-28",
"tags": [
"black",
"light",
"promote",
"serif",
"two-column",
"white"
],
"thumbnail_large": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/1_large.jpg",
"thumbnail": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/1.jpg",
"title": "Empty"
},
{
"categories": [
"others"
],
"collections": "",
"context": "free",
"description": "",
"short_description": "",
"designer": "beefree-team",
"id": "empty-page",
"is_blank": true,
"template_type": "page",
"order": "99999998",
"published_at": "2021-07-19",
"tags": [],
"thumbnail_large": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/4246_large.jpg",
"thumbnail": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/4246.jpg",
"title": "Empty Page"
}
],
"facets": {
"categories": [
{
"id": "events",
"name": "Events",
"parent": "usage",
"count": 353
},
{
"id": "seasonal-promotion",
"name": "Seasonal Promotion",
"parent": "seasonal",
"count": 345
},
{
"id": "e-commerce",
"name": "E-commerce",
"parent": "industry",
"count": 316
}
]
}
}
Get a specific template from the catalog.
{"message":"Success"}
GET /v1/catalog/templates/:slug HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"message": "Success"
}
Get a list of collections from the catalog.
{"count":19,"next":"https://api.getbee.io/v1/catalog/collections?page=2&pagesize=10","previous":null,"results":[{"bg_color":"#E8F8D4","description":"A Beefree collection is a set of templates focused on a specific communication need. Whether you need to create an automated email sequence to onboard new customers, launch a new product, or dress up transactional messages for your online store, Beefree collections will help you hit the ground running and achieve your goals faster.","short_description":"","fg_color":"#140244","highlighted":false,"icon_url":"https://d1oco4z2z1fhwp.cloudfront.net/collections/real-estate_icon.svg","id":"real-estate","image_url":"https://d1oco4z2z1fhwp.cloudfront.net/collections/Real-Estate-TC.png","name":"Real Estate","order":"0"}]}
GET /v1/catalog/collections HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"count": 19,
"next": "https://api.getbee.io/v1/catalog/collections?page=2&pagesize=10",
"previous": null,
"results": [
{
"bg_color": "#E8F8D4",
"description": "A Beefree collection is a set of templates focused on a specific communication need. Whether you need to create an automated email sequence to onboard new customers, launch a new product, or dress up transactional messages for your online store, Beefree collections will help you hit the ground running and achieve your goals faster.",
"short_description": "",
"fg_color": "#140244",
"highlighted": false,
"icon_url": "https://d1oco4z2z1fhwp.cloudfront.net/collections/real-estate_icon.svg",
"id": "real-estate",
"image_url": "https://d1oco4z2z1fhwp.cloudfront.net/collections/Real-Estate-TC.png",
"name": "Real Estate",
"order": "0"
}
]
}
Retrieve a specific collection in the catalog.
{"bg_color":"#FBFBFB","description":"A Beefree collection is a set of templates focused on a specific communication need. Whether you need to create an automated email sequence to onboard new customers, launch a new product, or dress up transactional messages for your online store, Beefree collections will help you hit the ground running and achieve your goals faster.","short_description":"","fg_color":"#140242","highlighted":false,"icon_url":"https://d1oco4z2z1fhwp.cloudfront.net/collections/photo.svg","id":"photography","image_url":"https://d1oco4z2z1fhwp.cloudfront.net/collections/Photography-TC.png","name":"Photography","order":"0"}
GET /v1/catalog/collections/:slug HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"bg_color": "#FBFBFB",
"description": "A Beefree collection is a set of templates focused on a specific communication need. Whether you need to create an automated email sequence to onboard new customers, launch a new product, or dress up transactional messages for your online store, Beefree collections will help you hit the ground running and achieve your goals faster.",
"short_description": "",
"fg_color": "#140242",
"highlighted": false,
"icon_url": "https://d1oco4z2z1fhwp.cloudfront.net/collections/photo.svg",
"id": "photography",
"image_url": "https://d1oco4z2z1fhwp.cloudfront.net/collections/Photography-TC.png",
"name": "Photography",
"order": "0"
}
GET /v1/catalog/categories HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"count": 114,
"next": null,
"previous": null,
"results": [
{
"bg_color": "#F8F8F8",
"fb_color": "#333A45",
"highlighted": false,
"icon": null,
"id": "leap-year",
"image": null,
"name": "Leap Year",
"description": "Make every extra day count with our Leap Year email templates. Whether you're celebrating a special promotion, organizing an exclusive event, or simply seizing the opportunity for a unique marketing campaign, our templates are designed to make your Leap Year messages stand out.",
"short_description": "Engage your audience with visually appealing designs that capture the essence of this rare occurrence.",
"parent": "seasonal"
}
]
}
Retrieve a specific category in the catalog.
{"bg_color":"#F8F8F8","fb_color":"#333A45","highlighted":false,"icon":null,"id":"fashion-week","image":null,"name":"Fashion Week","description":"Strut into the spotlight of style with our Fashion Week email templates. Whether you're unveiling a new collection or promoting exclusive runway-inspired deals, these templates offer a chic and visually captivating platform to make your mark during the most fashionable moments.","short_description":"Stand out this Fashion Week with our email and page templates","parent":"seasonal"}
GET /v1/catalog/categories/:slug HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Accept: */*
{
"bg_color": "#F8F8F8",
"fb_color": "#333A45",
"highlighted": false,
"icon": null,
"id": "fashion-week",
"image": null,
"name": "Fashion Week",
"description": "Strut into the spotlight of style with our Fashion Week email templates. Whether you're unveiling a new collection or promoting exclusive runway-inspired deals, these templates offer a chic and visually captivating platform to make your mark during the most fashionable moments.",
"short_description": "Stand out this Fashion Week with our email and page templates",
"parent": "seasonal"
}
{
"page": {
"body": { ... },
...
}
}
Use this endpoint to transform any template's Beefree JSON into HTML. This endpoint is compatible with Email, Page, and Popup builder designs.
The collection ID or name
An object field for comments
An integer field for beautifyHtmlEnabled
Use this endpoint to transform any template's Beefree JSON into HTML. This endpoint is compatible with Email builder designs.
The collection ID or name
A string field for language
{
"page_size": "Full",
"page_orientation": "landscape",
"html": "<!DOCTYPE html>...</html>"
}
Transform email or page HTML into a PDF that can be attached to emails, SMS messages, or physically printed out.
The collection ID or name
A string field for page_size
A string field for page_orientation
A string field for html
{
"html": "<!DOCTYPE html>...</html>",
"width": 800,
"height": 600
}
html*
String
A Beefree HTML message.
size
String
Use “size” instead of “width” and “height” when you only know the width and want the height automatically calculated. Required if width and height are not defined.
width
Integer
The image width in pixels. Required if size is not defined.
height
Integer
The image height in pixels. Default applies a proportional value based on the given width, keeping the image aspect ratio. When the value is not proportional to the given width, either will occur: If it’s higher, the proportional value applies, or, if it’s lower, the image is cropped. Required if size is not defined.
file_type*
String
Accepts jpg or png.
POST /v1/{collection}/merge-rows HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 8386
{
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>Updated paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "29cd2a3d-fd76-4537-a91b-b8cb9872d8a3"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Arvo', 'Courier New', Courier, monospace",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e22bd20c-805e-439a-832c-f7a100dcaaf2"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "600px"
}
},
"empty": false,
"locked": false,
"metadata": {
"message_type": "email",
"name": "test",
"guid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
},
"synced": true,
"type": "one-column-empty",
"uuid": "55bd90ef-1d57-450d-adab-d97727b1db4a"
}
],
"rowIdentifierLabel": "guid",
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#ffffff"
}
},
"content": {
"computedStyle": {
"linkColor": "#7747FF",
"messageBackgroundColor": "transparent",
"messageWidth": "600px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"name": "Alegreya",
"url": "https://fonts.googleapis.com/css2?family=Alegreya:wght@100;200;300;400;500;600;700;800;900"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "29cd2a3d-fd76-4537-a91b-b8cb9872d8a3"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Arvo', 'Courier New', Courier, monospace",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e22bd20c-805e-439a-832c-f7a100dcaaf2"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "600px"
}
},
"empty": false,
"locked": false,
"metadata": {
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
},
"synced": true,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "29cd2a3d-fd76-4537-a91b-b8cb9872d8a3"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Arvo', 'Courier New', Courier, monospace",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e22bd20c-805e-439a-832c-f7a100dcaaf2"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "600px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
}
},
"webFonts": [
{
"fontFamily": "'Arvo', 'Courier New', Courier, monospace",
"name": "Arvo",
"url": "https://fonts.googleapis.com/css2?family=Arvo:wght@100;200;300;400;500;600;700;800;900"
},
{
"fontFamily": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"name": "Alegreya",
"url": "https://fonts.googleapis.com/css2?family=Alegreya:wght@100;200;300;400;500;600;700;800;900"
},
{
"fontFamily": "'Chivo', Arial, Helvetica, sans-serif",
"name": "Chivo",
"url": "https://fonts.googleapis.com/css2?family=Chivo:wght@100;200;300;400;500;600;700;800;900"
}
]
}
{
"message": "Success"
}
POST /v1/{collection}/merge HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 46687
{
"replace": [
{
"path": "$..rows[?(@.metadata.uid=='508824c4-8d45-11ee-84be-aafd6b2aca16')]",
"value": {
"columns": [
{
"grid-columns": 4,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[1].image_url$",
"height": "500px",
"href": "",
"prefix": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px"
},
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "ebce211c-e771-4a85-ac7b-e4b40f9dc041"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 1\" data-bee-value=\"$product_reco[1].name (new)$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "1dff7521-11ca-4fa5-aab0-ef3ab1e7cc28"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 1\" data-bee-value=\"$product_reco[1].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "dfe9b1ee-13a2-4d64-b6b6-f917fe359874"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 1\" data-bee-value=\"$product_reco[1].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "edd551af-b2d5-4e84-a03e-188f5612c242"
},
{
"descriptor": {
"button": {
"href": "$product_reco[1].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\">product button 1</p></div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"height": 38,
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"width": 131
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "f2dfb43a-9b2c-4a6c-934c-185b8995cf4a"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "909f2b4f-557e-4aad-acc8-ae48b2fd8fd1"
},
{
"grid-columns": 4,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[2].image_url$",
"height": "500px",
"href": "",
"prefix": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px"
},
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "1b5fa1b7-8ce8-4f67-a9e0-9b19038a788b"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 2\" data-bee-value=\"$product_reco[2].name$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "de22ee0a-c86e-4811-a8ed-76dd8039267b"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 2\" data-bee-value=\"$product_reco[2].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "a8f24663-e5bc-4cf4-b448-1cbc8ebf9349"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 2\" data-bee-value=\"$product_reco[2].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "a665bd50-39d6-43f6-9148-d7ed7de1d931"
},
{
"descriptor": {
"button": {
"href": "$product_reco[2].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\">product button 2</p></div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"height": 38,
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"width": 131
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "f1c7e4e9-e11f-4be5-99c6-a36ee56378ce"
},
{
"type": "mailup-bee-newsletter-modules-button",
"descriptor": {
"button": {
"label": "<div class=\"txtTinyMce-wrapper\"><p style='font-family: inherit;'>Button</p></div>",
"href": "",
"target": "_blank",
"style": {
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"background-color": "#3AAEE0",
"border-radius": "4px",
"border-top": "0px solid transparent",
"border-right": "0px solid transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"color": "#ffffff",
"line-height": "200%",
"padding-top": "5px",
"padding-right": "20px",
"padding-bottom": "5px",
"padding-left": "20px",
"width": "auto",
"max-width": "100%",
"direction": "ltr"
}
},
"style": {
"text-align": "center",
"padding-top": "10px",
"padding-right": "10px",
"padding-bottom": "10px",
"padding-left": "10px"
},
"mobileStyle": {},
"computedStyle": {
"width": 52,
"height": 42,
"hideContentOnMobile": false
}
},
"uuid": "974e36a4-dd64-43ac-a6d2-ddbe74120e13",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "e2982735-0bbc-473d-b2f3-ae2f70f1e14e"
},
{
"grid-columns": 4,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[3].image_url$",
"height": "500px",
"href": "",
"prefix": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px"
},
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "0be65661-f596-4dc8-afa2-f886d64439b2"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 3\" data-bee-value=\"$product_reco[3].name$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "23c9c3b8-ce5c-48e1-8491-90a982799c35"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 3\" data-bee-value=\"$product_reco[3].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e4a351b9-cf06-4040-8db0-31202ec9e37c"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068A5"
},
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 3\" data-bee-value=\"$product_reco[3].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "131bac4a-4396-4559-819c-688abbb571cb"
},
{
"descriptor": {
"button": {
"href": "$product_reco[3].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\">product button 3</p></div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"height": 38,
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"width": 131
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "264812f2-d487-4d1c-baab-554921508b56"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "2bfe2efe-af8f-43cf-9b6a-b6003a85f937"
}
],
"container": {
"displayCondition": {
"after": "{ SPLIO ENDPRODUCT_RECO }",
"before": "{ SPLIO PRODUCT_RECO 4 }",
"description": "desc product reco 4",
"label": "product reco 4",
"type": "BEE_CUSTOM_DISPLAY_CONDITION"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "500px"
}
},
"empty": false,
"locked": false,
"metadata": {
"name": "ProductReco NEW 2",
"uid": "508824c4-8d45-11ee-84be-aafd6b2aca16"
},
"synced": true,
"type": "",
"uuid": "8b547e1e-2b19-46af-a86d-3dc0cb3d3893"
}
}
],
"source": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#FFFFFF"
}
},
"content": {
"computedStyle": {
"linkColor": "#0068A5",
"messageBackgroundColor": "transparent",
"messageWidth": "500px"
},
"style": {
"color": "#000000",
"font-family": "Arial, 'Helvetica Neue', Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": []
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"type": "mailup-bee-newsletter-modules-heading",
"descriptor": {
"heading": {
"title": "h1",
"text": "<span class=\"tinyMce-placeholder\">ProductRecoOne</span>",
"style": {
"color": "#555555",
"font-size": "23px",
"font-family": "inherit",
"link-color": "#E01253",
"line-height": "120%",
"text-align": "center",
"direction": "ltr",
"font-weight": "700",
"letter-spacing": "0px"
}
},
"style": {
"width": "100%",
"text-align": "center",
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"mobileStyle": {},
"computedStyle": {
"width": 52,
"height": 42
}
},
"uuid": "ba1fd29b-4e18-4a69-a708-9755a2da87d5",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px dotted transparent",
"border-left": "0px dotted transparent",
"border-right": "0px dotted transparent",
"border-top": "0px dotted transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56978ed0-79cd-494f-8c72-b6f9470c5ef3"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "500px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "a0a410e4-3b14-4a41-98ba-fe6a355b79fa"
},
{
"columns": [
{
"uuid": "736d2504-9d0d-485f-87c9-d1ff3dfd1588",
"grid-columns": 4,
"modules": [
{
"uuid": "60650bb5-c0f5-449f-bfa0-2ffc25a7b04a",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[1].image_url$",
"href": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px",
"height": "500px"
},
"mobileStyle": [],
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"type": "mailup-bee-newsletter-modules-image",
"align": "left"
},
{
"uuid": "f3fd437e-0ecc-4585-81b0-db39d9b260f5",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 1\" data-bee-value=\"$product_reco[1].name$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "125f536f-46b7-4cdf-8a59-25168357387e",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 1\" data-bee-value=\"$product_reco[1].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "2d35f73e-20f2-4d20-a2af-55c3b3bd8186",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 1\" data-bee-value=\"$product_reco[1].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "810f6968-7aaf-4b20-b892-9407cacd73e0",
"descriptor": {
"button": {
"href": "$product_reco[1].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\">product button 1</div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
},
"mobileStyle": [],
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"type": "mailup-bee-newsletter-modules-button",
"align": "left"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
}
},
{
"uuid": "8324c1fb-8485-4429-9ffe-8cd656bbaef2",
"grid-columns": 4,
"modules": [
{
"uuid": "e866a16b-56ee-43c1-bfce-9a10a7f6a3fd",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[2].image_url$",
"href": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px",
"height": "500px"
},
"mobileStyle": [],
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"type": "mailup-bee-newsletter-modules-image",
"align": "left"
},
{
"uuid": "7b070eae-4b65-46e2-8b9b-4449b36edeaa",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 2\" data-bee-value=\"$product_reco[2].name$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "f133b5f7-cc70-4ac2-aa43-6e504ac52bc2",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 2\" data-bee-value=\"$product_reco[2].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "2cb7b14a-29f5-4f9c-8068-7b9dd4090ce4",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 2\" data-bee-value=\"$product_reco[2].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "12bc82a2-b6be-4be5-aa83-f4434eb11344",
"descriptor": {
"button": {
"href": "$product_reco[2].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\">product button 2</div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
},
"mobileStyle": [],
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"type": "mailup-bee-newsletter-modules-button",
"align": "left"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
}
},
{
"uuid": "54be4f34-5d62-4779-adcb-4762d2e42161",
"grid-columns": 4,
"modules": [
{
"uuid": "2b07c014-bd37-47e2-b3cf-594c1dc61969",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "156.66666666666666px"
},
"image": {
"alt": "",
"dynamicSrc": "$product_reco[3].image_url$",
"href": "",
"src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiNGM0YzRjMiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMzMS4yNTMgMjExLjY1NEwyMzUuOTc5IDE4Ni4xMjZMMjE1LjA3OSAyNjQuMTI5TDI1MS45ODkgMjQ4LjUxM0wyNzEuMzUgMjYzLjQwN0wzMjMuMTcyIDI0MS44MTVMMzMxLjI1MyAyMTEuNjU0Wk0zMDUuNzI1IDMwNi45MjhMMjc5LjgxNCAyOTkuOTg1TDMwNS44OTEgMzA2LjMwN0wzMDUuNzI1IDMwNi45MjhaTTIzNy4yNzQgMTgxLjI5NkwyMzIuNDQ0IDE4MC4wMDJMMjMxLjE1IDE4NC44MzJMMjA1LjYyMSAyODAuMTA2TDIwNC4zMjcgMjg0LjkzNUwyMDkuMTU3IDI4Ni4yMjlMMzA0LjQzMSAzMTEuNzU4TDMwOS4yNiAzMTMuMDUyTDMxMC41NTQgMzA4LjIyMkwzMzYuMDgzIDIxMi45NDhMMzM3LjM3NyAyMDguMTE5TDMzMi41NDggMjA2LjgyNUwyMzcuMjc0IDE4MS4yOTZaTTI1OS40MzUgMjM2LjU5NUMyNjYuODM4IDIzNi41OTUgMjcyLjgzOSAyMzAuNTk0IDI3Mi44MzkgMjIzLjE5MUMyNzIuODM5IDIxNS43ODggMjY2LjgzOCAyMDkuNzg2IDI1OS40MzUgMjA5Ljc4NkMyNTIuMDMyIDIwOS43ODYgMjQ2LjAzIDIxNS43ODggMjQ2LjAzIDIyMy4xOTFDMjQ2LjAzIDIzMC41OTQgMjUyLjAzMiAyMzYuNTk1IDI1OS40MzUgMjM2LjU5NVoiIGZpbGw9IiM5Nzk4OTQiLz4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIxNy42MDQgMjEyLjc2NEgyMTQuNTAyVjIxNC4wMTRWMjE1LjI2NEgyMTYuOTM0TDIxNy42MDQgMjEyLjc2NFpNMTYyLjYyMiAyMTguMTI1SDE2My44NzJIMTY1LjEyMlYyMTUuMjY0SDE2Ny4zMzhWMjE0LjAxNFYyMTIuNzY0SDE2NS4xMjJIMTYzLjg3MkgxNjIuNjIyVjIxNC4wMTRWMjE1LjI2NFYyMTguMTI1Wk0xNzYuNzcxIDIxMi43NjRIMTg2LjIwNFYyMTQuMDE0VjIxNS4yNjRIMTc2Ljc3MVYyMTQuMDE0VjIxMi43NjRaTTE5NS42MzcgMjE0LjAxNFYyMTIuNzY0SDIwNS4wNjlWMjE0LjAxNFYyMTUuMjY0SDE5NS42MzdWMjE0LjAxNFpNMjc0LjU2NSAzMTQuNjM3SDI3NS44MTVWMzE3LjQ5OVYzMTguNzQ5VjMxOS45OTlIMjc0LjU2NUgyNzMuMzE1SDI3MS4wOTlWMzE4Ljc0OVYzMTcuNDk5SDI3My4zMTVWMzE0LjYzN0gyNzQuNTY1Wk0yNjEuNjY2IDMxOC43NDlWMzE5Ljk5OUgyNTIuMjMzVjMxOC43NDlWMzE3LjQ5OUgyNjEuNjY2VjMxOC43NDlaTTI0Mi44IDMxOC43NDlWMzE5Ljk5OUgyMzMuMzY4VjMxOC43NDlWMzE3LjQ5OUgyNDIuOFYzMTguNzQ5Wk0yMjMuOTM1IDMxOC43NDlWMzE5Ljk5OUgyMTQuNTAyVjMxOC43NDlWMzE3LjQ5OUgyMjMuOTM1VjMxOC43NDlaTTIwNS4wNjkgMzE4Ljc0OVYzMTkuOTk5SDE5NS42MzdWMzE4Ljc0OVYzMTcuNDk5SDIwNS4wNjlWMzE4Ljc0OVpNMTg2LjIwNCAzMTguNzQ5VjMxOS45OTlIMTc2Ljc3MVYzMTguNzQ5VjMxNy40OTlIMTg2LjIwNFYzMTguNzQ5Wk0xNjcuMzM4IDMxOC43NDlWMzE5Ljk5OUgxNjUuMTIySDE2My44NzJIMTYyLjYyMlYzMTguNzQ5VjMxNy40OTlWMzE0LjYzN0gxNjMuODcySDE2NS4xMjJWMzE3LjQ5OUgxNjcuMzM4VjMxOC43NDlaTTE2My44NzIgMzAzLjkxNEgxNjIuNjIyVjI5My4xOUgxNjMuODcySDE2NS4xMjJWMzAzLjkxNEgxNjMuODcyWk0xNjMuODcyIDI4Mi40NjdIMTYyLjYyMlYyNzEuNzQzSDE2My44NzJIMTY1LjEyMlYyODIuNDY3SDE2My44NzJaTTE2My44NzIgMjYxLjAySDE2Mi42MjJWMjUwLjI5NkgxNjMuODcySDE2NS4xMjJWMjYxLjAySDE2My44NzJaTTE2My44NzIgMjM5LjU3M0gxNjIuNjIyVjIyOC44NDlIMTYzLjg3MkgxNjUuMTIyVjIzOS41NzNIMTYzLjg3MloiIGZpbGw9IiM5Nzk4OTQiLz4KPC9zdmc+Cg==",
"target": "_blank",
"width": "500px",
"height": "500px"
},
"mobileStyle": [],
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "100%"
}
},
"type": "mailup-bee-newsletter-modules-image",
"align": "left"
},
{
"uuid": "5e458b01-7574-4c5c-84a4-a62901b3b400",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product name 3\" data-bee-value=\"$product_reco[3].name$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "dd60bc41-f15a-447d-92bb-d3193d7ea625",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product description 3\" data-bee-value=\"$product_reco[3].description$\"><q>no-content</q></code>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "12px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "9d899e18-9f54-4f19-bfe4-2cea5bc5e9dd",
"descriptor": {
"paragraph": {
"html": "<code spellcheck=\"false\" data-bee-type=\"mergetag\" data-bee-code=\"\" data-bee-name=\"product price 3\" data-bee-value=\"$product_reco[3].price$\"><q>no-content</q></code> €",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "inherit",
"font-size": "13px",
"font-weight": "500",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"type": "mailup-bee-newsletter-modules-paragraph",
"align": "left"
},
{
"uuid": "cb56d5c0-1743-458a-b19c-c5a49ca3342d",
"descriptor": {
"button": {
"href": "$product_reco[3].extid$",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\">product button 3</div>",
"style": {
"background-color": "#3AAEE0",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "4px",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"color": "#ffffff",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
},
"mobileStyle": [],
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"type": "mailup-bee-newsletter-modules-button",
"align": "left"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
}
}
],
"type": "",
"name": "ProductRecoOne",
"locked": false,
"synced": true,
"metadata": {
"name": "ProductRecoOne",
"uid": "508824c4-8d45-11ee-84be-aafd6b2aca16"
},
"container": {
"displayCondition": {
"after": "{ SPLIO ENDPRODUCT_RECO }",
"before": "{ SPLIO PRODUCT_RECO 4 }",
"description": "desc product reco 4",
"label": "product reco 4",
"type": "BEE_CUSTOM_DISPLAY_CONDITION"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "500px"
}
},
"uuid": "cce7dcda-25e5-47b1-aa9e-16e251c6a184"
}
],
"saveRows": true,
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"comments": {}
}
}
{
"message": "Success"
}
POST /v1/{collection}/synced-rows HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 5932
{
"rowIdentifierLabel": "guid",
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#ffffff"
}
},
"content": {
"computedStyle": {
"linkColor": "#7747FF",
"messageBackgroundColor": "transparent",
"messageWidth": "600px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"name": "Alegreya",
"url": "https://fonts.googleapis.com/css2?family=Alegreya:wght@100;200;300;400;500;600;700;800;900"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "29cd2a3d-fd76-4537-a91b-b8cb9872d8a3"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Arvo', 'Courier New', Courier, monospace",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e22bd20c-805e-439a-832c-f7a100dcaaf2"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "600px"
}
},
"empty": false,
"locked": false,
"metadata": {
"guid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
},
"synced": true,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "29cd2a3d-fd76-4537-a91b-b8cb9872d8a3"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#7747FF",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#101112",
"direction": "ltr",
"font-family": "'Arvo', 'Courier New', Courier, monospace",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "e22bd20c-805e-439a-832c-f7a100dcaaf2"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "600px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
}
},
"webFonts": [
{
"fontFamily": "'Arvo', 'Courier New', Courier, monospace",
"name": "Arvo",
"url": "https://fonts.googleapis.com/css2?family=Arvo:wght@100;200;300;400;500;600;700;800;900"
},
{
"fontFamily": "'Alegreya', 'Trebuchet MS', Helvetica, sans-serif",
"name": "Alegreya",
"url": "https://fonts.googleapis.com/css2?family=Alegreya:wght@100;200;300;400;500;600;700;800;900"
},
{
"fontFamily": "'Chivo', Arial, Helvetica, sans-serif",
"name": "Chivo",
"url": "https://fonts.googleapis.com/css2?family=Chivo:wght@100;200;300;400;500;600;700;800;900"
}
]
}
{
"message": "Success"
}
The Reusable Content page discusses, on a very high-level, the differences between key row-related features offered within Beefree SDK. This page provides more detailed information on pre-building and saving reusable content.
By enabling the Save Rows feature, your end users will be able to save design elements that they want to use in other designs in the future.
To display saved rows in the Rows tab, add them to the list of rows available to users by leveraging the Custom Rows feature.
When using the standard, empty rows, users are forced to start from scratch every time they introduce a new row.
A set of pre-built rows may accelerate message construction, providing users with commonly used structures filled with sample content. For example, a set of headers, footers, news sections, etc.
With Custom rows you – the host application – are in control of the content that is included. In some cases, providing canned text can speed up the email creation process and provide consistency across all the communications.
Imagine, for example, the case of a CRM where customer success representatives can quickly build curated emails selecting from a number of pre-built text blocks.
In addition to the empty rows that have always been part of the Beefree SDK system, we now provide a set of default rows that you can add to your application with a simple configuration parameter.
They feature a series of popular structures, filled with placeholder text, images, and buttons.
For some users, they may work better than empty rows as they allow them to immediately visualize what they can accomplish with a specific structure.
Reference Rows Configuration to learn more about how to configure these sample rows.
Does your application onboard users asking for company or brand information?
If so, you can use custom rows to provide footers with legal information already applied (and centralized), header designs that already include the company logo, etc.
Other common use cases:
Approved promotional material
QR codes or barcodes
Advertising content
Product recommendation templates
Check how to configure these sample rows below under Rows configuration > Parameters > Default rows
Create custom rows with content from different sources like blogging platforms, content management systems, etc.
This will allow your customers to save time and reduce errors by avoiding copying and pasting text, links, and images.
Additionally, this helps you ensure that only reviewed and approved contents, provided by a common repository, are used in the message creation.
Transform products from your e-commerce catalog into custom rows, using product images, text, and call to actions to create a promotional message with a few clicks.
You can divide the products into categories and feed them into the builder as different arrays of custom rows.
Or you can use different sets of custom rows to provide different layout options in order to add design flexibility.
Saved Rows allows users to select a row in a message and save it for later use. More specifically, it allows 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 the Custom Rows feature, can feed these saved elements back to the builder as rows that can be dragged into other messages.
In this tutorial, you will learn how to implement Saved Rows in an application that has embedded Beefree SDK.
Also, see the sample code!
When the feature is enabled, a new Save icon is added to the action icons when a row is selected:
The same action is also available in the row properties panel when a row is selected:
By clicking on this icon, users trigger a request to the host application to store the row’s JSON document, which includes:
row structure and settings;
contents and their settings;
all style settings.
It is entirely up to the host application:
where to store the JSON documents that describe these saved rows;
if and how to display them to users of the application;
whether to allow users to edit them individually
when and how to feed them back to the builder, using the Custom Rows feature.
There are two data structures that are important to understand and utilize when working with both Custom Rows and Self-hosted Saved Rows.
These structures are the following:
Reference the Simple Row Schema documentation or the GitHub repository for Simple Schema to learn more. Throughout the subsequent pages, these two schemas and their applications will be referenced and discussed more thoroughly.
The following code shows a row with metadata
and columns
objects.
[
{
metadata: {
name: 'My row name' // Identifies the row, required.
}
columns: { ... }
...
}, // The row that was previously saved. - (*)
...
]
The metadata
section of the rows schema allows you to keep track of row-specific information.
metadata: {
"name": "My Saved Row", // The row's title displayed in the "Rows" panel.
"tags": "product, two columns, blue",
... additional custom parameters
}
name
: The saved row’s title displayed 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
Recommended metadata
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.
Reference the Row Metadata page to learn more.
Learn more about the HTML Importer API offering in Beefree SDK.
Beefree SDK includes a comprehensive API offering designed to expand upon the builder's capabilities. By leveraging Beefree SDK's APIs, you can extend the builder's functionality into other aspects of your application.
Beefree SDK's API offering includes three APIs. They are the following:
This section of the documentation discusses the HTML Importer API, which includes resources for programmatically importing pre-existing HTML templates into Beefree SDK's builder.
Import custom HTML into Beefree SDK
✅ Yes, .
Export, convert, and style templates and rows. Use AI to generate metadata, SMS, and summaries.
✅ Yes,.
Access Beefree's catalog of templates
✅ Yes, .
The HTML Importer API allows you to import your own HTML files into Beefree SDK. To use the HTML Importer API, you'll need to create an API key for the HTML Importer in the Beefree SDK Developer Console. Visit the Import HTML page to learn how to make API calls with the HTML Importer API.
Manually migrating your existing templates can be time-consuming, but with the HTML Importer API you can:
Make existing HTML editable in the Beefree SDK: Empower your end-users to edit their current HTML email templates using the intuitive drag-and-drop interface — without having to manually recreate them
Save time and resources: Manually recreating email templates from scratch can take hours. With the new Importer API, you can make existing email templates editable in Beefree in seconds.
Significantly reduce migration friction for faster client onboarding: Overcome the challenge of template migration, a common pain point when bringing on new clients. The HTML Importer API streamlines this process, allowing for quicker onboarding.
The HTML Importer API is a REST-based API that enables Beefree SDK integrators to programmatically convert email HTML into Beefree JSON. It is built to follow predictable resource url patterns, and to utilize standard HTTP response codes and methods. This service is particularly helpful if you (or your end users) have pre-existing HTML templates you'd like to load within the no-code Beefree SDK builder and edit in the drag-and-drop editor.
Beefree SDK requires that you authenticate prior to accessing the HTML Importer API's resources and obtain an API key for your production application.
The resource in HTML Importer API is a synchronous endpoint that accepts the email HTML as the body of a POST
request and returns the Beefree JSON in the response.
The following webinar utilizes the demo code in the html-importer-spotlight repository to demonstrate an example of how to use the HTML Importer API along with the Brand Style endpoint to create a compelling import and brand styling experience for your application's end users.
This section provides a high-level overview of the concepts related to the HTML Importer API. For detailed information on how to activate, use, and implement the endpoint, visit the Import HTML page, which includes comprehensive implementation steps and considerations. The HTML Importer leverages a series of algorithms to map and classify all the content elements available in the email, label them, and then translate them into Beefree's JSON format.
Using a simple API, you can pass us the email you'd like us to convert, and the API will return Beefree JSON in response:
Explore answers to the most frequently asked questions.
There are a few things you should be aware of to ensure a great import experience:
The conversion engine is designed to convert email HTML. It's not optimized for converting landing pages or other HTMLs.
Ensure your email HTML is valid. We can't import HTML files that miss DOCTYPE
declaration, don't include valid html
and body
elements, or don't include the <meta charset="UTF-8">
tag in the head
section of your HTML.
Our API doesn't convert dynamically created HTML documents that leverage JavaScript to render content. We currently support static HTML and CSS content only.
Ensure that all images and resources included in your HTML are publicly available on the internet. We can't convert emails with images and resources that are only available on private networks.
Please be aware that some HTML elements are not fully supported by the importer at this time, including background images, dividers, and menus.
If you follow the best practices above, the HTML Importer will migrate the structure and content of your HTML into Beefree's JSON format, significantly reducing the time it takes to recreate templates from scratch manually. Some design adjustments may still be necessary to match the original design.
Unsupported HTML tags do not break the endpoint as long as the overall HTML structure is valid. However, they may behave unpredictably and result in suboptimal imports. Implement validation and sanitization workflows for unsupported HTML tags to ensure proper handling.
No, with the HTML importer API, the result will stay consistent each time you call the API.
You can use this tool in accordance with Beefree's Terms of Service. In particular, you should use the tool in a way that ensures you will not violate the rights of third parties.
Yes, the HTML Importer API can be integrated with usage-based logic. For instance, you can track API calls by user ID and enforce usage limits based on predefined credit tiers. This logic should be implemented within your backend—for example, by maintaining a counter that increments with each API call to monitor and restrict access accordingly.
The HTML Importer API is available for all Beefree SDK plan types, including the free plan. We charge $2 per template import.
Every time you call our HTML Importer API and receive a JSON in response, that’s counted as an import for billing purposes.
If an API call fails for any reason (and we respond with an error rather than a JSON file), you won’t be charged.
For more information on usage and pricing, visit the Usage-based fees article.
No, we do not store any of your templates.
Images are not uploaded to Beefree SDK's file manager. They are referenced from the original source and must be publicly accessible on the internet to display correctly in the builder.
No, the HTML importer API does not use AI to recreate content into our native JSON format. Your templates will not be stored or used for training or data analysis purposes.
External CSS may only work if it is publicly hosted online, but its behavior is not guaranteed as it has not been thoroughly tested. It is best to inline CSS for reliable results. Merge tags are not supported during import but can be added afterward in the builder.
Dynamic content must be configured after import. The importer does not interpret or map dynamic content placeholders. You can apply dynamic content once the HTML is converted and editable in the Beefree SDK.
The HTML Importer API only supports plain HTML. If clients provide .eml or other formats, you’ll need to convert them to static HTML before importing. Consider developing preprocessing tools for recurring client onboarding.
Using this simple, client-side example, you can literally try out Beefree SDK in 2 minutes…
Obtain your application keys (Client ID and Client Secret) by signing up here (there is a free plan).
Create a new application: you will find your keys in the project’s details page
Download the client-side sample code.
Open index.html
with your favorite code editor
Locate client_id
and replace “YOUR_CLIENT_ID” with yours
Locate client_secret
and replace “YOUR_CLIENT_SECRET” with yours
Save the file
Open it in your browser and get creative
Before using the code samples listed below in a production environment, please consider the following:
Make sure you first sign up and get your application keys (Client ID and Client Secret).
The client-side sample is not safe for a production environment (it was conceived as a quick way for you to test the application). Someone would be able to easily steal your application credentials (just viewing the source code of the page). To keep those credentials safe, authorization must be managed sever-side, as the .NET sample does.
These code samples use a limited set of features and configurations: they can be a good starting point to start developing around Beefree SDK, but they are not an exhaustive showcase of everything you can do.
All sample code is provided “as is”: it may contain defects, it may not follow best practices (although we try to!), and it should only be considered as point of reference.
Demonstrates integrating the Beefree SDK into a full-stack NextJS application with database integration and user authentication.
NextJS, Python, SQLite
The official NPM package for Beefree SDK, complete with installation instructions and configuration tips.
Typescript
Code from our latest webinars showcasing how to use Saved and Synced Rows feature within the Beefree SDK.
ReactJS
A collection of free email, landing page, and popup templates designed for easy integration with the Beefree SDK.
JSON
A simple HTML app demonstrating the basic implementation of the Beefree SDK for client-side applications.
HTML, JavaScript
Assuming that beeInstance
is the instance of your embedded builder application, here are the methods you can call:
If you use a paid plan, you can hide the top toolbar and control the builder from your application’s user interface. For example, it’s up to you at that point to have buttons above or below the builder. Here’s some useful methods for this scenario:
The top toolbar displayed by default within the builder contains buttons that trigger certain actions. These are the callbacks that are triggered when the buttons are clicked.
Learn more about what Beefree SDK's embeddable no-code email builder is, how to test it out, and how to integrate it into your SaaS application.
Beefree SDK’s embeddable no-code email builder offers a solution that empowers creators to design visually striking, high-converting emails with ease. By removing technical barriers, it enables teams to build, customize, and launch campaigns faster, maximizing results without the need for hard coding. This allows marketers, designers, and content creators to focus more on designing and refining their email strategies, rather than spending time coding emails from scratch.
Email marketing remains one of the most effective digital channels, delivering an impressive —for every $1 spent, businesses see an average return of $36. In a landscape where personalization and quick execution are critical, no-code email builders like Beefree SDK make it easier for teams to create and optimize these high-performing, targeted campaigns. Personalized campaigns, which , are more easily executed with tools that free teams from coding, allowing them to concentrate on strategy and design. By simplifying the email creation process, Beefree SDK enables creators to spend less time on technical tasks and more time driving results through impactful, strategic designs.
The email builder within Beefree SDK is a no-code drag-and-drop editor that enables end users to design beautiful emails that resonate with their audiences. Within the email builder, end users have access to both simple email creation tools, such as adding content blocks, and advanced email creation tools, such as dynamic content, merge tags, display conditions, html blocks, and so on. Beefree SDK’s email builder was created with email marketers, copywriters, designers, and other content creators in mind. It provides them with an environment to intuitively create emails without having to write a single line of code, while being able to easily export their design’s HTML code if they ever need it. Overall, Beefree SDK’s email builder democratizes the email creation process by providing a no-code route for your application’s end users to create visually stunning and appealing emails for their audiences.
Embedding Beefree SDK’s email builder is quick and easy. Once you embed the SDK within your application, you’ll already have access to a host of default features that are instantly available to your application’s end users. In addition to these default features, Beefree SDK also offers a variety of optional features you can easily activate by simplifying toggling them on in the Developer Console. If you want to customize the email builder further, you can also integrate with our, , add , and much more. You can reference of the level of customization that is possible with Beefree SDK.
In the following GIF, you can see an example of differently customized experiences.
On a foundational level, the Email builder includes the capabilities detailed in the following table.
Note: Additional capabilities and features can be added on top of these through , toggle on options in the , , , , and more.
There are various tools you can use to experiment with and test out the Email builder to learn more about it.
The following resources are a great start to learn more:
You do not need a Client ID or Client Secret to experiment with the Email builder in this environment.
You do not need a Client ID or Client Secret to experiment with the Email builder in this environment.
You do need a to experiment with the Email builder in this environment.
To integrate the Email builder, take the following steps:
in the
within the Developer Console
Obtain your Client ID and Client Secret
Authenticate
Use the to and embed Beefree SDK
Visit to learn more about installing Beefree SDK.
When you configure a builder application, you have four options for image & file storage:
Beefree SDK storage: unless you select another option, images will be hosted in Beefree SDK’s own AWS S3 bucket. for details about potential fees associated with this option.
An existing builder application: to connect the selected application’s storage to an already existing application. After selecting this option the two applications will share their storage.
Your own AWS S3 bucket: instead of using Beefree SDK’s AWS S3 bucket to store & deliver files, you can use your own. See .
Your own file system: if your application already has a place where images and other assets are stored, you can leverage it. This option is only available on Beefree SDK paid plans. See using .
When working with your own custom file system provider, there are many considerations to keep in mind. Follow the steps outlined in the documentation to ensure you configure this feature successfully for this storage option.
End users can upload images, PDFs, and other documents to the builder. For instance, they can link a button to download a PDF report.
Reference to learn more about the end user experience with the File manager.
If you need more control on what files users should be able to upload, you may activate in the Privacy & Security section of your app’s configuration. In alternative, you may consider .
Note: In addition to storing images and files within the Beefree SDK File Manager, Beefree SDK also offers a storage option for saving saved rows. This is available through . To store the JSON of full email templates, you'll need to connect your own database to Beefree SDK. While there is an option to host saved rows within Beefree SDK, there currently isn't a way to host full email, page, and popup designs just yet.
By default, images used in emails and pages created with the builder are stored in Beefree SDK’s file storage system. Beefree SDK uses service for storage, and leverages Amazon’s Content Delivery Network () for fast content delivery.
There are no charges for storing images & other documents.
There are no charges for delivering images & other documents up to a total of 5TB of delivery traffic per 30-day period.
Above 5TB of data traffic recorded in a 30-day period, you will be billed $0.01 per GB of data transferred.
Beefree SDK customers that exceed 50 GB of image data traffic on the Free plan in a given month will be moved to our .
You can enable the move icon for files within the File manager. This move icon allows your end users to move their files between folders, locations, and so on within the File manger. They can access the move icon directly on the file within the File manager. The move icon is a folder with an arrow pointing right inside it. End users click this icon to initiate the process of relocating the corresponding file to a new destination.
If you are using the Beefree AWS S3 Bucket, take the following steps to enable this feature for your File manager.
If you are using your own AWS S3 bucket, take the following steps to activate the Move File feature:
Ensure that your FSP is updated to the latest version.
Navigate to the .
Locate the Move File configuration toggle.
Toggle the feature on.
The Move Feature will be available in your application.
Reference answers to the most frequently asked questions about Beefree SDK Storage fees. You can also reference the following pages to learn more about Storage options within Beefree SDK:
When you use the Beefree SDK S3 storage, your images are delivered via a Content Delivery Network (AWS Cloudfront), and AWS bills us based on the traffic generated by those assets when you send emails or publish web pages created with Beefree SDK. A large amount of monthly traffic (5TB) is included in your Beefree SDK paid subscription at no charge.
If you exceed the 5TB monthly traffic allotment, we ask you to cover the cost of the service (for a few of our customers that generate a lot of image data traffic, that cost has grown to exceed their Beefree SDK subscription fee). Also, note that this scenario is quite rare: it applies to less than 3% of our customers.
If you’re on a paid plan, billed monthly, the counter will reset on the same days as your UIDs and CSAPI calls, i.e., on the day your subscription to Beefree SDK is renewed.
If you’re on a paid plan, billed yearly, the counter will reset on the 1st day of each month.
If you’re on a free plan, the counter will reset on the 1st day of each month.
You can always see when the current period starts and ends in your application details, in the Statistics widget:
If you’re on an annual plan, any usage-based fees are still billed monthly. This means that even though your subscription is annual, any additional usage beyond your included monthly allotment will be calculated and charged at the end of each month.
For the moment, only subscriptions on paid plans will be notified by our Customer Success team. If you’re on a free plan, you may check your usage by logging into the , and going into the application details, in the Statistics widget.
You can switch to or .
All traffic generated is charged to the shared storage. E.g.: an Email Builder application shares its storage with a Popup and a Page applications. In this case, the Email Builder application will be charged for the traffic generated by Email + Popup + Page.
It’s not possible to link a development app to a production app.
An app can be linked to another just once.
The same shared storage can be shared across different applications within the same subscription
No, this is not possible. You can either connect production apps included in the same subscription or dev apps included in the same subscription.
Please contact your account manager for this. If you are not sure how to do this, please and submit a support ticket asking for your usage history.
In this box, you can enable additional content blocks that will appear in the Content panel inside the editor.
Currently, you can manage these content blocks:
If you’re configuring a Page Builder application, there are a few differences in what these blocks allow:
the HTML Block also allows script and iframe tags;
the Video block allows for video playback, either embedding a YouTube, YouTube Shorts, or Vimeo video or pointing to a hosted video (). Supported video formats are:
YouTube (16:9 aspect ratio)
Public Videos
Unlisted Videos
Videos starting at a certain time
YouTube Shorts (16:9 aspect ratio)
Vimeo
Public Videos
Unlisted Videos
Cinemascope (21:9 aspect ratio)
the Menu block allows menu items to be set as “internal links,” pointing to any content block in the page that is configured as a “block identifier.”
There is also an additional option for turning on the Form block.
Please note that you need to implement one of the two methods indicated in this article for the Form tile to appear in the Content tab of the editor:
The method is available for all plans, including free
The method is available for paid plans only.
You can enable AMP blocks that will become available in the “Content” tab of your application's Email Builder. To enable this feature, toggle on Enable AMP Carousel in the AMP Content section of your application's configuration options.
We currently provide an content block. After enabling the toggle, you will need to configure an .
Please note that AMP content is not available for Page Builder.
There are three types of pre-built reusable content you can provide your application's end users with. These are the following:
In this page, we will look at a sample rowsConfiguration
that incorporates defaultRows
, emptyRows
, selectedRowType
, and externalContentURLs
. The will discuss the steps to .
The following code snippet provides a sample rowsConfiguration
.
This section explains each of the properties listed in the rowConfiguration
code snippet.
These properties are the following:
: Set of empty rows. The same rows available when rowsConfiguration
is not included. End users can use these empty rows to structure and customize their own content within.
: A set of rows that contain sample content. End users can use the sample content as inspiration for customizing them with their own look and feel.
: Specify which type of row should be pre-selected when the end user opens the Rows selection in the visual builder.
: Each item in this list defines an option available in the Rows tab drop-down.
You can add pre-built default rows to your builder by setting the defaultRows
property to true
in your beeConfig
.
Default rows are a set of rows that contain sample content. That’s why we also call them sample rows. They may be used as a supporting feature for starting templates, or to speed up the process of building a message from scratch.
Allowed values: boolean
, can be set to true
or false
.
Default value: false
They are presented as follows in the builder’s default theme (the screenshot shows the first 2 default rows):
You can add pre-built empty rows to your builder by setting the emptyRows
property to true
in your beeConfig
. Empty rows are a set of rows that aren't prefilled with content. However, they offer a general structure for content to be placed within them. These are the same rows available to end users when the rowsConfiguration
parameter is not included in the .
Allowed values: boolean
, can be set to true
or false
.
Default value: true
Will always be included as the last element if omitted in the configuration.
They are presented as follows in the builder’s default theme (the screenshot shows the first 4 empty rows with unique structures):
This property is used to specify which type of row should be pre-selected when the end user opens the Rows selection in the visual builder. You have several options for what value to assign to this property, and its role is to simplify the end user's interaction with the builder by focusing their attention on a specific type of row by default.
Possible values for selectedRowType
:
'defaultRows'
: This value will automatically select the default rows that come with the builder, which usually contain pre-designed content that users can easily modify and adapt. It helps users start with a pre-configured structure and quickly adjust it to meet their needs.
'emptyRows'
: This value pre-selects an option for the user to start with empty rows. This is useful for users who prefer to build their layouts entirely from scratch, without any predefined content or structure.
The handle of a row in externalContentURLs
:
You can also pass the handle of a row that is listed in externalContentURLs
to pre-select a row from an external source. A handle in this context refers to the unique identifier or name used to reference a specific row from an external list. Think of it as a unique key that allows the system to identify which external row to load or pre-select.
For example, if you have external content rows listed in externalContentURLs
, such as "Rows list 01" or "Rows list 02," you can pass their respective handle (typically a string like "Rows list 01"
) as the value for selectedRowType
. This will automatically load and pre-select that specific external row, saving the user the step of manually selecting it from the list.
The externalContentURLs
property accepts a row's name and url. You can add multiple items to the property. Each item in the list defines an option available in the Rows drop-down.
name
: the text displayed in the Rows drop-down
value
: URL that will be called by the builder when the user selects the corresponding name in the drop-down. The URL must return a set of rows as a JSON object.
The following image displays an example of how the name
value appears in the drop-down menu.
In the drop-down menu, you can see a visual example of each pre-built content type mentioned in this article and in :
Empty rows: When the end user clicks the Empty option in the drop-down menu, they will be redirected to a list of row structures to choose from.
Default rows: When the end user clicks the Default option in the drop-down menu, they will be redirected to a list of default rows to choose from.
My Saved Rows: When the end user clicks the My Saved Rows option in the drop-down menu, they will be redirected to a list of rows they created and at a later time.
Custom rows: The MailChimp Footers, HubSpot Footers, and Sendgrid footers are additional options added to the drop-down through the . When an end user clicks on any of these three options, they will be redirected to the lists of rows available in that external resource.
A handle acts like a reference key to point to a specific row in an external list. Handles are typically unique names or identifiers that can be used to quickly access specific rows from an external content source, ensuring that the correct row is fetched and displayed to the user. For instance, in the following configuration:
If you want to pre-select "Rows list 01" from the external content list, you would set selectedRowType: 'Rows list 01'
, where 'Rows list 01'
is the handle of that specific external content row. The handle here refers to the name or a unique identifier that the system recognizes and uses to select the correct row from the external content list.
Visit to learn more about editing, deleting, categorizing, and managing rows within the builder.
beeInstance.start(templateToLoad)
Starts the builder, loading the templateToLoad
JSON string with the template structure (if specified). If using the NPM package, you have additional options to pass here as defined on the NPM page.
beeInstance.load(template)
Loads the JSON template string specified in the template
parameter.
beeInstance.reload(template)
Loads the JSON template string specified in the template
parameter. Unlike beeInstance.load(template)
, the reload method does not trigger a loading dialog. This method helps quickly reload a template seamlessly for specific use cases, such as using a custom undo/redo feature or injecting custom content in real-time.
beeInstance.execCommand
The frontend performs one of the following actions: highlight, scroll, focus, or select. This is based on the action and target defined in the object. Read more.
beeInstance.preview()
Triggers the message preview behavior within the builder.
beeInstance.togglePreview()
Open/close the message preview behavior within the builder.
beeInstance.toggleStructure()
Controls the visibility of the structure outlines in the message editing portion of the builder.
beeInstance.save()
Invokes the onSave
callback function. The application will pass two files to the function: a JSON file with the message structure (for later editing) and a ready-to-send HTML file.
beeInstance.saveAsTemplate()
Invokes the onSaveAsTemplate
callback function. The application will pass to the function a JSON file with the message structure (for later editing).
beeInstance.send()
Invokes the onSend
callback function. The application will pass to the function a ready-to-send HTML file. Important: This callback is only compatible with the email builder.
beeInstance.toggleMergeTagsPreview()
Controls the visibility of sample content for merge tags in the message editing portion of the builder.
onSave
Fired when the Save button is clicked.
JSON and HTML documents
onSaveAsTemplate
Fired when “Save as template” is clicked.
JSON document
onAutoSave
Fired automatically based on autosave
configuration parameter value.
JSON document
onSend
Fired when the “Send a test button” is clicked.
HTML document
onLoad
Fired when the JSON is loaded in the builder.
JSON document
onError
Fired every time an error occurs.
Error message
onPreview
Fired every time the preview button is pressed.
Status (Boolean)
onTogglePreview
Fired every time the preview is opened or closed.
Status (Boolean)
onChange
Fired every time a change on the message is performed.
onRemoteChange
Triggers during co-editing sessions. It notifies the frontend about changes made by other users in the session.
Note: This is for users B, C, D, and so on, while onChange
is specific to the main user, User A, making the change.
Read more about onRemoteChange
and tracking changes. Read more about collaborative editing.
onComment
Fired every time a thread or comment changes.
onFilePickerInsert
Fired when the “insert” button is clicked. This property must be defined by the host application for the insert button to appear within the user interface. Available for File Manager applications only.
Object with file info
onFilePickerCancel
Fired when the “X” button is clicked. This property must be defined by the host application for the cancel “X” button to appear within the user interface. Available for File Manager applications only.
None
onViewChange
Fired when a view in SDK changes (eg. File manager opens, preview, or image editor)
Either one of these strings:
'fileManager'
- When File Manager opens
'editor'
- When the user closes one of the other views - also triggered when the Editor loads at first
'preview'
- When preview gets opened
'imageEditor'
- When the image editor gets opened
HTML
Allows your users to include their own HTML code
Paid plans only
Menu
Allows users to create simple, text-based navigation elements
All plans, including free
Title
Allows users to add text with H1,H2,H3 tags, for email and web accessibility, and for SEO on web pages.
All plans, including free
List
Allows users to create easy numbered and bullet lists with Paragraph’s upgrades and list type, spacing, and identation support.
All plans, including free
Paragraph
Allows users to write text with support for multiple font weights, copy/paste support, easier reformatting, and more.
All plans, including free
Text
Legacy text block. Please refer to title, paragraph and list.
All plans, including free
Video
Helps users include a visual link to video content
Paid plans only
Icons
Enables users to create icon-based layouts, such as star ratings, bullet lists, properties
All plans, including free
Spacer
Allows users to add a space between content
All plans, including free
Table
Allows users to add a table to their design
All plans
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
selectedRowType: 'my_saved_rows', // pre-select this item in the Rows select
externalContentURLs: [
{
name: "Rows list 01",
value: "https://URL-01"
},
{
name: "Rows list 02",
value: "https://URL-02"
}
]
}
externalContentURLs: [
{
name: "Rows list 01",
value: "https://URL-01"
}
externalContentURLs: [
{
name: "Rows list 01",
value: "https://URL-01"
},
{
name: "Rows list 02",
value: "https://URL-02"
}
]
What if the default styles and standard settings aren’t enough? No worries! In the following sections, we will look at styling your popup to make it look and feel more like the one real visitors will interact with.
A theme is simply a set of custom styles that give the popup its look and feel. Separate from your layout, Popup Builder comes with some preset themes. The primary is our default theme that is loaded when no settings are specified. We also provide an empty theme that has no styles, which you can use a blank canvas to create your own theme. This is one of the most powerful features of Popup Builder, and we’ll be covering custom styles in depth below.
Here is a preview of the configuration:
workspace: {
popup: {
customStyles: {
...
},
}
}
To understand the best way to apply your styles, let’s start by inspecting the underlying HTML structure so you can view where the system will map your styles.
<div id="popup-container">
<div id="popup-header">
<div></div>
<div></div>
</div>
<div id="popup-content">
<!-- BEE CONTENT -->
</div>
<div id="popup-footer">
<div></div>
<div></div>
</div>
</div>
Here is a quick break down of what each div does:
popup-container
This is where you will apply any styles related to how the popup looks, such as border-radius, drop shadows, background colors, or padding.
popup-header
The header is sometimes used to add a close icon to a popup or display a title.
popup-content
The div that holds the editable content of your Beefree application.
popup-footer
You can use this div to show a traditional footer for your popup or position some icons outside the popup container (e.g., a close button).
The above HTML structure is represented in your bee config as the following JSON object.
customStyles: {
container: {},
header: {},
content: {},
footer: {},
overlay: {},
},
Add styles to the JSON section that corresponds to the HTML element you want to style.
For example, if you want to apply styles to the div with id popup-container, then you would add the styles to the following JSON:
customStyles: {
container: {
...styles,
},
},
We’ll go deeper into styling in the following sections.
You may be wondering at this point if you have to design an entire theme to get started. Well, you can if you want to, but thanks to the order of operations, you don’t have to. You can start with our default theme and pass in the styles that you want to override. Any style you provide will take priority over any of the defaults.
We said that you could start from scratch if you want, and the easiest way to do that is by using our theme parameter. This allows you to avoid overriding every default style and gives you an empty canvas to build your own theme.
beeConfig: {
workspace: {
popup: {
theme: 'custom'
}
}
}
Now that you have seen what the HTML looks like and have some idea where to apply your styles, let’s look at how you get your styles into the editor. The best way to show you is by example, so let’s get started with some common use cases!
Using the schema JSON above and your HTML structure knowledge, you probably guessed that the border is defined on the popup container. So here’s what that would look like:
Example:
workspace: {
popup: {
customStyles: {
container: {
border: '1px solid black'
}
}
}
}
workspace: {
popup: {
customStyles: {
container: {
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.5)'
}
}
}
}
After looking at a couple of samples, you may notice these parameters are looking familiar. That’s because every layer of our schema maps to a layer of HTML with the same name AND can be styled with any valid CSS property.
Basically, CSS properties are the same as CSS used by web developers in style sheets, but instead of dashes to separate words, it uses a camel case.
Example:
The CSS property of the style box-shadow would be boxShadow.
Why not use CSS styles as defined by CSS3 specification directly? Well, simply put, CSS properties are better suited for JSON and can easily be shared with any FE application using the popular React framework.
We covered the default layout settings in Setting layout and size section. To recap, the layout determines the type of popup (e.g., a bar) and its location on the screen (e.g., bottom, top, or side). Our research team looked into it, and it turns out, nearly all popups fall into one of the most popular layouts, which we’ve included as presets. But, when that’s not enough, the configuration option customLayout can be used to make minor adjustments to a preset layout or create an entirely new layout from scratch.
Here is a preview of the configuration:
workspace: {
popup: {
customLayout: {
...
},
}
}
The popup is positioned in the workspace using divs and CSS flexbox. We created a layout structure that mimics an HTML page to map your page’s styles to the workspace.
Layout HTML:
<div id="html">
<div id="body">
<div id="main">
<div id="popup-wrapper">
<!-- Popup -->
</div>
<div id="popup-overlay">
</div>
</div>
</div>
Here is a quick break down of what each div does:
HTML
We will apply the styles placed here to the document HTML tag.
body
We will apply the styles placed here to the HTML body tag
main
This is the main container div of the workspace.
popup-wrapper
The wrapper of the popup is used entirely for positioning the popup within the workspace main div.
Example:
workspace: {
popup: {
layout: 'classic-center',
customLayout: {
wrapper: {
maxWidth: '700px'
}
}
}
}
This section provides the information you need to get started integrating PopUp Builder in your SaaS applications. For more advanced settings, see Popup Builder – Advanced Settings.
Out-of-the-box, the setup and configuration are the same as Email and Page Builder. This section will cover the settings specific to Popup Builder. Check out our Getting Started guide if you’re new to Beefree SDK or unfamiliar with the configuration basics (as seen in the example below).
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
...
}
Loading Popup Builder with no additional settings will give the end-user a beautifully designed popup and workspace to design their content. However, Popup Builder comes with an additional, robust set of configuration options to customize the workspace. This allows the host application to build a workspace that matches their popup’s look and feel and that of the destination page.
For example, the host app can customize…
The popup workspace background to view how the popup will look “in context” on the destination page.
The theme and position of the popup for both desktop and mobile design modes.
The following sections will look at how to customize the workspace, starting with the common settings and working up to a full custom layout.
Let’s start by looking at some of the differences between Page Builder and Popup Builder.
Content Width
HTML output
In Email and Page Builder, the content area width is saved in the template. For example, if you start with an empty template, a default width that works for most scenarios is chosen, but the designer can adjust the message width slider. If you start with an existing template, the content width was chosen by the template’s designer using the message width slider in the the builder’s Settings tab.
With Popup Builder, the same template may have multiple contexts, and each context will likely have specific size requirements. For example, an exit-intent popup may have a max-width of 600px on a desktop with a classical layout centered on the screen. On the other hand, the host app may display the same template on mobile in the bar style docked at the bottom of the screen with a restricted width of 300px.
Since the content area’s width is tightly coupled to the context and layout, no one size fits all width is saved in the template. Instead, the host app will specify the width settings when the builder loads, based on the context of using the template. You’ll find an example in the common settings section below.
Popup Builder does not support fluid 100% width content.
In Email and Page Builder, the Beefree SDK HTML parser service converts your template into an HTML document customized for email or pages, respectively. However, the Popup Builder will not return a full HTML page because the host application is the final destination. In addition, Beefree SDKPopup Builder doesn’t provide the scripts to control the popup’s behavior, such as opening and closing. Rather, Popup Builder provides the HTML “partials” to embed within your popup’s content area or body.
The HTML partial will come with all the CSS required to look as it did in the preview mode. The parser service will wrap the content with a special container to clear all the host application styles and prevent style conflicts. The HTML output is designed to be embedded into any popup framework or application and still render the way it appears in the builder.
Now that we covered the basic differences between Popup Builder and our other applications let’s discuss what you should expect when the builder starts.
As mentioned above in the Getting Started section, you will receive a ready-to-go design experience if no settings are provided. The default layout is a classic centered modal with a fixed width.
If the default popup style and layout suit your needs, then you are all set to start designing! You can load the builder without additional configuration and use the same standard controls and callbacks to access the HTML and JSON template.
What if you like most of the defaults but want to make some minor adjustments? We have you covered!
Easily change the background to make the workspace look like the destination page where you’ll embed the popup.
beeConfig: {
...
workspace: {
popup: {
backgroundImage: 'https://.../background.png',
backgroundImageMobile: 'https://.../background.png',
...
}
}
}
If this option is not set, then we will provide a default skeleton layout. It’s worth noting at this point that you can apply every setting for both desktop and mobile design modes. That means you can have a different background when editing in Mobile Design Mode. We’ll show you how later!
One of the most common needs is changing the popup’s default-centered position to better match the end-user’s use case. Out-of-the-box, the Popup Builder comes with many of the most common popup layouts preconfigured. You can use any available presets “as is” or use them as starting points that you can fine-tune to your satisfaction.
beeConfig: {
...
workspace: {
popup: {
layout: 'bar-top'
}
}
}
Here is a complete list of preset layouts:
Classic Popup
classic-center
classic-top-right
classic-top-left
classic-bottom-right
classic-bottom-left
This is our default layout and works great for alerts and exit intents.
Drawer or Slide-in panel
drawer-left
drawer-right
Side panels, or drawers, can be used to design menus or display ads.
Bar or Docker
bar-bottom
bar-top
This is great for cookie approval dialogs.
Another useful preset available is changing the popup’s styles from the default to better match the end-user’s use case. For example, if you’re using the popular Bootstrap CSS framework, you can select the “Bootstrap Theme” as your default. As with the default layouts, you can use any of the available preset themes “as is” or use them as starting points that you can fine-tune to your satisfaction.
beeConfig: {
...
workspace: {
popup: {
theme: 'bootstrap'
}
}
}
Here is a complete list of preset themes:
Custom
custom
This is our default layout and works great for alerts and exit intents.
Bootstrap
bootstrap
This will a popup that looks like the popular Bootstrap CSS modal.
jQuery
jQuery
This will be a popup that looks like the popular jQuery modal. Many of the latest CSS systems use a style similar to the original jQuery.
Material
material
This will be a popup that looks like the popular Material CSS modal.
As mentioned above, the content area’s width is tightly coupled to the layout, no one size fits all width is saved in the template. All Popup Builder preset layouts come with a default width, which you can override with the following configuration settings.
workspace: {
popup: {
contentWidth: 600,
contentWidthMobile: 300
}
}
Continue to Popup Builder- Advanced Settings if you’d like to customize more than the position, background, and content area width.
The stage where the end user drags and drops the content tiles and designs their email.
The content types end users can drag and drop as tiles onto their stage to add to their designs. The Free email builder comes with the following Content tiles (more are available on higher plans):
Title
Paragraph
List
Image
Button
Divider
Spacer
Social
Dynamic content
Icons
Table
When an end user clicks on content on the stage, the Content properties will appear in the sidebar. This is where they can customize the content on their stage. Customization options include Text color, Link color, Line height, Letter spacing, Block options, and more.
End users can drag and drop Rows onto the stage, too. Rows store groups of content within the email design. An end user needs to drag and drop a row onto the stage before they can add Content tiles. Once the rows are added, they can drag and drop Content tiles onto them.
Users can customize Rows with Row properties. Customizable options include Backgrounds, Borders, Column Structure, and more.
Settings enable end users to apply general customization options to their email designs.
A few of the actions included with the email builder include:
Preview
Send test
Save as Template
The text editor appears when you click on a text-type content on the stage. The options include adding Merge tags, Special links, and more.
POST /v1/{collection}/html HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 35263
{
"page": {
"body": {
"container": {
"style": {
"background-color": "#FFFFFF"
}
},
"content": {
"computedStyle": {
"linkColor": "#FF819C",
"messageBackgroundColor": "transparent",
"messageWidth": "675px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica Neue, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Montserrat', 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif",
"name": "Montserrat",
"url": "https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap"
}
]
},
"description": "BF-ecommerce-template",
"rows": [
{
"columns": [
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "287px"
},
"image": {
"alt": "Image",
"height": "142px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/logo_1.png",
"target": "_self",
"width": "546px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "ca41c638-c8fa-4b88-b4de-db0584002b4d"
},
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": true
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "20px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "b3ad4612-0b4c-48e4-b4c9-b63eb9f4014b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
},
"uuid": "63f745dd-ab3f-49b3-b173-a0ba7fa77732"
},
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "25px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "49740804-c7a9-4cec-b307-9ad3d05eec58"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>ANY DEVICE, ANYWHERE, FAST.</p>",
"style": {
"color": "#ffffff",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "18px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "right"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "8e540cc4-4a11-4469-acf2-34cd3e6b5d56"
},
{
"type": "mailup-bee-newsletter-modules-heading",
"descriptor": {
"heading": {
"title": "h1",
"text": "<span class=\"tinyMce-placeholder\">This is English</span>",
"style": {
"color": "#555555",
"font-size": "23px",
"font-family": "inherit",
"link-color": "#E01253",
"line-height": "120%",
"text-align": "center",
"direction": "ltr",
"font-weight": "700",
"letter-spacing": "0px"
},
"translations": {
"fr-FR": {
"text": "<span class=\"tinyMce-placeholder\">This is french</span>"
},
"it-IT": {
"text": "<span class=\"tinyMce-placeholder\">This is Italian</span>"
}
}
},
"style": {
"width": "100%",
"text-align": "center",
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"mobileStyle": {},
"computedStyle": {
"width": 52,
"height": 42
}
},
"uuid": "122f4b0f-9e7e-475c-ad0a-b56ea67c3537",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "20px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
},
"uuid": "9f69fc4a-f3cc-46aa-be89-625913f374a6"
}
],
"container": {
"style": {
"background-color": "#3f005a",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "two-columns-empty",
"uuid": "9624ba86-b3d4-47ad-962d-f6701f1c61af"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "60px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "cd500e1b-70e3-48f4-9c3b-dfee60b3b6df"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "12px"
},
"html": "<p>INTRODUCING</p>",
"style": {
"color": "#ffffff",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "28px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "ad5fc7a7-b4c5-4db3-bbf9-905d0040649d"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#ffffff",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "75px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
},
"text": "HACKISTER<strong>4</strong>",
"title": "h1"
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "25d452fb-d07d-49e0-bf2b-b26969b89ff0"
},
{
"descriptor": {
"computedStyle": {
"class": "center fixedwidth",
"width": "371.25000000000006px"
},
"image": {
"alt": "rocket",
"height": "256px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://pre-assets.imgdist.com/public/users/Integrators/BeeAppPre/roberto/rocket_1f680.png",
"target": "_self",
"width": "256px"
},
"style": {
"padding-bottom": "20px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "20px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "9a2ae0f8-785c-49fd-a2eb-73e00153e3a9"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "30px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "1fe2d079-351a-4920-bf7c-a56ed7660fca"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "50px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
},
"uuid": "ed93c48c-f593-4c8e-9069-0c5135f4be6f"
}
],
"container": {
"style": {
"background-color": "#fa8072",
"background-image": "url('https://pre-assets.imgdist.com/public/users/Integrators/BeeAppPre/roberto/windows-11-365-purple-abstract-background-4k-wallpaper-uhdpaper.com-551%400%40i.jpg')",
"background-position": "top center",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "973b04b3-19ab-4519-ad9e-b4c99b74068c"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#680080",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "34px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
},
"text": "<span class=\"tinyMce-placeholder\">The <strong>fake</strong> <strong>app</strong> for <br /><strong>real-time</strong> collaboration</span>",
"title": "h1"
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "5f570375-ba13-4cb2-b136-4a1ab89477fb"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "4px"
},
"html": "<p>Aenean eu leo quam. Pellentesque ornare sem</p>\n<p>lacinia quam venenatis vestibulum.</p>\n<p>Donec sed odio dui.</p>",
"style": {
"color": "#555555",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "18px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "ce6062a1-3ba6-437b-b378-cacb1ec2fb0d"
},
{
"descriptor": {
"button": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #800080",
"border-left": "3px solid #800080",
"border-radius": "30px",
"border-right": "3px solid #800080",
"border-top": "3px solid #800080",
"color": "#680080",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "20px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "5px",
"width": "35%"
},
"target": "_self"
},
"computedStyle": {
"height": 56,
"width": 229
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "a2e52ec4-59dd-44e9-a68b-6273a7d9385d"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "10px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "9d131f36-752d-4ebc-8944-51c9873d22b0"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "30px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
},
"uuid": "e065afb1-62dd-45f4-8aca-08a5f719eed1"
}
],
"container": {
"style": {
"background-color": "#eacaf6",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "8656050f-2d7d-4a3e-ac37-0f0504985539"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "30px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "f9890128-2034-43ea-97a8-3cc92737873e"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "15px"
},
"uuid": "0f59cf03-19e2-44a1-80fb-6a8441cf381c"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "fd2b49d3-2668-4d32-a46d-2d5031268ebe"
},
{
"columns": [
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth ",
"width": "103px"
},
"image": {
"alt": "Image",
"height": "120px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/icon-globe.png",
"target": "_self",
"width": "103px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "d7c13f74-1679-460c-86c3-528ec2148f6f"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "23px",
"font-weight": "700",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#ff819c",
"text-align": "center"
},
"text": "Fusce Nullam",
"title": "h1"
},
"style": {
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "20px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "d1a1bb5b-5668-421d-ba55-0d70be81ce85"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#ff819c",
"paragraphSpacing": "16px"
},
"html": "<p>Nullam quis risus eget urna mollis.<br />Sed turpi est quisquam nobis</p>",
"style": {
"color": "#9d9da1",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "494dcda2-890e-43d2-bf22-e5a7008563d8"
},
{
"descriptor": {
"button": {
"href": "https://beefree.io",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #D2687F",
"border-left": "3px solid #D2687F",
"border-radius": "30px",
"border-right": "3px solid #D2687F",
"border-top": "3px solid #D2687F",
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "0px",
"width": "auto"
},
"target": "_self"
},
"computedStyle": {
"height": 38,
"width": 146
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "f204ceb2-f285-4a20-944e-205a6ac62f8a"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "e2b2669a-0185-4565-a4a2-1644c9989d74"
},
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth ",
"width": "110px"
},
"image": {
"alt": "Image",
"height": "110px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/icon-chat.png",
"target": "_self",
"width": "110px"
},
"style": {
"padding-bottom": "10px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "43f99492-43c1-4451-9376-67d4e78d7e4b"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "23px",
"font-weight": "700",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#ff819c",
"text-align": "center"
},
"text": "<span class=\"tinyMce-placeholder\">Lorem Ipsum</span>",
"title": "h1"
},
"style": {
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "20px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "ade54875-7cd5-4bcc-8f97-fa496745949b"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#ff819c",
"paragraphSpacing": "16px"
},
"html": "<p>Nullam quis risus eget urna mollis.<br />Sed turpi est quisquam nobis</p>",
"style": {
"color": "#9d9da1",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "2cd0fdf7-00ce-48e0-9cd0-0946e0a7f280"
},
{
"descriptor": {
"button": {
"href": "https://beefree.io",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #D2687F",
"border-left": "3px solid #D2687F",
"border-radius": "30px",
"border-right": "3px solid #D2687F",
"border-top": "3px solid #D2687F",
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "0px",
"width": "auto"
},
"target": "_self"
},
"computedStyle": {
"height": 38,
"width": 146
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "c27985f5-a92d-4c0c-9f8d-8e3bedf71a8b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "f3b0abb4-6068-419b-bfed-60727570c366"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "two-columns-empty",
"uuid": "3bb64451-93bd-44e8-ab28-62ee2d09013d"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px solid #F0F0F0",
"height": "0px",
"width": "100%"
}
},
"style": {
"padding-bottom": "20px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "20px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "d5d46fc7-aeca-49ff-98e8-6453b7b076d6"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "db0f8784-ade7-42e0-bb2f-9273190070ff"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "e936284c-d052-43da-8a13-806b7b17289b"
},
{
"columns": [
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth ",
"width": "120px"
},
"image": {
"alt": "Image",
"height": "120px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/icon-heart.png",
"target": "_self",
"width": "120px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "2f90053a-b4fd-4215-9684-0acded4a61f8"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "23px",
"font-weight": "700",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#ff819c",
"text-align": "center"
},
"text": "<strong>Quibus numquam</strong>",
"title": "h1"
},
"style": {
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "20px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "011a8c2b-02cf-4b5f-9285-dd71e8f1c93d"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#ff819c",
"paragraphSpacing": "16px"
},
"html": "<p>Nullam quis risus eget urna mollis.<br />Sed turpi est quisquam nobis</p>",
"style": {
"color": "#9d9da1",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "90cae6a9-b1a8-4b89-9447-ad7a54dff03e"
},
{
"descriptor": {
"button": {
"href": "https://beefree.io",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #D2687F",
"border-left": "3px solid #D2687F",
"border-radius": "30px",
"border-right": "3px solid #D2687F",
"border-top": "3px solid #D2687F",
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "0px",
"width": "auto"
},
"target": "_self"
},
"computedStyle": {
"height": 38,
"width": 146
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "ca616f2e-7d96-43a6-a1cb-7642f4d27549"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "e2b2669a-0185-4565-a4a2-1644c9989d74"
},
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center autowidth ",
"width": "115px"
},
"image": {
"alt": "Image",
"height": "120px",
"href": "https://beefree.io",
"prefix": "",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/icon-bulb.png",
"target": "_self",
"width": "115px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "49fbfb1d-66eb-416b-a832-2dde397b2556"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "23px",
"font-weight": "700",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#ff819c",
"text-align": "center"
},
"text": "<strong>Dolor sit amet</strong>",
"title": "h1"
},
"style": {
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "20px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "049de2bd-a524-4313-9c2e-b3afac36eb0d"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#ff819c",
"paragraphSpacing": "16px"
},
"html": "<p>Nullam quis risus eget urna mollis.<br />Sed turpi est quisquam nobis</p>",
"style": {
"color": "#9d9da1",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "9720d206-2560-48ae-91cd-102739610088"
},
{
"descriptor": {
"button": {
"href": "https://beefree.io",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #D2687F",
"border-left": "3px solid #D2687F",
"border-radius": "30px",
"border-right": "3px solid #D2687F",
"border-top": "3px solid #D2687F",
"color": "#d2687f",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "0px",
"width": "auto"
},
"target": "_self"
},
"computedStyle": {
"height": 38,
"width": 146
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "4b3fd148-e154-414c-9b06-9d8bf1856a52"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "f3b0abb4-6068-419b-bfed-60727570c366"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "two-columns-empty",
"uuid": "fd36cf36-dbb3-4834-9464-6a6a8f27907b"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px solid #F0F0F0",
"height": "0px",
"width": "100%"
}
},
"style": {
"padding-bottom": "30px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "445a1956-deac-4e2e-a48d-2a458c83993d"
},
{
"descriptor": {
"computedStyle": {
"height": 42,
"width": 52
},
"heading": {
"style": {
"color": "#606060",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "38px",
"font-weight": "700",
"letter-spacing": "0px",
"line-height": "120%",
"link-color": "#E01253",
"text-align": "center"
},
"text": "<strong>Fusce Nullam Consectetur</strong>",
"title": "h1"
},
"style": {
"padding-bottom": "15px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "970cbd50-f921-4166-bf17-766251359e91"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>Vestibulum id ligula porta felis euismod semper. Nulla vitae elit.</p>",
"style": {
"color": "#828282",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "aa354280-903e-4ca5-8374-19ccb07b6277"
},
{
"descriptor": {
"button": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"\" data-mce-style=\"\"><p style=\"word-break:break-word;\" data-mce-style=\"word-break:break-word;\"><span style=\"\" data-mce-style=\"\"><span style=\"\" data-mce-style=\"\">SHOW MORE</span></span></p></div>",
"style": {
"background-color": "transparent",
"border-bottom": "3px solid #800080",
"border-left": "3px solid #800080",
"border-radius": "30px",
"border-right": "3px solid #800080",
"border-top": "3px solid #800080",
"color": "#680080",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "20px",
"font-weight": "700",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "5px",
"width": "35%"
},
"target": "_self"
},
"computedStyle": {
"height": 56,
"width": 229
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "051b8a87-1989-4a20-ade6-42fc0dcadf23"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"spacer": {
"style": {
"height": "55px"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-spacer",
"uuid": "5aeb2aff-b6dc-4f20-9518-25e64a374653"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "2595bc5d-0dde-4b9e-9eca-d969700fd3df"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "6fd5ca61-d6a8-49f6-8463-82a5d4a342a5"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"height": 57,
"iconsDefaultWidth": 32,
"padding": "0 5px 5px 0",
"width": 151
},
"iconsList": {
"icons": [
{
"image": {
"alt": "Facebook",
"href": "https://www.facebook.com/",
"prefix": "https://www.facebook.com/",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-outline-circle-color/facebook.png",
"target": "_self",
"title": "Facebook"
},
"name": "facebook",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Twitter",
"href": "http://twitter.com/",
"prefix": "http://twitter.com/",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-outline-circle-color/twitter.png",
"target": "_self",
"title": "Twitter"
},
"name": "twitter",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Instagram",
"href": "https://instagram.com/",
"prefix": "https://instagram.com/",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-outline-circle-color/[email protected]",
"target": "_self",
"title": "Instagram"
},
"name": "instagram",
"text": "",
"type": "follow"
}
]
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-social",
"uuid": "a901f3ec-f8f0-4a59-9260-2ace7ef36ff5"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#ff819c",
"paragraphSpacing": "16px"
},
"html": "<p>Your Company © All rights reserved</p>",
"style": {
"color": "#959595",
"direction": "ltr",
"font-family": "Montserrat, Arial, Helvetica, sans-serif",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "center"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "543e160e-c86e-4863-abbe-ec17524260fc"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "30px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
},
"uuid": "d38114b4-b17f-41c7-86cc-f016916e09c6"
}
],
"container": {
"style": {
"background-color": "#f5e4ff",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "fb49b3e5-5808-4945-9244-6211badb95bb"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": "BF-ecommerce-template"
},
"comments": {},
"beautifyHtmlEnabled": true
}
<html>Hello World!</html>
POST /v1/{collection}/plain-text HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 18838
{
"page": {
"body": {
"container": {
"style": {
"background-color": "#fff",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"background-size": "auto"
}
},
"content": {
"computedStyle": {
"linkColor": "#8a3b8f",
"messageBackgroundColor": "transparent",
"messageWidth": "650px"
},
"style": {
"color": "#000000",
"font-family": "Lato, Tahoma, Verdana, Segoe, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Lato', Tahoma, Verdana, Segoe, sans-serif",
"name": "Lato",
"url": "https://fonts.googleapis.com/css?family=Lato"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "10px",
"width": "100%"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "b89c3d25-dbec-439a-8ad1-4939a28678e9"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
},
"uuid": "3bd72010-5175-4326-b848-8beacea852d6"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:49:32.875165Z",
"dateModified": "2022-01-20T09:49:32.875165Z",
"description": "",
"idParent": null,
"name": "Pre header purple row",
"slug": "pre-header-purple-row",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/8b99691b-8e39-47a7-8773-4540cd7ff113_small.jpg",
"uuid": "8b99691b-8e39-47a7-8773-4540cd7ff113"
},
"synced": false,
"type": "one-column-empty",
"uuid": "7fa3e6c4-ac4f-421f-b9eb-db1b9f629fb3"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "162.5px"
},
"image": {
"alt": "BEE Pro Logo",
"height": "109px",
"href": "https://beefree.io/",
"percWidth": 25,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/BEEPro_logo_2.png",
"target": "_self",
"width": "291px"
},
"style": {
"padding-bottom": "40px",
"padding-left": "20px",
"padding-right": "20px",
"padding-top": "20px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "cc54124d-97bd-44e0-b15e-710a577840ec"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "20px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "2cd36842-fbe8-4f43-9688-ff6c964aaa89"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"paragraph": {
"computedStyle": {
"linkColor": "#0068a5",
"paragraphSpacing": "16px"
},
"html": "<p>Hi 🙂</p>\n<p><strong>Would you be interested to participate in a user research project with us?</strong></p>\n<p>The research will consist of a video call. It usually takes 30 to 45 minutes maximum, but we schedule 1 hour in case we need more time. We'll be asking questions about you, your team, and your email/page creation workflow. The idea is for us to understand how BEE Pro fits in your work day.</p>\n<p><strong>Sounds good?</strong> Pick a time slot at your convenience using <a href=\"https://calendly.com/beepro-product-team/beepro-interview?month=2022-06\" target=\"_blank\" rel=\"noopener\" style=\"text-decoration: underline;\">this link ↗</a></p>\n<p>Look forward to hearing back from you.</p>\n<p>Best,</p>\n<p>Dalila from the Product Team 💜</p>\n<p>P.S. Probably your colleagues that use BEE Pro have received this email too. If you'd like you can add one guest to the booking link and participate together, or you can join us alone. We would love to talk to you in any case. </p>",
"style": {
"color": "#000000",
"direction": "ltr",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "120%",
"text-align": "left"
},
"translations": {
"de-DE": {
"html": "<p>Hallo 🙂<br /><br />Is het interessant om deel te nemen aan een onderzoek naar nieuwe gebruikersonderzoeken?<br /><br />Het onderzoek bestaat uit een videofilm. Wacht tussen 30 en 45 minuten als het maximum, maar het programma duurt 1 uur voordat u meer tijd nodig heeft. De haremos worden nu gebruikt, uw uitrusting en uw vloeiende creatie van pagina's/correos elektronische. Het idee is dat BEE Pro op zijn werk werkt.<br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br />Groot,<br /><br />Dalila del equipo de producto 💜<br /><br /><br />PD Waarschijnlijk is uw partner die BEE Pro gebruikt, deze recibido is elektrisch correct. Als je dit hebt gedaan, kun je een uitnodiging voor het reserveren en de deelname aan de wedstrijd verzamelen, of je kunt een nieuwe solo spelen. Geen enkele gebeurtenis wordt in een ander geval verwisseld.</p>"
},
"es-ES": {
"html": "<p>Hola 🙂<br /><br />¿Estaría interesado en participar en un proyecto de investigación de usuarios con nosotros?<br /><br />La investigación consistirá en una videollamada. Suele tardar entre 30 y 45 minutos como máximo, pero programamos 1 hora por si necesitamos más tiempo. Le haremos preguntas sobre usted, su equipo y su flujo de trabajo de creación de páginas/correos electrónicos. La idea es que entendamos cómo encaja BEE Pro en su jornada laboral.<br /><br /><br />¿Suena bien? Elija un horario de su conveniencia usando este enlace ↗<br />Esperamos tener noticias suyas.<br /><br /><br />Mejor,<br /><br />Dalila del equipo de producto 💜<br /><br /><br /><br />PD Probablemente tus compañeros que utilizan BEE Pro también hayan recibido este correo electrónico. Si lo desea, puede agregar un invitado al enlace de reserva y participar juntos, o puede unirse a nosotros solo. Nos encantaría hablar con usted en cualquier caso.</p>"
}
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "0456f2de-7125-475c-b016-41f77b3fda47"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "5px"
},
"uuid": "61614a04-eb36-4d98-b28e-c6c9e048877d"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2022-01-20T09:51:57.896884Z",
"dateModified": "2022-01-20T09:51:57.896884Z",
"description": "",
"idParent": null,
"name": "body with: logo + pre title + title + subtitle + body",
"slug": "body-with-logo-pre-title-title-subtitle-body",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/35d02430-32b2-41d6-a115-68d7bb476d64_small.jpg",
"uuid": "35d02430-32b2-41d6-a115-68d7bb476d64"
},
"synced": false,
"type": "two-columns-empty",
"uuid": "f57920be-d9e4-41c0-a009-eb85fd2a8034"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"align": "center"
},
"divider": {
"style": {
"border-top": "1px dotted #CCCCCC",
"width": "100%"
}
},
"style": {
"padding-bottom": "30px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "15px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "ab4460e6-1206-45c1-ba56-9f6d6409508e"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "6ac459ef-5e34-468a-b064-07ea57e1e37c"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 625122,
"dateCreated": "2021-06-29T08:19:25.800829Z",
"dateModified": "2021-06-29T08:19:27.572522Z",
"description": "",
"idParent": null,
"name": "Footer Line",
"slug": "footer-line",
"uuid": "77127825-a508-4127-9155-b5161f9e1703"
},
"synced": false,
"type": "row-1-columns-12",
"uuid": "b759c29c-fb9e-4b1a-add9-a464eeb568f5"
},
{
"columns": [
{
"grid-columns": 3,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"class": "left fixedwidth",
"width": "130px"
},
"image": {
"alt": "Elena Loatelli & Dalila Bonomi",
"height": "263px",
"href": "",
"percWidth": 80,
"prefix": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_655907/editor_images/dalila.png",
"target": "_self",
"width": "263px"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "682c9273-3090-43fb-9acc-a2e2cda857b7"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "a434440b-92d8-4841-90cc-2ab49b1afc14"
},
{
"grid-columns": 9,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "10px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:14px;line-height:16px;font-family:inherit;\" data-mce-style=\"font-size:14px;line-height:16px;font-family:inherit;\"><p style=\"font-size:14px;line-height:16px;word-break:break-word;\" data-mce-style=\"font-size:14px;line-height:16px;word-break:break-word;\"><strong><span style=\"font-size:16px;line-height:19px;\" data-mce-style=\"font-size:16px;line-height:19px;\">DALILA BONOMI</span></strong></p></div>",
"style": {
"color": "#8a3b8f",
"font-family": "inherit",
"line-height": "120%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "b37a5a73-5f40-4e2d-8d7b-6a117aa686eb"
},
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false
},
"style": {
"padding-bottom": "5px",
"padding-left": "15px",
"padding-right": "0px",
"padding-top": "10px"
},
"text": {
"computedStyle": {
"linkColor": "#8a3b8f"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-size:12px;line-height:21px;font-family:inherit;\" data-mce-style=\"font-size:12px;line-height:21px;font-family:inherit;\"><p style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\" data-mce-style=\"font-size:14px;line-height:25px;word-break:break-word;text-align:left;\"><strong><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">BEE | The email & page builder for everyone.</span></strong></p><p style=\"line-height:21px;word-break:break-word;\" data-mce-style=\"line-height:21px;word-break:break-word;\"><span style=\"font-size:16px;line-height:28px;\" data-mce-style=\"font-size:16px;line-height:28px;\">Design Researcher</span></p></div>",
"style": {
"color": "#454562",
"font-family": "inherit",
"line-height": "180%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text",
"uuid": "a916773b-42f4-4efc-af64-3b2a9f801015"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "bc078241-a4ab-4a26-b28b-b7aba3180d3a"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-31T09:21:17.612857Z",
"dateModified": "2022-01-31T09:21:20.633639Z",
"description": "",
"idParent": null,
"name": "Dalila single sign",
"slug": "dalila-single-sign",
"uuid": "37bceb9d-b1c9-4724-b5ad-31645653d1c2"
},
"synced": false,
"type": "two-columns-3-9-empty",
"uuid": "3218627f-a68a-4f5d-b3e9-adfa19bb82ec"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": false
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "50px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider",
"uuid": "5a247632-900c-4a38-8bf1-2307938d9bb5"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "ecfdb53f-a7a0-40dd-9fd9-67d7e2677832"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "feb66cab-ac4a-4ec2-b5d6-657eeabd1039"
},
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"align": "left",
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "16px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "6px",
"padding-top": "5px"
},
"itemsSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "Designed with BEE",
"height": "325px",
"href": "https://beefree.io/",
"id": "1879a39d-9303-43e5-8458-990ac7b0a429",
"image": "https://d15k2d11r6t6rl.cloudfront.net/public/users/Integrators/BeeProAgency/53601_510656/Signature/bee_w.png",
"target": "_blank",
"text": "Designed with BEE",
"textPosition": "right",
"title": "Designed with BEE",
"width": "325px"
}
]
},
"style": {
"color": "#ffffff",
"font-family": "inherit",
"font-size": "15px",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "35f3f7a2-37aa-4471-bd26-ce2b51e6e39b"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "8d6cbc30-0a36-4037-ae02-827d71033fee"
}
],
"container": {
"style": {
"background-color": "#8a3b8f",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "650px"
}
},
"empty": false,
"locked": false,
"metadata": {
"category": 706433,
"dateCreated": "2022-01-20T09:44:21.371097Z",
"dateModified": "2022-01-20T11:01:58.708887Z",
"description": "",
"idParent": null,
"name": "Designed with BEE",
"slug": "designed-with-bee",
"thumb_large": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_large.jpg",
"thumb_medium": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_medium.jpg",
"thumb_small": "https://pro-bee-beepro-thumbnails.s3.amazonaws.com/templates/saved-rows/53601/655907/727e515b-7455-4661-8e85-22b9f7178d3f_small.jpg",
"uuid": "727e515b-7455-4661-8e85-22b9f7178d3f"
},
"synced": false,
"type": "one-column-empty",
"uuid": "cc615b28-4773-45ef-b0bf-4ef7ef89b1bf"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"language": "it-IT"
}
Hello world! Welcome to [Beefree SDK](https://developers.beefree.io/)!
POST /v1/{collection}/pdf HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 189
{
"page_size": "Full",
"page_orientation": "landscape",
"html": "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body><div style='width:900px; margin: 30px;'>test</div></body></html>"
}
{
"message": "Success"
}
A form is defined through the structure
object, which includes its main properties.
This is the object that the host application passes to Beefree SDK, and it includes fields
, layout,
and attributes
along with a title
and a description
string values that you can use. The appearance of the form, in terms of styling of labels / fields / buttons (spacing, colors, etc…) is handled directly in the application and is saved in the design’s JSON file. Therefore, the same form can be used in different designs, and have message-specific styles.
To take a look at real-world examples and samples, you can head to our dedicated GitHub page.
Let’s now examine the anatomy of a Beefree SDK form structure.
{
"structure": {
"attributes": {},
"fields": {},
"layout": [],
"title": "Form title",
"description": "Form description"
}
}
This object contains the general form attributes as strings: all of them are standard HTML5 attributes.
action
string
method
string
target
string
accept-charset
string
autocomplete
string
enctype
string
novalidate
boolean
dir
string
An object that lists all the form fields included in the form with its relative properties. The order in which they appear only matters if you pass a single form to an application. If you want to use the content dialog to feed forms in the builder, the order is not relevant and you can set the form layout in the layout array.
Beefree SDK supports the vast majority of standard HTML5 form
fields. A few of them (such as color
, datetime
, datalist
) have mixed browser support, so please make sure to check browser compatibility before using them.
To see them in action, you can find a few examples on our dedicated GitHub page. Head over to allowed form fields if you need the full list of allowed field types, along with the available attributes and options for each of them.
If you want to use a single form, you can use the optional canBeRemovedFromLayout
and removeFromLayout
attributes to determine (respectively) if that specific field can be removed from the layout by the user, and if it should appear in the stage when the form is dragged in.
canBeRemovedFromLayout
all fields
boolean
true
This attribute indicates that a field can be toggled off by the user. If unspecified, it will be applied as true, allowing the user to switch it on or off in the builder UI.
It’s a best practice to add canBeRemovedFromLayout: false
to mandatory fields (e.g., the email address field in a sign-up form) so that they can’t be excluded in the HTML form.
removeFromLayout
all fields
boolean
false
This attribute indicates that a field is toggled off by default when the form is loaded. This behavior is particularly useful to simplify the user experience when you implement forms in the builder through a default form in the configuration parameters.
If you want to leverage the full power of Beefree SDK forms and use a content dialog to feed the form to the editor’s stage, the layout
array will determine how the fields will appear to the user.
Each layout
element is an array itself and represents a single line of fields. This allows different layout dispositions, including multi-column.
Probably the best way to represent this is with an example:
The form title is a string value. It is not displayed to the user while working in the editor but provides extra information that can be used later for troubleshooting. Likewise, description as a string value that is not displayed to the user while working in the editor, but provides extra information that can be used later for troubleshooting or internal reference.
reCAPTCHA is a free service from Google that helps protect websites from spam and abuse. To learn more about reCAPTCHA, visit the official website or Google technical documentation site.
To embed Google ReCaptcha in a Form you need a Google API key for ReCaptcha, the key has to be enabled for a specific website URL or domain; this is crucial because otherwise the script will load but will fail its validation, returning API key errors.
Here’s what’s needed in the submit action when passing a form configuration:
"class": "g-recaptcha"
"data-action": "submit"
"data-sitekey": "___YOUR_RECAPTCHA_API_KEY___"
"data-callback": "onSubmit" (this can be optional, check reCaptcha docs)
In addition, you have to add an HTML block that imports the reCaptcha library inside the template that encapsulates the form:
<script src="https://www.recaptcha.net/recaptcha/api.js" async defer></script>
Here’s a sample JSON config for the submit button:
"submit": {
"attributes": {
"class": "g-recaptcha",
"data-action": "submit",
"data-callback": "onSubmit",
"data-sitekey": "___YOUR_RECAPTCHA_API_KEY___",
"value": "Login"
},
"label": " ",
"type": "submit"
}
Ensure you keep the following in mind:
Make sure HTML sanitize is OFF (this is the default value).
Remember that the reCaptcha UI elements will be visible neither in the Beefree SDK work area nor in the Preview, but they will be integrated when the page will be published. Furthermore, the page has to be hosted on the domain that was enabled on the Google Developers Console when setting the reCaptcha.
Explore how to implement customization options for a form's layout.
This document outlines how you can customize a form’s layout, and discusses the available layout customization options. These options allow you to adjust various elements of forms to improve your end's user experience creating them. Form layout options ensure your application's end users have more tools to create a more effective presentation of their forms.
Key form layout customization options include:
Multiple choice and radio button orientation: You can adjust the orientation of multiple choice and radio button elements, choosing between horizontal or vertical alignment to suit your design preferences or space constraints.
New layout presets: Three layout presets are available: horizontal, vertical, and grid. These presets define the overall structure of the form, allowing you to easily apply a consistent layout across fields.
The form field width includes the following customization option:
Form field width property: A new boolean property, fullWidth
, enables you to manage form field widths. When set to true
, the field will expand to 100% width. When set to false
, it the field width is set to 50%.
The following video provides a visual representation of these customization options and how they function within the user interface.
Prior to getting started, ensure you have the following:
Page builder or Popup builder application within your Dev Console
For this implementation, there is a field called orientation
in the JSON at the field object level. This field controls the layout orientation for multiple-choice and single-choice fields, which include radio buttons and checkboxes. The orientation
field accepts the following two values:
horizontal
vertical
The following JSON display an example of the updated structure for a radio button field with the orientation
field included:
{
"structure": {
"fields": {
"gender": {
"type": "radio",
"label": "Gender",
"orientation": "vertical", // Newly added field for layout orientation
"attributes": {},
"options": [
{
"type": "option",
"value": "M",
"label": "Male"
},
{
"type": "option",
"value": "F",
"label": "Female"
},
{
"type": "option",
"value": "-",
"label": "Not telling"
}
]
}
},
"layout": [
[
"gender"
]
]
},
"attributes": {},
"style": {
"labels": {},
"fields": {},
"buttons": {}
}
}
Take the following steps to configure the orientation
field:
Locate the form field object in the JSON: Find the field you want to configure, such as a radio button or checkbox field. This will be under the "fields"
key within the JSON structure.
Add the orientation
property: Inside the field object, add a new property called orientation
.
Set the value: Assign the orientation
field a value of either "horizontal"
or "vertical"
, depending on how you want the options displayed in the form.
"orientation": "vertical"
Save the changes: After making the necessary updates to the JSON structure, ensure that the changes are saved.
Test the form: Once the JSON is updated, test the form to ensure that the options are displayed in the correct orientation. If the field is missing, check if the default horizontal orientation is applied.
These steps will allow you to effectively control the layout orientation of multiple-choice fields in your forms.
The layout of the form fields can be controlled using a new layoutPreset
field. This field is located in the structure
object of the JSON and supports three possible values:
vertical
horizontal
grid
JSON Structure Example
Here is an example of a form JSON structure utilizing layout presets:
{
"structure": {
"layoutPreset": "grid", // New field to define form layout
"fields": {
"email": {
"type": "email",
"label": "Email Address",
"fullWidth": true, // Only applicable for 'grid' preset
"attributes": {}
}
}
},
"attributes": {},
"style": {
"labels": {},
"fields": {},
"buttons": {}
}
}
The following list shows the available options for layout presets.
Vertical: Fields will be stacked vertically, one on top of another.
Horizontal: Fields will be aligned horizontally, side by side.
Grid: Fields will be organized into a grid layout, allowing for more complex positioning.
Take the following steps to configure the layoutPreset
field:
Locate the structure
object in the JSON: Find the structure
key within the form’s JSON definition where the fields and layout are defined.
Add or modify the layoutPreset
field: Inside the structure
object, add a new property called layoutPreset
.
Set the desired value: Assign the layoutPreset
field one of the following values to control the layout of the form:
"vertical"
: Stack fields vertically.
"horizontal"
: Align fields horizontally.
"grid"
: Organize fields in a grid format.
Example:
"layoutPreset": "horizontal"
Configure field properties (if applicable): If you are using the grid
layout, you may also need to adjust other field properties like fullWidth
to control the width of individual fields. For example, set "fullWidth": true
to make a field span the full width of the grid column.
Save and test the form: After setting the layoutPreset
, save the updated JSON structure and test the form layout to ensure the fields are displayed according to the selected preset.
By following these steps, you can easily configure and control the layout of your form fields using the new layoutPreset
field.
fullWidth
FieldA new boolean field, fullWidth
, has been introduced within each form field object. This field is applicable only when the layout preset is set to grid
. If a layout other than grid
is used, the fullWidth
field will be ignored or removed from the JSON structure.
In a grid layout, setting fullWidth
to true
will cause the form field to span the entire width of the grid column, while setting it to false
will restrict the field's width to a smaller portion of the grid.
fullWidth
Field in JSONTake the following steps to configure the fullWidth
field:
Ensure the layout preset is set to grid
: The fullWidth
field only functions when the form’s layout preset is set to "grid"
. Verify that the "layoutPreset"
field in the JSON is set to "grid"
.
Locate the desired form field: In the JSON structure, find the field you want to configure, such as an email or text field.
Add the fullWidth
field: Inside the form field object, add a new property called fullWidth
.
Set the boolean value:
Set fullWidth
to true
to make the form field span the entire width of the grid column.
Set fullWidth
to false
if you want the form field to occupy half or a portion of the grid column.
Example:
"fullWidth": true
Save the changes: After adding or modifying the fullWidth
field, save the updated JSON structure.
Test the form in grid layout: Ensure that the form’s layout is set to grid
and that the field's width behaves as expected.
By following these steps, you can effectively configure the fullWidth
property to control the width of form fields in grid layouts.
Layout Widget: End users can change the layout preset using a layout widget available in the form sidebar.
Field Width Widget: When the form is using the grid
preset, the fullWidth
field can be modified by users through a field width widget available in the Manage Fields section or the Edit Form Modal.
The Submit field will always have fullWidth
set to true
, and the corresponding widget will be disabled to ensure it spans the full width. For more details on the end user experience, reference the Form Layout Customization end user documentation.
This page lists and describes the Convert category of endpoints within the Content Services API. It also includes interactive testing environments for each endpoint in this category.
The Conversion Collection provides you with endpoints that enable you to convert templates from one format to another. With the Email to Page endpoint, you can easily convert your email JSON templates into page JSON. The Page to Email endpoint lets you turn your page JSON templates into email-ready JSON, with the option to disable the HTML sanitizer if needed. The Simple to Full JSON endpoint enables you to convert Simple Schema templates into full Beefree JSON templates that can be loaded in the builder.
The Email to Page endpoint converts a JSON template created for email into a JSON template optimized for web pages. During this conversion, the following adjustments are applied:
Remove AMP Carousel Any AMP carousels included in the email template are removed, as these are not supported in the page format.
Expand Content Area Width The content width is expanded to 900px to fit the web page format, removing the width constraints typically applied to emails.
Target Attributes Target attributes will not be processed. Remove all link target attributes or set them to "Open a new page." Links will not be modified during the conversion.
Remove Subject and Preheader Email-specific metadata, such as the subject line and preheader text, is removed since these elements are not relevant in the page format.
Retain Comments and Secondary Language Comments and secondary language data in the email template are preserved in the conversion process.
The Page to Email endpoint transforms a JSON template designed for a web page into a JSON template optimized for email. During this conversion process, the following adjustments are made:
Remove Video Row Backgrounds Video backgrounds applied to page rows are removed because email formats do not support video backgrounds.
Replace Embedded Videos with Thumbnails Embedded videos are replaced with thumbnail images. This ensures recipients can preview the content visually without the compatibility issues of embedded videos. Note: Hosted videos will not be converted.
Remove Form Blocks Any form blocks present in the page template are removed.
Adjust Design Content Area Width If the page width exceeds the maximum width supported by the email builder (900px), it is resized to fit within email constraints.
Update Link Target Attributes Target attributes will not be processed. Remove all link target attributes. Links will not be modified during the conversion.
Sanitize Code The endpoint sanitizes the code to ensure compatibility with email standards. When the sanitizer is disabled, the payload looks like this:
{
"disableHtmlSanitizer": true,
"template": { "page": ... }
}
Handle Multi-Column Layouts The email builder supports up to 12 columns, which is compatible with the page builder's column configurations.
This section discusses what the /simple-to-full-json
endpoint is and how you can use it for AI-driven designs. Beefree SDK template JSON is long and includes many properties. For this reason, it does not provide the best structure for training AI models in workflows that include AI-driven design creation. Beefree SDK's Simple schema is a lightweight alternative that is optimized for training AI models. Simple schema, which is several lines shorter than Beefree SDK's template JSON, is a great solution for AI-generated schemas. This endpoint accepts Simple schema as the body of the POST
request, and returns the full Beefree SDK template JSON, which can then be loaded in the Beefree SDK editor for an end user to view and edit accordingly. There are many creative ways to use and implement this endpoint, because it provides a pathway to programmatically creating full Beefree SDK-compatible templates completely outside of the Beefree SDK builder.
The API call accepts a template
object, which is required to successfully perform the /simple-to-full-json
API call. The following table describes this required object.
template
JSON
Yes
A Beefree SDK template in simple JSON format ().
The following code snippet shows the template object as the body of the POST
request.
{
“template”:{...}
}
The following table lists and describes both required and optional object parameters nested within the mandatory template
object. This template
object is the body of the POST
request for the API call.
type
String
✅ Yes
Specifies the template type. Possible values include: email
, page
, popup
.
rows
Array
✅ Yes
Array containing at least one row. Reference the .
settings
Object
❌ No
Configuration settings. Reference the section for more information.
metadata
Object
❌ No
Metadata information. Reference the for more information.
The following code snippet shows the optional settings
object nested within the template
object in the body of the POST
request.
{
“template”:{
"settings":{...},
...
}
}
The following table lists and describes optional object parameters nested within the settings
object. The settings object is nested within the mandatory template
object.
linkColor
String
❌ No
The default color of the links within the template.
backgroundColor
String
❌ No
The background color of the template.
contentAreaBackgroundColor
String
❌ No
The background color of the content area.
width
integer
❌ No
Important: The width of the template must be between 320 and 1440 pixels.
The following code snippet shows the optional metadata
object nested within the template
object in the body of the POST
request.
{
“template”:{
"metadata":{...},
...
}
}
The following table lists and describes optional object parameters nested within the metadata
object. The metadata
object is nested within the mandatory template
object.
lang
string
❌ No
The language code of the template (for example, "en"
, "fr"
).
title
string
❌ No
The title of the template.
description
string
❌ No
A short description of the template.
subject
string
❌ No
The subject line of the email (if applicable).
preheader
string
❌ No
The preheader text for the email (if applicable).
This page lists and describes the Brand Style category of endpoints within the Content Services API. It also includes interactive testing environments for each endpoint in this category.
The Brand Style endpoints enables you to manage and modify the style of email, pages, and popup templates. While the Content Defaults feature enables you to set default styles for new content elements like headings, paragraphs, and buttons, the Brand Style Management endpoint takes it a step further. It allows you to make template-wide design changes to existing templates quickly and easily, ensuring that all modules adhere to the broader design system or brand guidelines. In this article, we'll explore what this Content Services API (CSAPI) Brand Style Management endpoint is, its benefits, how to get started with it, and how it differs from Content Defaults.
To apply a style globally, take the following steps:
Manage Brand Styles: Begin by defining your brand's styles within the schema. The Brand Style Management endpoint schema mirrors the . This enables you to easily reuse the styles you’ve already defined in your application’s frontend. Use the same schema to specify colors, fonts, and any other design elements you want to apply uniformly.
Prepare the Template: Ensure you have the JSON template ready, which is the foundation for your branding modifications.
API Call: Make an API call to the CSAPI Brand Style Management endpoint, providing the schema with your defined brand styles and the JSON template to be updated.
API Processing: The API will take care of processing your request. It will automatically merge the specified brand styles into the template, applying the desired changes globally.
Receive Modified Template: After the API processes your request, it will return the modified JSON template with the updated styles. This template is now ready to be used in your marketing campaigns with the consistent branding you've defined.
/template/brand
or /row/brand
HTTP Method: POST
Description: Apply brand styles to a template or row, ensuring a consistent visual identity.
Request Parameters:
styles
(JSON): The brand styles to apply to the template.
template
(JSON): The JSON template to be updated with the brand styles.
HTML
Return the template with or without HTML.
The following section displays an example request. Note that the syntax for the CSAPI Brand Style Management endpoint is similar to the syntax for .
Example Request:
You can define multiple classes of buttons, images, and rows by passing an array of styles targeting design elements by their class names. To provide multiple styles, use the className
property to define as many styles as you like. Before defining the className
within the array, ensure you define the className
within the template using the .
The following examples displays a button array.
Response Format:
200 OK: The request was successful, and the modified template was returned.
400 Bad Request: There was an issue with the request parameters.
401 Unauthorized: The API key is invalid or missing.
500 Internal Server Error: An unexpected server error occurred.
Example Response:
This section discusses the request formats for the different parameters.
The styles parameter in the request should follow this JSON format:
Each block style can include attributes such as colors, fonts, borders, and more, depending on your brand's requirements. For additional code samples of each content block type and its respective style customization options, reference the .
Note: The mobileStyles
and hoverStyles
properties are not supported by the Brand Style Management API.
The template parameter should contain your template's JSON structure. Ensure that the JSON structure aligns with the template you intend to update.
Both the (frontend) and Brand Style Management endpoint (backend) include the table content block.
The following code shows an example of how to configure the style for headers within the table content block:
The Brand Style Management endpoint schema is designed to be user-friendly and intuitive. You can use the same you used to style your application’s frontend with the Brand Style Management endpoint.
For example:
The CSAPI Brand Style Management endpoint will take these styles and merge them with your design template, eliminating the need for complex manual editing.
While both Content Defaults and the Brand Style Management endpoint aim to streamline the design process, they serve different purposes:
Can be a part of the .
Set default styles for specific content types.
Useful for quickly creating new templates with consistent styling.
CSAPI endpoint that enables the development of a user interface that empowers end users to make style changes with ease and speed.
Modify the style of existing templates.
Suitable for users who need to make template-wide design changes or maintain brand consistency on existing templates.
The Brand Style API includes a 422
status code (unprocessable entity). This status code is returned when an API call is successful, but the brand style defined in the body of the API call does not apply to the template specified. For example, if the brand style defined in the body of the API call applies to buttons, and there are no buttons within the specified template, no styles will be applied. In this scenario, the final result of the API call is that no styles were applied to the template because there were none applicable. Be sure to handle this specific case when implementing the API.
POST /v1/{collection}/merge/index HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 4204
{
"source": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#FFFFFF"
}
},
"content": {
"computedStyle": {
"linkColor": "#FF819C",
"messageBackgroundColor": "transparent",
"messageWidth": "675px"
},
"style": {
"color": "#000000",
"font-family": "Arial, 'Helvetica Neue', Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"name": "Montserrat",
"fontFamily": "'Montserrat', 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif",
"url": "https://fonts.googleapis.com/css?family=Montserrat"
}
]
},
"description": "BF-ecommerce-template",
"rows": [
{
"metadata": {
"name": "demo3",
"guid": "test3"
},
"columns": [
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"class": "center fixedwidth",
"width": 338
},
"image": {
"alt": "Image",
"href": "https://beefree.io",
"src": "https://d1oco4z2z1fhwp.cloudfront.net/templates/default/113/logo_1.png"
},
"style": {
"padding-bottom": "0px",
"padding-left": "15px",
"padding-right": "15px",
"padding-top": "5px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image"
},
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": true
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "20px",
"width": "100%"
}
},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
}
},
{
"grid-columns": 6,
"modules": [
{
"descriptor": {
"computedStyle": {
"align": "center",
"hideContentOnMobile": true
},
"divider": {
"style": {
"border-top": "0px solid transparent",
"height": "32px",
"width": "100%"
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-divider"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnMobile": true
},
"style": {
"padding-bottom": "15px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "0px"
},
"text": {
"computedStyle": {
"linkColor": "#FF819C"
},
"html": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: Montserrat, "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif; font-size: 12px; line-height: 18px;\" data-mce-style=\"font-family: Montserrat, "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif; font-size: 12px; line-height: 18px;\">\n<div style=\"line-height: 18px; font-size: 12px; text-align: center;\" data-mce-style=\"line-height: 18px; font-size: 12px; text-align: center;\"><span style=\"font-size: 18px; line-height: 27px;\" data-mce-style=\"font-size: 18px; line-height: 27px;\"><strong><span style=\"line-height: 27px; font-size: 18px;\" data-mce-style=\"line-height: 27px; font-size: 18px;\">ANY DEVICE, ANYWHERE, FAST.</span></strong></span></div>\n</div>",
"style": {
"color": "#FFFFFF",
"font-family": "'Montserrat', 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif",
"line-height": "150%"
}
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-text"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "20px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "30px"
}
}
],
"container": {
"style": {
"background-color": "#FF819C",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#333",
"width": "675px"
}
},
"locked": false,
"type": "two-columns-empty"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": "BF-ecommerce-template"
}
}
}
{
"message": "Success"
}
"layout":[
["name"],
["surname"],
["email"],
["privacy_checkbox"],
["submit"]
]
"layout":[
["email","telephone"],
["notes"],
["privacy_checkbox"],
["submit"]
]
In user interfaces, a workspace is a parameter that changes the appearance, settings, and widgets available in an builder, to help the user to focus on what matters.
In Beefree SDK, workspaces are an optional parameter that can be used to provide an experience focused on context and purpose, and to facilitate the outcome of an editing session.
You can load the builder with a certain workspace, but workspaces can also be changed by the user when editing, on-the-fly.
Switching between workspaces might change:
content visibility on the stage
tiles availability in the content tab
available previews
outputs when saving a content
…and more!
If no workspace is loaded at launch, the builder starts in its “Default” workspace.
We currently offer 3 additional workspaces, and we are planning to launch more as we evolve BEE and its capabilities.
These 3 workspaces revolve around the use of AMP content, and are provided so that you can tailor the experience of creating AMP emails in Beefree SDK.
Here is an overview of the different workspaces and their differences. Please refer to this page for more information on using AMP in Beefree SDK.
Stage message
HTML content
HTML & AMP content
HTML & AMP content
HTML content
Content tiles
HTML content tiles
HTML & AMP content tiles
HTML & AMP content tiles
HTML content
AMP sidebar properties
No
Yes
Yes
No
Available in preview
HTML content
HTML & AMP content
HTML & AMP content
HTML content
onSave callback files
HTML
HTML & AMP
HTML & AMP
HTML
Loading a template with AMP content
The onWarning is triggered
Template loads
Template loads
Template loads
Loading a template with HTML content only
Template loads
Template loads
Template loads
Template loads
Availability of the hide on AMP/HTML property
Not available
Yes
Yes
Yes
Behavior for hidden for HTML/AMP content
The onWarning is triggered
Both are visible
Only “hidden for HTML” content is visible
Only “hidden for AMP” content is visible
Here is an example of loading Beefree SDK with a “mixed” workspace:
type ClientConfig = {
workspace?: {
type:'default'|'mixed'|'amp_only'|'html_only'
}
// ....
}
const beeConfig: ClientConfig = {
workspace:{
type:'mixed'
}
// ....
}
//Create the instance
function BeePlugin.create(token, beeConfig, (beePluginInstance) => {
//....
}
You can implement a workspace selector within your application, so that users can switch between workspaces, by using the loadWorkspace(type)
method.
First, you need to define template files for the workspaces you want to propose, as JSONs:
{
"type":"mixed"
}
Then, you can load those workspaces at runtime:
type Workspace = 'default'|'mixed'|'amp_only'|'html_only'
const req = url => fetch(url).then(r => r.json())
const loadWorkspace = async (workspace:Workspace) => {
const { type } = await req(`https://example.com/workspaces/${workspace}.json`)
beePluginInstance.loadWorkspace(type)
}
And here is how to create a simple select to switch workspace:
<select id="workspace" onchange="loadWorkspace(this.value)">
<option selected="selected" value="">WORKSPACE</option>
<option value="default">DEFAULT</option>
<option value="mixed">MIXED</option>
<option value="amp_only">AMP_ONLY</option>
<option value="html_only">HTML_ONLY</option>
</select>
After you load a workspace, the application will trigger one of these three callbacks:
//SUCCESS
onLoadWorkspace: function (workspace) {
console.log(`workspace: ${workspace} has been loaded`);
},
//FAILURE
onError: function (error) {
console.error('error: ', error);
},
{
code: 1400,
name: "Invalid workspace type",
message: "RANDOM : is not a valid workspace",
details: "Available workspaces are: [ default,mixed,amp_only,html_only ]"
}
The additional workspaces for AMP (AMP-only and HTML-only) can become helpful if you want to tailor the user experience of creating AMP emails, by adding:
a workflow where users decides if they want to create a standard message or an AMP-powered message (in the first case, AMP components will be hidden in the builder;
an option to switch between the HTML and the AMP editing of a message.
In addition, omitting the workspace, or loading the “default” workspace for certain users, has the effect of disabling AMP for those users, even when AMP content is enabled in the Beefree SDK Console. This way, you can decide to make the feature available to customers of your application:
depending on the subscription plan that they are on (i.e. you could push users to a higher plan based on the ability to use AMP);
depending on the purchase of an optional feature (same);
only if they are “beta” customers, so they see it while keeping it hidden from the rest of your users.
Convert an email JSON template to a page JSON template, and ensure compatibility throughout the conversion process by removing or adjusting unsupported blocks.
The collection ID or name
POST /v1/{collection}/email-to-page HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 3810
{
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#FFFFFF"
}
},
"content": {
"computedStyle": {
"linkColor": "#0068A5",
"messageBackgroundColor": "transparent",
"messageWidth": "500px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": []
},
"description": "Empty template for BEE",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"type": "mailup-bee-newsletter-modules-paragraph",
"descriptor": {
"paragraph": {
"html": "<p>I'm a new paragraph block.</p>",
"style": {
"color": "#000000",
"font-size": "14px",
"font-family": "inherit",
"font-weight": "400",
"line-height": "120%",
"text-align": "left",
"direction": "ltr",
"letter-spacing": "0px"
},
"computedStyle": {
"linkColor": "#0068A5",
"paragraphSpacing": "16px"
}
},
"style": {
"padding-top": "10px",
"padding-right": "10px",
"padding-bottom": "10px",
"padding-left": "10px"
},
"mobileStyle": {},
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnHtml": false,
"hideContentOnDesktop": false,
"hideContentOnMobile": false
}
},
"uuid": "c8ecedba-4891-46fa-9aec-1f4ef3276914",
"locked": false
},
{
"type": "mailup-bee-newsletter-modules-image",
"descriptor": {
"image": {
"alt": "",
"src": "https://d153pg9b3vec03.cloudfront.net/public/users/Integrators/41032f14-a2c0-4389-842f-81e67db90a66/Marco/download.png",
"href": "",
"target": "_blank",
"width": "110px",
"height": "110px"
},
"style": {
"width": "100%",
"border-radius": "0px",
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"computedStyle": {
"class": "center autowidth",
"width": "110px",
"hideContentOnMobile": false
},
"mobileStyle": {}
},
"uuid": "bf5b394e-e238-40cf-9c45-69866139490c",
"locked": false
},
{
"type": "mailup-bee-newsletter-modules-table",
"descriptor": {
"table": {
"content": {
"headers": [
{
"cells": [
{
"html": "a"
},
{
"html": "a"
},
{
"html": "a"
}
]
}
],
"rows": [
{
"cells": [
{
"html": "Add text"
},
{
"html": ""
},
{
"html": ""
}
]
},
{
"cells": [
{
"html": ""
},
{
"html": ""
},
{
"html": ""
}
]
},
{
"cells": [
{
"html": ""
},
{
"html": ""
},
{
"html": ""
}
]
}
]
},
"style": {
"color": "#000000",
"font-size": "14px",
"font-family": "inherit",
"font-weight": "400",
"line-height": "120%",
"text-align": "left",
"direction": "ltr",
"letter-spacing": "0px",
"background-color": "transparent",
"border-top": "1px solid #dddddd",
"border-right": "1px solid #dddddd",
"border-bottom": "1px solid #dddddd",
"border-left": "1px solid #dddddd"
},
"computedStyle": {
"linkColor": "#0068A5",
"headersFontSize": "14px",
"headersFontWeight": "400",
"headersTextAlign": "left",
"headersBackgroundColor": "#EAEAEA",
"headersColor": "#505659"
}
},
"style": {
"padding-top": "10px",
"padding-right": "10px",
"padding-bottom": "10px",
"padding-left": "10px"
},
"mobileStyle": {},
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnHtml": false,
"hideContentOnDesktop": false,
"hideContentOnMobile": false
}
},
"uuid": "77957748-6069-40bd-9342-14f0b514f244",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "9cb47b70-8e2f-4e12-b79b-511f3c7b0dae"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "500px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "row-1-columns-12",
"uuid": "ae43b807-1a9d-4f1f-888d-798f74ec54b3"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": "Empty Template"
}
}
}
{
"message": "Success"
}
Convert a page JSON template to an email JSON template, and ensure compatibility throughout the conversion process by removing or adjusting unsupported blocks.
The collection ID or name
An integer field for disableHtmlSanitizer
POST /v1/{collection}/page-to-email HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 2705
{
"disableHtmlSanitizer": true,
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#FFFFFF"
}
},
"content": {
"computedStyle": {
"linkColor": "#0068A5",
"messageBackgroundColor": "transparent",
"messageWidth": "500px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": []
},
"description": "Empty template for BEE",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"type": "mailup-bee-newsletter-modules-html",
"descriptor": {
"html": {
"html": "<div class=\"our-class\"><script>console.log(\"ok\");</script>test 1</div>"
},
"style": {
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"computedStyle": {
"hideContentOnMobile": false,
"hideContentOnDesktop": false,
"hideContentOnAmp": false,
"hideContentOnHtml": false
}
},
"uuid": "f6c6a079-dd90-4589-8855-93dfdf74461d",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "cbd74fa2-b853-449e-88b8-f34195441c05"
},
{
"grid-columns": 12,
"modules": [
{
"type": "mailup-bee-newsletter-modules-html",
"descriptor": {
"html": {
"html": "<div class=\"our-class\"><script>console.log(\"ok\");</script>test 2</div>"
},
"style": {
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"computedStyle": {
"hideContentOnMobile": false,
"hideContentOnDesktop": false,
"hideContentOnAmp": false,
"hideContentOnHtml": false
}
},
"uuid": "f6c6a079-dd90-4589-8855-93dfdf74461d",
"locked": false
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "cbd74fa2-b853-449e-88b8-f34195441c05"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "500px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "row-1-columns-12",
"uuid": "d0a914f7-7212-41c6-9372-c954886e6bd4"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": "Empty Template"
}
}
}
{
"message": "Success"
}
Manage and modify the style of email, pages, and popup templates. Make template-wide design changes to existing templates quickly and easily, ensuring that all modules adhere to the broader design system or brand guidelines.
POST / template / brand
Content-Type: application / json
Authorization: Bearer YOUR_API_KEY
{
"styles": {
"general": {
"background": "#eeeeee",
"links": "#0068a5"
},
"h1": {
"styles": {
"color": "#333333",
"fontSize": "36px"
}
},
"h2": {
"styles": {
"color": "#CCCCCC",
"fontSize": 246 px "
}
},
"paragraph": {
"styles": {
"color": "#333333",
"fontSize": "16px"
}
},
"button": {
"styles": {
"backgroundColor": "#ff9900",
"borderRadius": "5px"
}
}
},
"template": {
// Your template JSON here
}
}
{
"styles": {
"button": [
{
"className": "Primary",
...more styles
},
{
"className": "Secondary",
...more styles
}
]
}
}
{
"html": “html document”,
"json": {
// Updated template JSON here
}
}
{
"general": {
// General brand styles
},
"title": {
// Title block styles
},
"text": {
// Text block styles
},
"button": {
// Button block styles
},
// Add more block styles as needed
}
{
"headersBackgroundColor": "#EAEAEA",
"headersColor": "#505659",
"headersFontSize": "14px",
"headersFontWeight": "400",
"headersTextAlign": "left",
"linkColor": "#0068a5"
}
"styles": {
"general": {
"background": "#eeeeee",
"links": "#0068a5"
}
}
You can load forms in the builder with two methods:
by passing in the configuration parameters a single, default JSON form, potentially including all the fields your application supports;
by implementing a content dialog and building a user interface on top of the builder, so that your users can browse and select forms.
If you successfully implement either method, you’ll see a new Form content tile in the builder Content tab.
Let’s see in detail how these methods work.
Use this method to provide a default form in the configuration parameters when the builder starts.
defaultForm: {
// Form
},
The default form will load when the user drags the form tile from the “Content” tab into the stage.
Here is an example of a typical login form:
defaultForm: {
structure: {
title: 'Form title',
fields: {
email: {type: 'email', label: 'Email'},
password: {type: 'password', label: 'Password'},
submit: {type: 'submit', label: ' ', attributes: {value: 'Login'}},
},
layout: [
['email', 'password', 'submit']
]
}
},
The default form you pass to a Beefree SDK application may consist of a simple form (e.g., the most used one), or a longer form that the user can customize using the options in the form content properties, as pictured here:
The flexibility of these properties allows you to cover multiple form building capabilities, even when implementing just a default form. Let’s see how.
For higher flexibility and better user experience, the form can be customized with the optional canBeModified
, canBeRemovedFromLayout
, and removeFromLayout
attributes.
canBeModified
all fields except file
, hidden
, label
, and submit
,
since they cannot be edited
boolean
true
This attribute can be used to turn off the “Edit field” dialog for a field. If set to false, the configuration for that field will be locked to the one defined in the form JSON you passed to the application, except for the label.
If unspecified, it will be applied as true, allowing the user to edit the field using the builder UI.
canBeRemovedFromLayout
all fields
boolean
true
This attribute indicates that a field can be toggled off by the user. If unspecified, it will be applied as true, allowing the user to switch it on or off in the builder UI.
It’s a best practice to add canBeRemovedFromLayout: false
to mandatory fields (e.g., the email address field in a sign-up form) so that they can’t be excluded in the HTML form.
removeFromLayout
all fields
boolean
false
This attribute indicates that a field is toggled off by default when the form is loaded. This behavior is quite useful to simplify the first experience when working with forms:
you can use a single form with all the possible fields, so there is no form selection step;
you can hide less common fields to load the most used combination at first, and keep the starting point simple, or even empty;
the user than can explore available fields with the form properites and build their custom form
defaultForm: {
"structure": {
"fields": {
"name": {
"type": "text",
"label": "Name",
"removeFromLayout": true,
"canBeRemovedFromLayout": true
},
"surname": {
"type": "text",
"label": "Surname",
"removeFromLayout": true,
"canBeRemovedFromLayout": true,
},
"email": {
"type": "email",
"label": "Email *",
"canBeRemovedFromLayout": false,
"attributes": {
"required": true
}
},
"notes": {
"type": "textarea",
"label": "Notes",
"removeFromLayout": true,
"canBeRemovedFromLayout": true
},
"privacy": {
"type": "checkbox",
"label": "Accept privacy policy. [Read it here](http://example.com)",
"canBeModified": false,
"canBeRemovedFromLayout": false,
"attributes": {
"required": true
}
},
"submit_button": {
"type": "submit",
"label": "",
"canBeRemovedFromLayout": false,
"attributes": {
"value": "SEND DATA",
"name": "submit_button"
}
}
}
}
},
When added, the form shows the minimum fields for submtting an email, e.g. for subscribing to a newsletter:
but then, the user can toggle on the available fields to transform it:
The content dialog allows you to build a user interface for selecting a form, on top of the builder. It can be a simple list with prebuilt forms, a search through categorized forms, a small form configurator or wizard, or even a complete form builder tailored for your application’s data.
For detailed information about this feature, please check the content dialog section.
The object that defines the form content dialog is the following:
manageForm: {
label: 'Change form',
handler: async (resolve, reject, args) => {
// Your function
}
},
As with most content dialog objects, the label is used within the interface to trigger the function:
The resolve object in the handler function must return a form using the structure and parameters described in this section.
The args object in the handler function returns to the host application the form object already applied. With this information, the application can decide what to display to the user (e.g., edit the current form, suggest a similar form, etc.).
An example of the content dialog object in beeConfig that handles special links and forms:
contentDialog: {
specialLinks: {
label: 'Custom text for links',
handler: function(resolve, reject) {
openMySpecialLinkDialog() // Replace this with your application function
.then(specialLink => resolve(specialLink))
.catch(() => reject())
}
},
manageForm: {
label: 'Edit form',
handler: async (resolve, reject, args) => {
const structure = await onHandleManageForm(args)
structure ? resolve(structure) : reject()
}
},
},
The default configuration returned by the system can be extended by using additional configuration objects such as:
Special links are links that your system generates dynamically when the message is sent, typically because they include the message ID, the recipient’s email, or some other variable. The most common one is probably the unsubscribe link.
The type
parameter will be used to group related links in the UI and simplify the user selection.
Technically, special links are passed to the application in the configuration file as follows:
specialLinks: [
{
type: 'Frequently used',
label: 'Unsubscribe link',
link: 'http://[unsubscribe]/'
},{
type: 'Frequently used',
label: 'Preference center link',
link: 'http://[preference_center]/'
},
/* Other special links */
];
and here’s an example of what the user will see in the builder UI, starting from the above code:
As mentioned above, when you initialize the application, in the configuration file you can submit both “merge tags” and “merge content”.
Really, they are the same thing: some syntax that your system will replace with some meaningful content at the time the email is sent. They differ in the way they are presented to the user.
Merge tags help dynamically insert text into a paragraph, such as the very common scenarios of “Dear {first_name}”.
Merge content, instead, helps the user insert special syntax as content element in other sections of the message that are not text, such a list of recommended products.
Currently it is not possible to group merge tags and merge contents as it is for special links.
Here is an example of adding mergeTags
and mergeContents
in the configuration file:
var mergeTags = [
{
name: 'First Name',
value: '[first-name]'
}, {
name: 'Latest order date',
value: '[order-date]'
}
];
var mergeContents = [
{
name: 'Headline news',
value: '{headline}'
}, {
name: 'Image of last product viewed',
value: '{last-product-viewed}'
}
];
Merge tags can be inserted into a text block by clicking on the “Merge tags” button in the expanded text block toolbar. The button is not shown if no merge tags were submitted in the configuration file.
Merge tags also become available to the user by pressing the @ key on the keyboard while editing a text block.
Here is an example: the user wants the date of the last order to be inserted after “[…] placing an order on …”, so he/she presses the @ key and selects “Last order date” from the list of merge tags found by the builder in the configuration file.
After inserting the merge tag, the text block now shows the placeholder for the last order date.
You can load Merge Tags in the builder when it is initialized by adding a mergeTags
node to the JSON configuration file. For example:
var mergeTags = [
{
name: 'First Name',
value: '[first-name]'
}, {
name: 'Last Name',
value: '[last-name]'
}, {
name: 'Email',
value: '[email]'
}, {
name: 'Latest order date',
value: '[order-date]'
}
];
… or you can allow users to search and insert a merge tag by using the flexible Content Dialog feature. This is especially useful when the number of merge tags is large, and picking from a list would not provide an optimal user experience.
You can use a combination of both approaches, loading frequently used merge tags at the time the builder is initialized, and then allowing users to look for additional merge tags using Content Dialog.
Merge content differs from merge tags in that it allows the user to drag and drop instances of it as a content element available in the Content panel.
For example, let’s say you have a section of an email where you want to display some recommended products: Merge Content allows you to insert some syntax into the message that your application will replace with the recommended products at the time the email is sent.
When Merge Content elements are submitted to the builder in the configuration file, a new tile is displayed in the Content panel.
The user can drag and drop it into the message just like any other content element.
Once dropped in position, the settings panel will display the instances of merge content available for selection.
In the example below, the user wants to insert some banner ads into the email, using a service such as LiveIntent. An array of Merge Content elements were submitted to the builder in the configuration file, so the user has several banner ads to choose from (i.e. some syntax that will be replaced with HTML when the email is sent).
To create another instance of merge content, the user can either drag and drop it again from the Content tab, or duplicate the existing content element…
… choose another instance of merge content from the available selections…
… and then drag it elsewhere in the message.
Just like with Merge Tags, you can load Merge Content in the builder at the time it is initialized by adding a mergeContents
node to the JSON configuration file. For example:
var mergeContents = [
{
name: 'Headline news',
value: '{headlines}'
}, {
name: 'Lastest blog articles',
value: '{latest-articles}'
}, {
name: 'Latest products viewed',
value: '{latest-products}'
}
];
… or you can allow users to search for additional instances of Merge Content by using the Content Dialog feature.
Here too, you can certainly use a combination of both approaches, loading frequently used Merge Content at the time the builder is initialized, and then allowing users to look for additional Merge Content using Content Dialog.
Merge tags are meant to be placeholders that will be replaced at the time an email is sent, or the web content is generated for visitors.
You cannot use HTML code in the text strings passed to the builder because – if you do – it will be encoded and will not function correctly in the source code of the message. Of course, you can replace the tag with HTML code at the time of saving or sending the message.
Standard merge tags do not support sample placeholder content, for now. The syntax will be displayed in the builder as your users design the message or page.
If you want to provide a better experience when working with Merge tags, including using a friendly name instead of the syntax and generating sample content, we recommend to check out Smart merge tags.
Additionally, there are some other limitations that are specific to the Merge Content feature. Among them:
Users cannot see & edit the content: what’s in it, the style used, the layout, etc..
Not seeing it, they could select the wrong content from the list of available Merge Content.
The HTML might be created outside of Beefree SDK, which could lead to rendering issues when it’s inserted into the message.
Since the HTML is created elsewhere, and it’s not part of the document created by Beefree SDK, it must be managed separately.
Due to these additional limitations, we now recommend an alternative approach to Merge Content in order to handle dynamic content in Beefree SDK: utilizing Custom Rows with Merge Content & Display Conditions.
You can use the Content Dialog feature to introduce an interactive layer between the builder and your application, and through it extend Merge Tags, Merge Content, Special Links, and Display Conditions.
Custom Rows are a powerful way to provide “ready-to-go” content directly into the builder. Think products, blog articles, events, coupons. And don’t forget that Saved Rows your customers might have will be loaded as Custom Rows the next time they load the builder.
All this content is crucial to make the most out of the Beefree SDK experience, and that’s why you can add UI elements in your app’s interface to:
jump right to a Custom Rows category, without the need for the user to go into the Rows tab, click on the dropdown and select the category;
provide additional information on the available rows, either through a tooltip or by showing a Content dialog with all the information and the links to the rows.
With this feature, you will reduce the friction needed to discover and access the builder’s Custom Rows. To do so, you’ll use the loadRows
event, which will trigger the Custom Rows content dialog.
Here’s an example of our Beefree product, which integrates Beefree SDK, taking advantage of this method to load custom rows from its UI.
The toolbar in the application contains explicit call-to-action text links to load footers, which correspond to different categories of Custom Rows in the application.
When users click on “Mailchimp Footers”, the Custom Rows Content Dialog is triggered, meaning that the builder opens a communication channel with your application. In this case, no additional UI will be displayed, as the host application provides the URL to the rows associated with that call-to-action. This way, the Rows tab will be immediately selected, with the “Mailchimp Footers” category already selected:
But what if you wanted users to select the email footers they need from a large catalog of pre-built content? In that scenario, you could have a more generic “Load footers” call-to-action in the toolbar.
Clicking on “Load Footers” will once again trigger the Custom Rows content dialog, but this time the application could provide a dialog window where users can browse or search through available footers, and get some additional context on them. Here is a visual example of how it might look like, but as with all content dialogs you have complete freedom on what to show:
When users click on MailChimp, the modal window fades off, the builder switches to the “Rows” tab, and the MailChimp Footers are shown, ready to be dragged into the message.
You can trigger the Custom Rows content dialog via the loadRows
instance event.
bee.loadRows()
Once the Content Dialog is triggered, you have two options, as explained in the How it works section:
Interact with the end user, as described in our Content Dialog documentation, and eventually return a URL of custom rows.
Immediately return the rows URL, without displaying the Content Dialog. This is useful if you have a menu and already know which rows to load based on the interaction by the end user with you application’s UI.
Content Dialog allows you to build user interfaces that let your users locate & insert additional content (Custom Rows) while they are working on their message.
By letting you establish an interaction layer between the editor and your application (e.g., you show a modal window), it allows your users to locate/build/insert new rows, thus making the Rows tab in the editor dramatically more flexible and scalable.
Note that Content Dialog may be used to load other content types, as merge tags, special links, or display conditions. Learn more about the Content dialog.
To start using it, you need to add the contentDialog object to beeConfig, or add the externalContentURLs parameter if you already use this feature in your editor configuration.
Here is an example of the syntax that needs to be added to the editor configuration document (beeConfig):
contentDialog: {
externalContentURLs: {
label: 'Search products',
handler: function(resolve, reject) {
// Your function
}
}
}
From the perspective of your users, this additional configuration adds a new item (using your text label) in the Rows drop-down.
Here is a visual example of how the “Search products” label will be shown, at the bottom of the Rows drop-down.
When the user clicks on the new menu item (e.g., “Search products” in the example above), what you define in the handler (a function with a Promise-like signature) is triggered.
You can use this event to display a form where the user can search for new items to insert in the message. Here is a visual example:
You could also ask the user to enter parameters that will affect the very structure of the rows (JSON documents) that will be imported into the editor, affecting the way they will display:
You can also mix both forms in a 2-step pattern.
When the selection is made, you must return to the resolve function a URL containing the result (row’s list).
The response must match the same format used to define the externalContentURLs in beeConfig:
{"name":"Results name","value":"Results URL"}
This response will:
Create a new drop-down choice with the provided name
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:
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.
This creates a new drop-down choice, keeping the previous results as selectable elements. Previous results are available directly in the drop-down.
Here is a visual example:
In our example, we are using this event to display a search form and transfer the user selection to the editor as custom rows.
The form is part of the application, so we are using the same elements and styles that users of the application are used to.
Rows can be saved directly in the editor using the Save Rows feature. These rows are returned to the host application as JSON objects that you can store based on your application logic.
These same rows can then be fed back into the editor by leveraging Custom Rows.
To do so, the host application must make them available in a reachable location specified through the externalContentURLs parameter.
The rows are displayed based on your rows configuration, so you can categorize them, creating multiple lists of rows to improve the user experience.
Here is an example of a rows configuration that displays saved items divided into usage categories:
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
selectedRowType: 'Headers', // Pre-selects the "Headers" row from the external content list
externalContentURLs: [
{
name: "Headers",
value: "https://URL-01"
},
{
name: "Footers",
value: "https://URL-02"
},
{
name: "Product grids",
value: "https://URL-03"
},
{
name: "Main article",
value: "https://URL-04"
}
]
}
And here is another example where saved rows are organized based on the campaign type:
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
selectedRowType: 'Newsletter', // Pre-selects the "Newsletter" row from the external content list
externalContentURLs: [
{
name: "Acquisition series",
value: "https://URL-01"
},
{
name: "Newsletter",
value: "https://URL-02"
},
{
name: "Transactional",
value: "https://URL-03"
},
{
name: "Post-Purchase Drip",
value: "https://URL-04"
}
]
}
The following is an example of the response schema when the editor calls one of the provided URLs:
[{
[{
metadata: {
name: 'My first row'
}
columns: { ... }
...
}, // The row that was previously saved
...
}]
},
{
[{
metadata: {
name: 'My second row'
}
columns: { ... }
...
}, // The row that was previously saved
...
}]
},{
[{
metadata: {
name: 'My third row'
}
columns: { ... }
...
}, // The row that was previously saved
...
}]
}]
With the introduction of Saved Rows Management, we’ve also introduced the ability to load external rows with an instance method. See here for more details.
A new feature becomes available in the File Manager when this is active.
It leverages an integration with popular stock photo services to offer users of the builder the ability to search through a large repository of high-quality images.
The images are free to use under the Creative Commons Zero (CC0) license.
When this is active, adds a toggle to the toolbar that allows a user to simulate the current design in dark mode.
When this is active, advanced users of the builder can set an image as background when editing a row.
When toggled on, this option scales the background image to fit the background dimensions of the entire document. This feature is best used with high-resolution images. More information here.
For Page and PopUp Builder.
When this is active, advanced users of the builder can set a video as the background when editing a row.
Requires “Row background video” to be enabled.
Enables the possibility for users to upload videos.
Requires “Row background video” to be enabled.
Enables a user to search for free stock videos to use in the File Manager.
When this setting is enabled, users of the builder can specify both a static placeholder image and a dynamic image URL when adding an image content block. This allows for scenarios such as personalized birthday cards, countdown timers, dynamic ads, and many other user cases in which an image is built dynamically at the time it is served. More about using dynamic images.
When enabled, adds a new row option to keep the horizontal layout on mobile devices. Useful when working with nav bars, icons, and other horizontal design elements.
When enabled, the display conditions widget will show as a row option. The widget can be used to apply the conditions created by the host applications or to add new syntax manually. More about display conditions.
When enabled, it adds a new property in the “Content properties” section of any content block that supports it. This widget allows users to hide a content block either on mobile or on desktop devices.
More on hiding content on mobile or desktop devices.
When you enable Custom Social Icons in the Social module, users will be able to upload their own social media icons as a new “Add a custom icon” feature will now be available in the Social content block’s property panel.
When enabled, it will give users the ability to Undo or Redo any changes that have been made to the email, including the ability to rewind and fast-forward to any point in their recent edit history.
This will allow users to select a row in the current message and save it for later use. More about Saved Rows.
When enabled, adds an option in the file manager to import images from different social networks and storage services. We use Filestack for this feature. Filestack may log the user’s IP address. If this is in conflict with your privacy policy, turn the feature off.
When enabled, an editor to apply image effects and transformations is available in the image module and row background images.
This feature allows users to leave comments and start discussion threads inside an email or page, to collaborate asynchronously. More on Commenting.
When enabled, adds a new row option to revert the stacking order of columns on mobile. Useful for layouts with alternating visual & text: applying it will ensure that, on mobile, images are consistently on top of their accompanying copy.
We use third-party tools to aggregate anonymous usage data. It helps us develop a better product by assessing locations, devices, browsers, etc.
This can be turned off if necessary.
When you disable the HTML sanitization service, you’re removing all restrictions on what users of the builder can add inside the Custom HTML content block.
The sanitize service checks and ‘cleans up’ custom HTML, which can be an important measure to prevent the inadvertent introduction of unsafe content or the usage of HTML tags that may impact the message delivery rate. However, it can also have an undesired side effect when the host application needs custom HTML tags or attributes to manage specific scenarios.
Please use caution when disabling this service.
Specifically, when HTML sanitization is disabled, we strongly recommend that you add an alternative code review process. To that extent, the onChange event can help the host application intercept the content as soon as it is inserted, and perform a check on it before the user exits the builder. Alternatively, you can use the onSave event to trigger an HTML review on your end at the time the HTML is saved in your system.
The client-side configuration exposes a parameter to override the global setting in the control panel. You cannot disable the HTML sanitization service in the client-side configuration, due to security reasons, but you can enable it per user via the forceSanitizeHTML parameter.
forceSanitizeHTML: true
The sanitization service allows the following tags and attributes:
a, abbr, acronym, address, b, bdo, big, blockquote, button, caption, center, cite, code, colgroup, dd, del, dfn, dir, div, dl, dt, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, i, ins, kbd, label, legend, li, map, menu, ol, optgroup, option, p, pre, q, s, samp, select, small, span, strike, strong, sub, sup, table, tbody, td, textarea, tfoot, th, thead, u, tr, tt, u, ul, var, video, source, style, img, br, hr, area, base, basefont, input, link, meta, col, iframe
general attributes
style, id, class, data-*, title
a
href, name, target
img
align, alt, border height, hspace, src, vspace, width, usemap
table
align, bgcolor, border, cellpadding, cellspacing, width
tbody
align, valign
td
align, bgcolor, colspan, height, rowspan, valign, width
tr
align, bgcolor, valign
tfoot
align, valign
th
align, bicolor, colspan, height, rowspan, valign, width
thead
align, valign
li
type
map
name
area
alt, coords, href, shape, target
div
itemscope, itemtype
meta
itemprop, content
video
autoplay, controls, height, loop, muted, poster, preload, src, width
source
media, src, type
In this section, you can activate restrictions for the file manager:
Specify which file formats your users can upload in File Manager.
Set a maximum allowed size, different from the default of 20MB.
Please note that the first option will not ask for file extensions, but will instead present file categories such as image, video, text, etc. We have mapped these categories to the most used MIME types that can be referenced in HTML documents.
Learn more about Mime Types and Groups for custom limitations on File manager.
This page discusses the ways that you can manage reusable content within the builder. There are different row management options, such as delete, edit, or display rows, available to you and your application's end users. Throughout this page, we will discuss these options and how you can implement them.
There is no limit to the number of rows passed to the builder in each array of custom rows.
However, the builder UI will only display the first 30 items (i.e., the first 30 rows in the array).
The rest of them will not show until the user performs a search that matches them. If the search matches over 30 items, the first 30 are displayed.
This filtering is applied to prevent performance degradation in the browser.
The search field allows users to narrow down the content shown after they select a list of .
The search is performed against all elements of the array (i.e., both visible and hidden), and the first 30 items (i.e., the first 30 rows in the array that match the search criteria) are shown.
All textual content included in the selected array – including image file names – is used to find a match.
The order of the JSON nodes in rowsConfiguration
defines the order in which the lists of custom rows will display in the drop-down. It also determines which list of rows will be used as default (selected) when the user clicks on the Rows tab for the first time during the session.
The first ordering factor refers to the type of row (empty, default, custom). That’s defined by how the following parameters are listed in rowsConfiguration:
emptyRows
defaultRows
externalContentURLs
You would list defaultRows
before emptyRows
to obtain the order shown in the following screenshot:
The order inside the externalContentURLs
node defines the order of the Custom rows.
In the above example configuration:
emptyRows
will be the first item in the drop-down and the default selection when clicking on the Rows tab.
defaultRows
will be the second item in the drop-down.
The lists of rows defined in externalContentURLs
will follow their ordering in the drop-down.
It’s up to you – the host application – to decide what’s available and in which order.
Note the following row type requirements when configuring your rowsConfiguration parameter:
emptyRows
and defaultRows
are not required.
This allows you to load just Custom rows through externalContentURLs
, if needed, controlling which rows end users can drag and drop into the builder.
The maxRowsDisplayed
parameter enables you to define the number of rows displayed under each user-created category in the application's sidebar, without affecting the "Empty" and "Default" categories. It directly influences the number of saved rows an end user sees when they click on a category in the sidebar.
You can set the maxRowsDisplayed
parameter in the rowsConfiguration
object in the Beefree SDK Configuration as follows:
The following section discusses how to configure the Saved Rows Management categories.
Accessing, and organizing saved rows is intuitive with Saved Rows Management. With this feature, there is an available action in the list of saved rows that your application can intercept to handle changes in this list itself. This means you can delete, rename, or re-organize your saved rows inside the builder.
Implementing Saved Rows Management Actions requires some development effort from the host application. This section outlines what you need to know for each action.
To get started, you will need to create a content dialog in your application configuration parameters. The content dialog method should be named onDeleteRow
and be nested under the contentDialog
object, as follows:
Following that, amend your rowsConfiguration
object with the additional parameters:
The handle
parameter to utilize in your onDeleteRow
handler from the previous step
The optional behaviors
parameter to set management permissions
Here’s an example:
When the onDeleteRow
method is called, utilize the 3rd parameter to obtain an argument containing the handle value of the row being requested, as well as the row metadata. Use the handle and the row’s metadata to determine which row should be deleted.
Finally, we can call the resolve
method, passing the value true
if you want to refresh the rows, or false
if you want to keep the side panel’s current listing.
To get started, much like with deleting rows, you will need to create a content dialog in your application configuration parameters. The content dialog method should be named onEditRow
and be nested under the contentDialog
object, as follows:
Following that, amend your rowsConfiguration
object with the additional parameters:
The handle
parameter to utilize in your onEditRow
handler from the previous step
The optional behaviors
parameter to set management permissions
Here’s an example:
When the onEditRow
method is called, utilize the 3rd parameter to obtain an argument containing the handle value of the row being requested, as well as the row metadata. Use the handle and the row’s metadata to determine which row should be edited.
Finally, we can call the resolve
method, passing the value true
if you want to refresh the rows, or false
if you want to keep the side panel’s current listing.
Saved Rows Management also provides errors and warnings for your application, so you can handle all cases gracefully.
You can call the reject
method, passing the message you want to display.
POST /v1/template/brand HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 6315
{
"styles": {
"button": {
"className": "Primary",
"styles": {
"color": "#FBF9FF",
"fontSize": "16px",
"fontFamily": "Inter,sans-serif",
"backgroundColor": "#7747ff",
"borderBottom": "0px solid transparent",
"borderLeft": "0px solid transparent",
"borderRight": "0px solid transparent",
"borderTop": "0px solid transparent",
"borderRadius": "5px",
"lineHeight": "120%",
"maxWidth": "100%",
"paddingBottom": "8px",
"paddingLeft": "20px",
"paddingRight": "20px",
"paddingTop": "8px"
},
"blockOptions": {
"paddingBottom": "20px",
"paddingLeft": "20px",
"paddingRight": "20px",
"paddingTop": "20px",
"align": "left",
"hideContentOnMobile": true
}
}
},
"template": {
"page": {
"body": {
"container": {
"style": {
"background-color": "#fff"
}
},
"content": {
"computedStyle": {
"linkColor": "#8a3b8f",
"messageBackgroundColor": "transparent",
"messageWidth": "650px"
},
"style": {
"color": "#000000",
"font-family": "Lato, Tahoma, Verdana, Segoe, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Lato', Tahoma, Verdana, Segoe, sans-serif",
"name": "Lato",
"url": "https://fonts.googleapis.com/css?family=Lato"
}
]
},
"description": "",
"rows": [
{
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-repeat": "no-repeat",
"background-position": "top left"
}
},
"content": {
"style": {
"background-color": "transparent",
"color": "#000000",
"width": "500px",
"background-image": "none",
"background-repeat": "no-repeat",
"background-position": "top left",
"border-top": "0px solid transparent",
"border-right": "0px solid transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "0px"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"columns": [
{
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"modules": [
{
"type": "mailup-bee-newsletter-modules-heading",
"descriptor": {
"heading": {
"title": "h1",
"text": "<span class=\"tinyMce-placeholder\">BUTTON</span>",
"style": {
"color": "#555555",
"font-size": "23px",
"font-family": "inherit",
"link-color": "#E01253",
"line-height": "120%",
"text-align": "left",
"direction": "ltr",
"font-weight": "700",
"letter-spacing": "0px"
}
},
"style": {
"width": "100%",
"text-align": "center",
"padding-top": "0px",
"padding-right": "0px",
"padding-bottom": "0px",
"padding-left": "0px"
},
"mobileStyle": {},
"computedStyle": {
"width": 52,
"height": 42
}
},
"uuid": "00a47280-8fa6-4519-b6c8-dcd5f28f35a2"
}
],
"grid-columns": 12,
"uuid": "9b3de3ea-4f56-4e21-b7cc-848aea563dc0"
}
],
"type": "one-column-empty",
"uuid": "dce46360-6ac7-4bee-bc24-f5688917b7b4"
},
{
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-repeat": "no-repeat",
"background-position": "top left"
}
},
"content": {
"style": {
"background-color": "transparent",
"color": "#000000",
"width": "500px",
"background-image": "none",
"background-repeat": "no-repeat",
"background-position": "top left",
"border-top": "0px solid transparent",
"border-right": "0px solid transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-radius": "0px"
},
"computedStyle": {
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top",
"hideContentOnMobile": false,
"hideContentOnDesktop": false
}
},
"columns": [
{
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"modules": [
{
"type": "mailup-bee-newsletter-modules-button",
"descriptor": {
"button": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p dir=\"ltr\" style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Call to action button</p></div>",
"href": "",
"target": "_blank",
"style": {
"font-family": "'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Typewriter', monospace",
"font-size": "14px",
"font-weight": "400",
"background-color": "#3AAEE0",
"border-radius": "4px",
"border-top": "0px solid transparent",
"border-right": "0px solid transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"color": "#ffffff",
"line-height": "200%",
"padding-top": "5px",
"padding-right": "20px",
"padding-bottom": "5px",
"padding-left": "20px",
"width": "auto",
"max-width": "100%",
"direction": "ltr"
}
},
"style": {
"text-align": "left",
"padding-top": "10px",
"padding-right": "10px",
"padding-bottom": "10px",
"padding-left": "10px"
},
"mobileStyle": {},
"computedStyle": {
"width": 216,
"height": 38,
"hideContentOnMobile": false
}
},
"customFields": {
"className": "Primary"
},
"uuid": "be31ba9a-b0b0-4ae7-b3ea-562ff74bb775"
},
{
"type": "mailup-bee-newsletter-modules-button",
"descriptor": {
"button": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p dir=\"ltr\" style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">100% width button example</p></div>",
"href": "",
"target": "_blank",
"style": {
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"background-color": "#3AAEE0",
"border-radius": "4px",
"border-top": "0px solid transparent",
"border-right": "0px solid transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"color": "#ffffff",
"line-height": "200%",
"padding-top": "5px",
"padding-right": "20px",
"padding-bottom": "5px",
"padding-left": "20px",
"width": "100%",
"max-width": "100%",
"direction": "ltr"
}
},
"style": {
"text-align": "center",
"padding-top": "10px",
"padding-right": "10px",
"padding-bottom": "10px",
"padding-left": "10px"
},
"mobileStyle": {},
"computedStyle": {
"width": 630,
"height": 38,
"hideContentOnMobile": false
},
"customAttributes": [
{
"key": "class",
"name": "class",
"value": "Primary",
"target": "tag"
}
]
},
"customFields": {
"className": "Primary"
},
"uuid": "220b02a8-1cb9-429a-88c6-c2b7028a9f31"
}
],
"grid-columns": 12,
"uuid": "3967ef9b-ed2b-4e9e-8fe4-2367736e32cc"
}
],
"type": "one-column-empty",
"uuid": "ce0b0367-bb90-4eaa-92e2-095d5a9170dc"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
},
"comments": {}
}
}
{
"message": "Success"
}
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
externalContentURLs: [{
name: "Acquisition series",
value: "https://URL-01"
},{
name: "Newsletter",
value: "https://URL-02"
},{
name: "Transactional",
value: "https://URL-03"
},{
name: "Post-Purchase Drip",
value: "https://URL-04"
}]
},
rowsConfiguration: {
maxRowsDisplayed: 50
}
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
contentDialog: {
onDeleteRow: {
handler: async (resolve, reject, args) => {
}
}
},
}
rowsConfiguration: {
externalContentURLs: [
{
name: "Saved Rows",
value: "category-value",
handle: "category-handle",
behaviors: {
canEdit: true,
canDelete: false,
canEditSyncedRows: false,
canDeleteSyncedRows: false,
},
}
],
maxRowsDisplayed: 50
}
{
value: "category-value",
handle: "category-handle",
row: {
name: "My row name",
metadata: {
name: "My row name",
guid: "key-for-deletion"
}
... // more row data
}
}
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
contentDialog: {
onDeleteRow: {
handler: async (resolve, reject, args) => {
// get the unique row id from metadata
const row_id = args?.row?.metadata?.guid
// pseudo code to delete a row and refresh the panel...
const result = await fakeRowDeleteService(row_id)
if (result === 'success') resolve(true)
reject(result)
}
}
},
}
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
contentDialog: {
onEditRow: {
handler: async (resolve, reject, args) => {
}
}
},
}
rowsConfiguration: {
externalContentURLs: [
{
name: "Saved Rows",
value: "category-value",
handle: "category-handle",
behaviors: {
canEdit: true,
canDelete: false,
canEditSyncedRows: false,
canDeleteSyncedRows: false,
},
}
]
}
{
value: "category-value",
handle: "category-handle",
row: {
name: "My row name",
metadata: {
name: "My row name",
guid: "key-for-deletion"
}
... // more row data
}
}
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
contentDialog: {
onEditRow: {
handler: async (resolve, reject, args) => {
// get the unique row id from metadata
const row_id = args?.row?.metadata?.guid
// pseudo code to edit a row and refresh the panel...
const result = await openFakeDialogToEditRow(row_id)
if (result === 'success') resolve(true)
reject(result)
}
}
},
}
{
warn: {
message: "This is a warning",
detail: "You don't have management permissions."
}
}
{
error: {
message: "This is an error",
detail: "You don't have management permissions."
}
}
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
contentDialog: {
onEditRow: {
handler: async (resolve, reject, args) => {
const warn = {
message: 'This is a warning.',
detail: 'You don't have management permissions.'
}
return reject({ warn })
}
}
},
}
This page provides a comprehensive list of HTML form field types, detailing their unique attributes and options, along with global attributes that apply to all fields.
The following global attributes are applicable across all field types. They define essential properties related to accessibility, content structure, behavior, and presentation. Reference the Global attributes and Attributes sub-sections of the HTML reference in mdn web docs to try out the attributes and learn more about their specifications.
List of Global Attributes and their corresponding explanations:
accesskey
: Defines a shortcut key to activate or focus an element.
class
: Assigns one or more class names to an element, used for styling and script interaction.
contenteditable
: Indicates whether the content of the element is editable.
dir
: Specifies the text direction (ltr
, rtl
, or auto
).
disabled
: Disables an element, making it not selectable.
readonly
: Prevents modification of the element’s content while still allowing interaction.
draggable
: Allows the element to be dragged.
hidden
: Hides the element.
id
: Assigns a unique identifier to an element.
name
: Specifies the name of the form control. Reference the mdn web docs on the name attribute to try it and learn more about its specifications.
itemid
: Provides a unique identifier for items when using microdata.
itemprop
: Specifies properties for microdata.
itemref
: References other items related to the current item for microdata.
itemscope
: Defines the scope of an item for microdata.
itemtype
: Defines the type of an item for microdata.
lang
: Declares the language of the element’s content.
tabindex
: Defines the tab order for focusable elements.
title
: Provides additional information about an element, often used as a tooltip.
value
: Specifies the value of the input element.
The following sections list the unique attributes for each field type. Reference the <input> types sub-section of the HTML Reference section of the mdn web docs to try out and learn more about unique attributes outlined in the subsequent sections.
The checkbox
field allows users to select multiple options from a list. It is often used to toggle between two states, like "checked" or "unchecked."
checked
(boolean): Specifies whether the checkbox is selected by default.
options
: An array of options, each with:
value
(string)
label
(string)
The color
field allows users to select a color from a color picker.
autocomplete
(string): Specifies if the browser should provide autocomplete suggestions.
list
(string): Refers to a <datalist>
that provides predefined color options.
required
(boolean): Specifies that the field must be filled before form submission.
The datalist
field provides a list of predefined options for other input fields, enhancing usability by offering suggestions.
No unique attributes.
options
: An array of options, each with:
value
(string)
The date
field allows users to select a date, displayed as a date picker.
autocomplete
(string): Specifies if the browser should suggest previously entered dates.
max
(string): Sets the maximum date allowed.
min
(string): Sets the minimum date allowed.
required
(boolean): Specifies that a date must be selected before submission.
step
(string): Specifies the granularity of selectable dates (e.g., steps in days).
The datetime-local
field allows users to input both a date and a time.
autocomplete
(string)
max
(string): Sets the maximum allowed date and time.
min
(string): Sets the minimum allowed date and time.
required
(boolean): Requires a date and time before form submission.
step
(string): Specifies the granularity of selectable times (e.g., steps in minutes).
The email
field is used for inputting one or more email addresses.
autocomplete
(string)
maxlength
(string): Specifies the maximum number of characters allowed.
minlength
(string): Specifies the minimum number of characters required.
multiple
(boolean): Allows multiple email addresses.
placeholder
(string): Displays a hint to the user.
required
(boolean): Requires an email address before form submission.
size
(string): Sets the visible width of the input.
The file
field allows users to upload one or more files from their device.
accept
(string): Specifies the types of files accepted by the server (e.g., image/png
).
capture
(string): Allows capturing images/audio from the camera/microphone if supported.
multiple
(boolean): Allows selecting multiple files.
required
(boolean): Specifies that at least one file must be uploaded.
The hidden
field stores data that the user cannot see or interact with but is submitted with the form.
autocomplete
(string)
The image
field creates a graphical submit button using an image.
alt
(string): Provides alternate text if the image cannot be displayed.
height
(string): Specifies the image URL.
src
(string): Defines the height of the image (in pixels).
width
(string): Defines the width of the image (in pixels).
The label
field associates a text label with a form control, improving accessibility.
No unique attributes.
The month
field allows users to select a month and year without choosing a specific day.
autocomplete
(string)
max
(string): Specifies the latest allowed month.
min
(string): Specifies the earliest allowed month.
required
(boolean): Ensures a selection is made before form submission.
step
(string): Defines the interval for month selection.
The number
field allows users to input numeric values.
autocomplete
(string)
max
(number): Sets the maximum allowed value.
min
(number): Sets the minimum allowed value.
required
(boolean): Requires a numeric value before submission.
step
(number): Specifies the allowed increment for numbers.
The password
field allows users to input masked text (e.g., passwords).
autocomplete
(string)
maxlength
(string): Limits the number of characters allowed.
minlength
(string): Sets the minimum number of characters required.
pattern
(string): Specifies a regular expression for validation.
placeholder
(string): Provides a hint to the user.
required
(boolean): Specifies that the field must be filled.
size
(string): Defines the visible width of the input.
The radio
field allows users to select one option from a group.
checked
(boolean): Indicates whether the radio button is selected by default.
required
(boolean): Specifies that one option must be selected before form submission.
options
: An array of options, each with:
value
(string)
label
(string)
The range
field allows users to select a numeric value within a range, often displayed as a slider.
autocomplete
(string)
max
(number): Sets the maximum allowed value.
min
(number): Sets the minimum allowed value.
step
(number):Defines the granularity of the range (e.g., steps in increments of 1 or 10).
The select
field creates a dropdown list that allows users to choose one or more options.
autocomplete
(string)
multiple
(boolean): Allows multiple selections if set to true.
required
(boolean): Specifies that the user must select at least one option.
size
(string): Defines the number of visible options in the dropdown.
options
: An array of options, either:
option
elements, with:
value
(string)
label
(string)
optgroup
elements, containing groups of options.
The search
field allows users to enter search queries with specialized input handling.
autocomplete
(string)
dirname
(string): Submits the text directionality of the search field with the form.
maxlength
(string): Limits the number of characters allowed in the input.
minlength
(string): Specifies the minimum number of characters.
placeholder
(string): Provides a hint about the expected input.
required
(boolean): Ensures that a search term is entered before submission.
The submit
field creates a button that submits the form data.
data-sitekey
(string): Used in conjunction with reCAPTCHA to verify form submissions.
data-callback
(string): Defines a JavaScript function to be executed after submission.
data-action
(string): Defines an action to be associated with the submit button.
width
(string): Defines the width of the submit button.
The tel
field allows users to enter telephone numbers.
autocomplete
(string)
maxlength
(string): Limits the number of characters allowed.
minlength
(string): Sets the minimum number of characters required.
pattern
(string): Provides a pattern for validation (e.g., for formatting telephone numbers).
placeholder
(string): Displays a hint about the expected input.
required
(boolean): Specifies that a telephone number must be entered before submission.
size
(string): Defines the visible width of the input.
The text
field allows users to input text.
autocomplete
(string)
maxlength
(string): Limits the number of characters allowed.
minlength
(string): Specifies the minimum number of characters.
pattern
(string): Provides a regular expression for validation.
placeholder
(string): Displays a hint for the expected input.
required
(boolean): Ensures that a value is entered before form submission.
size
(string): Specifies the visible width of the text input.
The textarea
field allows for multi-line text input, offering more space than the text
field.
autocomplete
(string)
cols
(number): Defines the visible width of the textarea in characters.
rows
(number): Defines the visible height of the textarea in lines.
maxlength
(string): Limits the number of characters allowed.
minlength
(string): Sets the minimum number of characters required.
placeholder
(string): Provides a hint about the expected input.
spellcheck
(string): Enables or disables spell checking.
wrap
(string): Controls text wrapping behavior (e.g., "hard"
or "soft"
).
required
(boolean): Specifies that input is mandatory before form submission.
The time
field allows users to input a time (hours, minutes, and optionally seconds).
autocomplete
(string)
max
(string): Sets the latest allowable time.
min
(string): Sets the earliest allowable time.
required
(boolean): Requires a time to be entered before form submission.
step
(string): Specifies the time granularity (e.g., steps in seconds).
The url
field is used for inputting valid URLs.
autocomplete
(string)
maxlength
(string): Sets the maximum number of characters allowed.
minlength
(string): Specifies the minimum number of characters required.
placeholder
(string): Provides a hint for the expected input.
required
(boolean): Ensures that a valid URL is entered before form submission.
The week
field allows users to select a specific week within a year.
autocomplete
(string)
max
(string): Specifies the latest week that can be selected.
min
(string): Specifies the earliest week that can be selected.
required
(boolean): Requires a week to be selected before form submission.
step
(string): Specifies the granularity of week selection.
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.
*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.
You can limit the number of Hosted Saved Rows an end user can save by their unique UID. The maxHostedRowsLimit
parameter lets you define the maximum number of Hosted Saved Rows an end user can create in your Beefree SDK configuration. Use this parameter to establish predictable saving patterns for Hosted Saved Rows within your application.
Why use maxHostedRowsLimit
?
Customize at the user level: Set unique limits per user ID (UID), giving you flexibility to adapt quotas based on specific needs or plan tiers.
Control usage and make costs more predictable: Prevent scenarios where users save large numbers of rows, leading to unexpected usage-based charges. By setting a clear upper limit, you can better forecast and manage your costs.
Differentiate your pricing plans: Create customized experiences for different user segments. For example, offer 3 saved rows to free-tier users and unlock higher limits for premium users. This allows you to align features with your pricing model and incentivize upgrades.
Code Snippet Example
The following code snippet shows an example of how to use the maxHostedRowsLimit
parameter in your beeConfig
file.
const beeConfig = {
rowsConfiguration: {
// Define custom row behavior or limitations here
// e.g., maxColumnsPerRow: 2,
},
maxHostedRowsLimit: 10, // Maximum number of hosted saved rows the user can save
};
In this example, the user can save up to 10 Hosted Saved Rows. Beefree SDK will block attempts to save more than this limit.
When you limit the number Hosted Saved Rows for an end user, they will see a toast message on the lower right-hand side of the screen when their limit is reached. The default message for this toast message is the following:
Title: Saved rows limit reached
Description: You've saved 5 of 5 rows. To save a new row, please delete an existing one first.
The following image shows how this default toast message looks within the user interface.
You can use Custom Languages to customize both the title and description text within this message. For example, if you have more of playful brand tone within your application, and want to adjust the message accordingly, you can.
In the following code snippet, the default text was changed to the following:
Title: Whoa there, design superstar!
Description: You’ve hit your 5-row max—time to let one go before saving another.
This was achieved by adding the translations
object to the beeConfig
, and then adding the strings within the object with the new text.
var beeConfig = {
uid: uid, // [mandatory]
container: "bee-plugin-container", // [mandatory]
language: "en-US",
trackChanges: true,
mergeTags: mergeTags,
translations: {
"hosted-content": {
"save-row-max-limit-error-toast-title": "Whoa there, design superstar! ", // Title text
"save-row-max-limit-error-toast-description": "You’ve hit your 5-row max—time to let one go before saving another.", // Message text
},
},
saveRows: uid === "Admin" || uid === "Designer",
};
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
:
{
...
advancedPermissions:{
...
rows:{
behaviors: {
canDeleteHostedRow: false,
canEditHostedRow: false,
canManageHostedRowCategory: false,
canAddHostedRowCategory: false,
},
...
},
...
}
...
}
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.
const beeConfig = {
uid: 'dev-user',
language: 'en-US',
...
saveRows: false // boolean
...
}
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']
.
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.
defaultTabsOrder: ['content', 'settings']
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.
defaultTabsOrder: ['settings', 'content']
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:
You can customize the list of fonts available in the editor’s text toolbar and the body settings panel.
This feature allows you (or users of your app) to:
Expand the list of available fonts, adding web fonts from popular services, such as Google fonts, font library.org or alike.
Reduce the list of fonts to a limited number of options, removing some or all our default fonts.
Unlike other premium features, fonts are part of the client-side configuration, so they can be defined each time the editor is started.
This flexible approach will help you use this feature in a variety of scenarios. A few example scenarios are the following:
You want your users to customize the list of fonts loaded in the builder when they edit designs. You can now create an interface in your app to do so, and instruct the editor accordingly (see below).
You have multiple levels of users, and you want “contributors” to only see a subset of approved fonts, while “editors” have access to a larger list.
You are a digital marketing agency, and you want to customize the list of fonts in the editor depending on the client/brand for which the email message is being designed.
For instance, in our hosted email design suite (Beefree), we leveraged this Beefree SDK feature to create a “Brand styles > Brand fonts” area where an agency or marketing team can select which fonts have been approved by that brand. Only the selected fonts will be loaded in the builder when an application is initialized. Here is a screenshot.
This object, passed as part of the builder configuration, tells the editor which fonts to load in any drop-down where a list of fonts is shown. It defines the availability of the default fonts and provides a list of additional, custom fonts.
editorFonts: {
showDefaultFonts: true,
customFonts: [{
name: "Comic Sans",
fontFamily: "'Comic Sans MS', cursive, sans-serif"
},
{
name: "Lobster",
fontFamily: "'Lobster', Georgia, Times, serif",
url: "https://fonts.googleapis.com/css?family=Lobster"
}]
}
In this example default fonts are loaded, and two new fonts are added: a web safe font (Comic Sans) and a Google hosted web font (Lobster).
Here is a more detailed description on how the editorFonts object is built:
showDefaultsFonts
This boolean parameter indicates if the entire list of default fonts is available or not. When the value is false, only the fonts added as custom fonts will be active in the editor.
customFonts
When the default font parameter is true, the custom fonts declared inside this object will be added to the list of default fonts: both are loaded into the editor. Otherwise, only custom fonts will be shown.
Each customFonts
element can have the following properties:
When we add a set of custom fonts, we can decide between system fonts and web fonts. Let’s see some details on what you need to know:
System fonts are installed on the operative systems and don’t need any external resource to work, so we can skip the url parameter.
Web fonts are hosted online and need to be loaded by the email client when the email is opened. Beefree SDK accepts only the CSS font embedding method, and the CSS file must be hosted in HTTPS protocol. You can use services like Google fonts, that provides host, font stacks and a well formatted CSS file.
We want the editor to work with only 2 fonts when creating a message, we want that only Lobster and Cabin fonts are available when editing this message:
editorFonts: {
showDefaultFonts: false,
customFonts: [{
name: "Cabin",
fontFamily: "'Cabin', Helvetica, Arial, sans-serif",
url: "https://fonts.googleapis.com/css?family=Lobster"
},
{
name: "Lobster",
fontFamily: "'Lobster', Georgia, Times, serif",
url: "https://fonts.googleapis.com/css?family=Lobster"
}]
}
In the following example, instead, we don’t want to add new fonts but restrict the default ones to our own selection:
editorFonts: {
showDefaultFonts: false,
customFonts: [{
name: "Helvetica",
fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
},
{
name: "Lucida",
fontFamily: "'Lucida Grande', 'Lucida Sans', Geneva, Verdana, sans-serif"
},
{
name: "Georgia",
fontFamily: "Georgia, Times, 'Times New Roman', serif"
},
{
name: "Lato",
fontFamily: "'Lato', Tahoma, Verdana, sans-serif",
url: "https://fonts.googleapis.com/css?family=Lato"
},
{
name: "Montserrat",
fontFamily: "'Montserrat', Trebuchet MS, Lucida Grande, Lucida Sans Unicode, sans-serif",
url: "https://fonts.googleapis.com/css?family=Montserrat"
}]
}
Notice that if you want to change the default set of fonts, you need to disable them and use custom fonts to indicate the new set, including the URL parameter for web fonts.
This is the complete list of the default fonts in the application and its configuration, including the external URL for web fonts:
{
name: "Arial",
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
}, {
name: "Courier",
fontFamily: "'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Typewriter', monospace"
}, {
name: "Georgia",
fontFamily: "Georgia, Times, 'Times New Roman', serif"
}, {
name: "Helvetica Neue",
fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif"
}, {
name: "Lucida Sans",
fontFamily: "'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Geneva, Verdana, sans-serif"
}, {
name: "Tahoma",
fontFamily: "Tahoma, Verdana, Segoe, sans-serif"
}, {
name: "Times New Roman",
fontFamily: "TimesNewRoman, 'Times New Roman', Times, Beskerville, Georgia, serif"
}, {
name: "Trebuchet MS",
fontFamily: "'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif"
}, {
name: "Verdana",
fontFamily: "Verdana, Geneva, sans-serif"
}, {
name: "ヒラギノ角ゴ Pro W3",
fontFamily: "ヒラギノ角ゴ Pro W3, Hiragino Kaku Gothic Pro,Osaka, メイリオ, Meiryo, MS Pゴシック, MS PGothic, sans-serif"
}, {
name: "メイリオ",
fontFamily: "メイリオ, Meiryo, MS Pゴシック, MS PGothic, ヒラギノ角ゴ Pro W3, Hiragino Kaku Gothic Pro,Osaka, sans-serif"
}, {
name: "Bitter",
fontFamily: "'Bitter', Georgia, Times, 'Times New Roman', serif",
url: "https://fonts.googleapis.com/css?family=Bitter"
}, {
name: "Droid Serif",
fontFamily: "'Droid Serif', Georgia, Times, 'Times New Roman', serif",
url: "https://fonts.googleapis.com/css?family=Droid+Serif"
}, {
name: "Lato",
fontFamily: "'Lato', Tahoma, Verdana, Segoe, sans-serif",
url: "https://fonts.googleapis.com/css?family=Lato"
}, {
name: "Open Sans",
fontFamily: "'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif",
url: "https://fonts.googleapis.com/css?family=Open+Sans"
}, {
name: "Roboto",
fontFamily: "'Roboto', Tahoma, Verdana, Segoe, sans-serif",
url: "https://fonts.googleapis.com/css?family=Roboto"
}, {
name: "Source Sans Pro",
fontFamily: "'Source Sans Pro', Tahoma, Verdana, Segoe, sans-serif",
url: "https://fonts.googleapis.com/css?family=Source+Sans+Pro"
}, {
name: "Montserrat",
fontFamily: "'Montserrat', 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif",
url: "https://fonts.googleapis.com/css?family=Montserrat"
}, {
name: "Ubuntu",
fontFamily: "'Ubuntu', Tahoma, Verdana, Segoe, sans-serif",
url: "https://fonts.googleapis.com/css?family=Ubuntu"
}
In this example, we want to add font weight options to our list:
var editorFonts = {
showDefaultFonts: true,
customFonts: [{
name: "Comic Sans MS",
fontFamily: "'Comic Sans MS', cursive, sans-serif"
},{
name: "Indie Flower",
fontFamily: "'Indie Flower', cursive",
url: "https://fonts.googleapis.com/css?family=Indie+Flower"
},{
name: "Oswald",
fontFamily: "'Oswald', sans-serif",
url: "https://fonts.googleapis.com/css2?family=Oswald:wght@200;300;400;500;600;700&display=swap",
fontWeight: {
200: 'Extra-light',
300: 'Light',
400: 'Regular',
500: 'Medium',
600: 'Semi-bold',
700: 'Bold',
}
}]
};
We open a saved template that uses fonts that are not available:
System fonts will display normally in the editor and the text can be edited, but the font-family is not available in the font selector.
Web fonts will fallback to a system font. Text can be edited and the font-family is not available on the font selector.
We are able to save the message that already uses unavailable fonts.
Discover the configuration parameters within Beefree SDK.
Once you have initialized your Beefree SDK application, you can pass a series of configuration parameters to it.
The following code displays an example of a default configuration:
The following table provides a list of the required parameters.
The following table provides a list of the language options for the language parameter. The language parameter is not required and has a default value of en-US
.
Available Languages
The following table provides a list of the optional parameters and their corresponding descriptions.
Synced Rows expands on the foundational capabilities of and , helping users manage rows more effectively. Using the merge-rows
and synced-rows
methods in the , you can create an efficient row management workflow. This ensures that when users update content in one row marked as “synced,” those updates are reflected across all connected designs using that synced row.
Cross-design synchronization: Sync saved row contents across multiple linked designs.
Design consistency: Lock rows in linked designs to keep designs uniform.
Editing flexibility: Convert rows from synced to unsynced, making individual changes as needed.
Intuitive edit indicator: Look for the pencil icon at the top-right of synced rows, which provides access to editing options
Auto-updating contacts: Change a contact in one email, and it updates across multiple campaigns.
Effortless re-branding: Edit your logo once and watch it reflect across all designs.
Unified transactional footers: Update details like copyright or social links, and it automatically updates in all relevant email templates.
Row details: This includes structure, settings, and styles.
Content details: Settings and styles of individual content blocks.
Metadata: Any metadata tied to the saved row.
Prior to implementing Synced Rows, review the following prerequisites:
: Implement first, because it establishes the foundation for a row management workflow.
and : Familiarizing yourself with Edit Single Rows Mode and CSAPI will provide you with a mechanism to edit and manage synced rows, which will support your implementation workflow. However, they are not strictly necessary to implement Synced Rows.
When a row is saved with the synced
property, it becomes a “synced row.” To maintain consistency, synced rows cannot be edited within a design. Instead, they function as reference points, ensuring uniformity across all linked designs. The host app must load the row’s JSON using Single Row Edit Mode to edit synced rows. Any modifications to synced rows can be propagated to all linked designs with the help of the CSAPI’s merge-rows
and synced-rows
methods.
Unsynced saved rows, in contrast, allow for edits that don’t impact other designs. They’re ideal for making design-specific changes without influencing other designs that might share the same base row.
As previously mentioned, a synced row is a saved row designated synced
when saved. To set a row’s synced property, adjust the JSON response from the saveRow
Content Dialog.
You might need to modify the saveRow
handler from the Metadata Content Dialog step in your app’s Save Rows workflow.
If you need a refresher, check out:
Here’s a sample implementation for the Metadata Content Dialog, offering the synced row option:
The JSON returned to the builder includes the user’s input and selections from the UI. The configuration below shows the new synced row setting applied to the options argument of the resolve method.
Look for the pencil icon at the top-right of synced rows. Rows without this icon are standard saved rows. The icon provides a clear visual cue for quickly identifying and editing synced rows.
To edit a synced row, click the pencil icon. Editing options appear in the sidebar panel. Inside, you’ll find a CTA button and optional text.
The CTA button opens the editSyncedRow
Content Dialog, allowing the host application to interact with the end-user and receive their selection.
The host application has complete control over the content dialog and UX. However, the content dialog must always return a boolean value of true
or false
to trigger one of the following outcomes:
If true
, the row remains synced to disable content editing in the design before closing the dialog.
If false
, the row updates to enable editing and remove the synced property before closing the dialog.
For example, a content dialog might present users with two options:
Edit the row across all designs.
Unsync the row, turning it into a standard saved row.
The first option, to edit the row across all designs, allows users to make changes to the synced row that will be reflected in all designs that use it.
The second option, to unsync the row, converts the synced row into a standard saved row. This means that any changes made to the row will only affect the design in which it is being edited. This option is useful when the user needs to make specific changes to a single design without affecting other designs that may use the same saved row.
The user’s selection from the above example editSyncedRow
content dialog UI is returned to the builder as a boolean value. Below is an example of the editSyncedRow
configuration for the UI above. Note the boolean value false
in the resolve method unlocks the row:
A comprehensive reference of the editSyncedRow
Content Dialog settings, such as the CTA button label and optional text, can be found in our .
The following animation shows this example of edit synced rows workflow in action. We’ll dive into this process in the following sections.
Suppose a user selects “Edit and update everywhere” from the content dialog. How does the host app ensure seamless editing and synchronization of the row?
Here’s a breakdown of the typical workflow the host app adopts:
Initialization: The host app launches the Edit Single Row Mode in a new builder instance to enable editing of the synchronized row. Our is available for reference for a deeper understanding.
User edits: Users generally hit ‘Save’ to confirm their edits once they modify the synchronized row. Simultaneously, the host app can proactively track these edits using the onChange
method.
Synchronization timing: The decision on when to synchronize changes across all designs rests with the host application. Given the potential need to propagate edits to multiple designs, holding off until the user indicates their wish to exit is customary.
Initiation of synchronization: The synchronization is initiated as soon as the user signifies their satisfaction with the edits, either through the ‘Save’ or ‘Save & Exit’ options.
Redirection & Synchronizing changes: After editing a row, the host app usually performs a synchronous . The user will then be redirected to their ongoing design, where they can see their edits reflected in the synced row.
Background syncing: Given the possible existence of numerous linked designs, a background process is usually set in motion to update all other templates.
In the fifth step of the sample workflow, the goal is to bring the user back to their ongoing design with the updated content. This is achieved using the CSAPI’s merge-rows
method.
The merge-rows
method functions as a sophisticated “find and replace.”
i.e., To synchronize content, the host app forwards a request comprising the outdated template, the newly edited row, and a succinct query detailing which row(s) the API should target for replacement. The “query” is a standards-based JSON Path query typically referencing a globally unique identifier that was added to the saved row during the Metadata Content Dialog step.
For an example on how to use the merge-rows
method, visit our .
To update rows across all designs, keeping track of the templates where rows have been dropped is crucial. There are two principal methods to associate rows with templates:
Using the onChange
method
Upon adding a synced row into a design, the onChange
callback method supplies the row’s metadata. The metadata will contain the row’s guid
, which can be used to link the synced row to the guid
assigned to the template by the host app. Commonly, this is achieved by establishing an index record within the app’s database linking the template’s guid
with the row’s guid
.
Leverage the synced-rows
method
For those rows incorporated into designs before the implementation of the onChange
tracking method, CSAPI’s synced-rows
method is available. Use the synced-rows
method get a list of all the synced rows inside a template with their corresponding rowIdentifier
values. To learn more about how to use this endpoint, visit our .
The specific objectives of the host application steer the choice between these methods. Whatever the choice, the primary focus is meticulously tracking the row across all linked templates, ensuring accurate and efficient updates.
By configuring advanced permissions for Synced Rows, you can manage the visibility of and access to the Edit Synced Row toolbar button. These customization options enable you to define whether end users can:
View the Edit Synced Row button.
Click the Edit Synced Row button.
Edit Synced Rows using one of the following options:
Redirecting to the builder to edit the Synced Row, and save changes applied globally.
Converting a Synced Row to a Saved Row.
A few of the benefits of applying advanced permissions to Synced Rows are the following:
Limit who can modify synced rows to ensure centralized control.
Hide unnecessary editing actions for users who only need to reuse existing content.
Prevent accidental edits to shared content, maintaining consistency across templates.
Sure! Here's a clearer and more user-friendly version of your configuration steps, based on the code you shared:
Follow these steps to enable or customize the editSyncedRow
option in your Beefree SDK configuration:
Open your codebase and locate where you configure the Beefree SDK.
If it doesn’t already exist, add the advancedPermissions
object to your configuration.
Inside advancedPermissions
, add the following nested structure:
Set the Properties:
show
: Set to true
to display the edit button for Synced Rows, or false
to hide it.
locked
: Set to true
to make the edit button read-only, or false
to make it clickable.
Save your changes and test your implementation to confirm the desired behavior.
The following table outlines the configurable parameters for Synced Rows.
The following code snippet shows an example configuration where show
is set to true
and locked
is set to false
. In the subsequent image, you can see this configuration results in a clickable Edit Synced Row button that is visible in the toolbar.
The following image shows a clickable Edit Synced Row button in the toolbar.
The following code snippet shows an example configuration where show
is set to true
and locked
is set to true
. In the subsequent image, you can see the configuration result, which is a visible Edit Synced Row button that can't be clicked in the toolbar.
The following image shows a visible Edit Synced Row button in the toolbar, but it is not clickable.
The following code snippet shows an example configuration where show
is set to false
and locked
is set to true
. In the subsequent image, you can see this configuration results in a toolbar without the button.
The following image shows a toolbar without the Edit Synced Row button.
var beeConfig = {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
autosave: 30, // [optional, default:false]
language: 'en-US', // [optional, default:'en-US']
trackChanges: true, // [optional, default: false]
specialLinks: specialLinks, // [optional, default:[]]
mergeTags: mergeTags, // [optional, default:[]]
mergeContents: mergeContents, // [optional, default:[]]
preventClose: false, // [optional, default:false]
editorFonts : {}, // [optional, default: see description]
contentDialog : {}, // [optional, default: see description]
defaultForm : {}, // [optional, default: {}]
roleHash : "", // [optional, default: ""]
rowDisplayConditions : {}, // [optional, default: {}]
rowsConfiguration: {},
workspace: { // [optional, default: {type : 'default'}]
editSingleRow: false // [optional, default: false]},
},
commenting: false, // [optional, default: false]}
commentingThreadPreview: true, // [optional, default: true]}
commentingNotifications: true, // [optional, default: true]}
disableLinkSanitize: true, // [optional, default: false]}
loadingSpinnerDisableOnSave: false, // [optional, default: false]}
loadingSpinnerDisableOnDialog: true, // [optional, default: false]}
onSave: function(jsonFile, htmlFile) { /* Implements function for save */ }, // [optional]
onChange: function(jsonFile, response) { /* Implements function for change */ }, // [optional]
onSaveAsTemplate: function(jsonFile) { /* Implements function for save as template (only JSON file) */ }, // [optional]
onAutoSave: function(jsonFile) { /* Implements function for auto save */ }, // [optional]
onSend: function(htmlFile) { /* Implements function to send the message */ }, // [optional]
onLoad: function(jsonFile) { /* Implements function to perform an action once the template is loaded */}, // [optional]
onError: function(errorMessage) { /* Implements function to handle error messages */ }, // [optional]
onWarning: function(alertMessage) { /* Implements function to handle error messages */ }, // [optional]
debug: {
all: true, // Enables all debug features listed below
inspectJson: true, // Enables an eye icon on the module/row toolbar to inspect specific JSON portions
showTranslationKeys: true // Shows translation keys instead of localized strings
},
translations: {
'bee-common-widget-bar': {
content: 'MODULES',
},
// additional translations...
},
// other properties...
};
uid
An alphanumeric string that identifies the user and allows the SDK to load resources for that user (e.g. images).
Min length: 3 characters
Can contain letters from a to z (uppercase or lowercase), numbers and the special characters _ (underscore) and – (dash)
It is a string and not a numeric value
It uniquely identifies a user of Beefree SDK. When we say “uniquely”, we mean that:
It will be counted as a unique user for monthly billing purposes.
Images (and other files) used by the user when creating and editing messages will be associated with it and not visible to other users (when using the default storage).
container
Identifies the id of div element that contains Beefree SDK.
English:
en-US
Spanish:
es-ES
French:
fr-FR
Italian:
it-IT
Portuguese:
pt-BR
Indonesian:
id-ID
Japanese:
ja-JP
Chinese:
zh-CN
Traditional Chinese:
zh-HK
German:
de-DE
Danish:
da-DK
Swedish:
sv-SE
Polish:
pl-PL
Hungarian:
hu-HU
Russian:
ru-RU
Korean:
ko-KR
Dutch:
nl-NL
Finnish:
fi-FI
Czech:
cs-CZ
Romanian:
ro-RO
Norwegian (Bokmål):
nb-NO
Slovenian:
sl-SI
trackChanges
Track message changes in the editor via the “onChange” callback. See “Tracking message changes” for further details.
false
specialLinks
An array of custom links that may be used in the message (e.g. unsubscribe). See “extending the editor” for further details.
[]
mergeTags
An array of merge tags that may be used in the message (e.g. first name of the recipient). See “extending the editor” for further details.
[]
mergeContents
An array of content elements that may be used in the message (e.g. small blocks of HTML). See “extending the editor” for further details.
[]
preventClose
Whether an alert should be shown when the user attempts to leave the page before saving.
false
editorFonts
Customize the list of available fonts in the editor’s text toolbar and the BODY settings panel. See “Font management” for further details.
See “Font management” for the default object.
roleHash
Identifies the user role:
Minimum length is 8, maximum is 30
Alphanumerical string only: No whitespaces, no special characters such as “_” and “-“
See “Roles and permissions” for further details.
""
rowDisplayConditions
Allows for conditional statements in email messages. See “Display Conditions” for further details.
{}
workspace
Configure the initial workspace for loading the editor. Currently used for AMP content visibility. See “Workspaces” for further details.
{type : 'default'}
contentDialog
Allows to exchange data with Beefree SDK using a UI layer you control. See the “Content Dialog” page for the complete reference.
{}
defaultForm
This should contain a structure
object with the form data.
See “Passing forms to the builder” for further details.
{}
commenting
Enables commenting on content blocks and rows. See Commenting for further details.
false
commentingThreadPreview
Enables a pop-over preview on the stage for comments.
true
commentingNotifications
Enables notifications of new comments in co-editing.
true
disableLinkSanitize
Disables link validation for URLs, including telephone number or SMS to enable merge content use.
false
loadingSpinnerDisableOnSave
Controls the visibility of the builder in a loading state.
false
loadingSpinnerDisableOnDialog
Controls the visibility of the builder in a loading state.
false
contentDialog: {
saveRow: {
handler: async (resolve, reject, args) => {
// The following is psuedo code: You need to create "openMetaDataContentDialogModal".
const metadata = await openMetaDataContentDialogModal(args)
// Metadata object format:
// Example: https://docs.beefree.io/save-rows/#saved-rows-metadata
// {
// "guid": "Globally unique id to track this row",
// "name": "string",
// "category": "string",
// }
resolve(metadata, { synced: true })
}
},
},
contentDialog: {
editSyncedRow: {
label: 'Edit synced rows',
description: `This row is used in other designs.
You can decide to update all the designs or transform this single row into a regular one`,
notPermittedDescription: `This row is used in other designs.
Your plan does not permit you to edit it. Please contact your account administrator`,
handler: function (resolve, reject, args) => {
resolve(false) // the boolean will be the value of 'Label of the sidebar button that triggers the contentDialog' `synced`
// if false the row will be un-synced, if true nothing will happen.
}
}
}
advancedPermissions: {
rows: {
toolbar: {
editSyncedRow: {
show: true, // or false
locked: true, // or false
}
}
}
}
show
boolean
Controls the visibility of the Edit Synced Row button.
Default value is true
.
locked
boolean
Determines whether the Edit Synced Row button is clickable.
Default value is false
.
advancedPermissions: {
rows: {
toolbar: {
editSyncedRow: {
show: true,
locked: false,
},
},
},
},
advancedPermissions: {
rows: {
toolbar: {
editSyncedRow: {
show: true,
locked: true,
},
},
},
},
advancedPermissions: {
rows: {
toolbar: {
editSyncedRow: {
show: false,
locked: true,
},
},
},
},
name
This string will be shown in the font dropdown list. You can use the term you prefer and we suggest the usage of common font names, but you can go creative and use semantic names that fit on your application. Long strings may impact the interface, so we recommend to keep it short. The characters { } [ ] : ” / \ | ? * are invalid.
fontFamily
Describes the CSS font stack that will be applied to the final HTML. Is important that you provide at least one fallback font to ensure that the text is not displayed using an unwanted font family. Is important that you use single quote marks with the font names instead of double quotation marks to maintain a correct JSON syntax.
url
This parameter is used only when we work with web fonts. Is important that the URL points to a CSS file with the @font-face properties, and not directly to the font files. To work, the CSS must be hosted in HTTPS.
fontWeight
Adds a new option in the dropdown of the content block’s settings for title, button, paragraph, and list blocks (e.g. 100: Thin). If not defined, only Regular (400) and Bold (700) will be available.
The HTML Importer API is an API built to easily convert HTML email templates into Beefree's JSON format.
The collection ID or name
POST /v1/{collection}/html-to-json HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: text/html
Accept: */*
Content-Length: 32437
"<!DOCTYPE html>\n<html>\n <head>\n\n <!--[if gte mso 9]><xml>\n<o:OfficeDocumentSettings>\n<o:AllowPNG/>\n<o:PixelsPerInch>96</o:PixelsPerInch>\n</o:OfficeDocumentSettings>\n</xml><![endif]-->\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0 \" />\n <meta name=\"format-detection\" content=\"telephone=no\" />\n\n <!--[if !mso]>\n<!-->\n <style>\n @import url('https://content.andomoney.com/email-assets/tropiline.css');\n </style>\n <link href=\"https://content.andomoney.com/email-assets/gt_walsheim.css\" rel=\"stylesheet\" type=\"text/css\" />\n\n <!--<![endif]-->\n <style type=\"text/css\">\n body {\n margin: 0;\n padding: 0;\n -webkit-text-size-adjust: 100% !important;\n -ms-text-size-adjust: 100% !important;\n -webkit-font-smoothing: antialiased !important;\n }\n img {\n border: 0 !important;\n outline: none !important;\n }\n p {\n Margin: 0px !important;\n Padding: 0px !important;\n }\n table {\n border-collapse: collapse;\n mso-table-lspace: 0px;\n mso-table-rspace: 0px;\n }\n td,\n a,\n span {\n border-collapse: collapse;\n mso-line-height-rule: exactly;\n }\n .ExternalClass * {\n line-height: 100%;\n }\n .el_defaultlink a {\n color: inherit;\n text-decoration: none;\n }\n .el_defaultlink1 a {\n color: inherit;\n text-decoration: underline;\n }\n .em_g_img+div {\n display: none;\n }\n a[x-apple-data-detectors],\n u+.el_body a,\n #MessageViewBody a {\n color: inherit;\n text-decoration: none;\n font-size: inherit;\n font-family: inherit;\n font-weight: inherit;\n line-height: inherit;\n }\n @media only screen and (max-width:624px) {\n .el_main_table {\n width: 100% !important;\n }\n .el_wrapper {\n width: 100% !important;\n }\n .el_hide {\n display: none !important;\n }\n .el_full_img img {\n width: 100% !important;\n height: auto !important;\n }\n .el_ptop {\n padding-top: 20px !important;\n }\n .el_pbottom {\n padding-bottom: 20px !important;\n }\n .el_h30 {\n height: 30px !important;\n }\n .el_h80 {\n height: 80px !important;\n }\n u+.el_body .el_full_wrap {\n width: 100% !important;\n width: 100vw !important;\n }\n .el_aside {\n padding-left: 20px !important;\n padding-right: 20px !important;\n }\n .el_ptrl {\n padding: 20px !important;\n }\n .el_clear {\n clear: both !important;\n width: 100% !important;\n display: block !important;\n }\n .el_center {\n text-align: center !important;\n }\n }\n @media screen and (max-width:480px) {\n .el_font25 {\n font-size: 25px !important;\n line-height: 32px !important;\n }\n .el_font15 {\n font-size: 16px !important;\n line-height: 28px !important;\n }\n .el_ptop40 {\n padding-toptop: 40px !important;\n }\n .el_ptop50 {\n padding-top: 50px !important;\n }\n .el_ptop30 {\n padding-top: 30px !important;\n }\n .el_ptop60 {\n padding-top: 60px !important;\n }\n .el_ptop40 {\n padding-top: 40px !important;\n }\n }\n </style>\n </head>\n <body class=\"el_body\" style=\"margin:0px auto; padding:0px;\" bgcolor=\"#ffffff\">\n\n <!-- == Header Section == -->\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"el_full_wrap\" bgcolor=\"#ffffff\" style=\"table-layout:fixed;\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table align=\"center\" width=\"625\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"el_main_table\" style=\"width:625px; table-layout:fixed;\" bgcolor=\"#ffffff\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table width=\"625\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\" style=\"width:625px;\" class=\"el_wrapper\">\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding:20px 27px 40px 28px;\" class=\"el_ptrl\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n\n <!-- == View_online Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:12px; line-height:18px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif;\" class=\"el_defaultlink1\"><a href=\"#\" target=\"_blank\" style=\"text-decoration:underline; color:#ffffff;\"><span style=\"text-decoration:underline; color:#3a3a3a;\">View in browser</span></a></td>\n </tr>\n\n <!-- == //View_online Section == -->\n\n <!-- == Logo Section == -->\n\n <!-- == //Logo Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding:40px 15px 20px;\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"middle\" width=\"150\" style=\"width:150px;\" class=\"el_clear\">\n <table width=\"150\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"left\" class=\"el_wrapper\">\n <tr>\n <td align=\"center\" valign=\"top\" class=\"el_pbottom\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZ3d3cuYW5kb21vbmV5LmNvbSUyRg==&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2398\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://andomoney.imgus11.com/public//d7dd232a77df187d6b8e0e48756e2506.png?r=868092789\" width=\"150\" alt=\"Ando\" style=\"display:block; max-width:150px; font-size:14px; line-height:18px; color:#000000; font-family:Arial, sans-serif;\" border=\"0\" /></a></td>\n </tr>\n </table>\n </td>\n <td align=\"right\" valign=\"middle\" class=\"el_clear\"><a href=\"April 22 2021\" target=\"_blank\" style=\"text-decoration:none; color:#000000; font-family:Arial, sans-serif;\" class=\"em_defaultlink el_center el_clear\">April 22 2021</a></td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == Hero_banner Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" class=\"el_full_img el_ptop40\" style=\"padding-top:40px;\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/spinning-globe-email-hero.gif?r=1041674147\" width=\"545\" alt=\"Alt tag goes here\" style=\"display:block; max-width:545px; font-size:14px; line-height:18px; color:#ffffff; font-family:Arial, sans-serif;\" border=\"0\" /></a></td>\n </tr>\n\n <!-- == //Hero_banner Section == -->\n\n <!-- == Headline Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:38px; line-height:48px; color:#3a3a3a; text-align: -moz-center; font-family:'Tropiline', Georgia,Times New Roman,Times,serif; font-weight:500; padding-top:40px;\" class=\"el_defaultlink el_ptop40 el_font25\">Mobile Banking for a More Sustainable Tomorrow<br class=\"el_hide\" />\n </td>\n </tr>\n\n <!-- == Headline Section == -->\n\n <!-- == body_copy Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:18px; line-height:32px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; padding-top:20px; text-align: -moz-center;\" class=\"el_defaultlink el_ptop el_font15\">Still thinking about opening an Ando account? Discover how everyday banking can be a eco-friendly force for good.\n </td>\n </tr>\n\n <!-- == //body_copy Section == -->\n\n <!-- == Call_to_action Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:30px;\">\n <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\" width=\"170\" style=\"width:170px; min-width:170px; border-radius:32px;\" bgcolor=\"#EFCE60\">\n <tr>\n <td align=\"center\" valign=\"middle\" height=\"54\" style=\"font-size:14px; color:#000000; height:54px; font-weight:bold; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-center;\" class=\"el_defaultlink\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none; color:#000000; line-height:54px; display:block;\">Complete My Setup</a></td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //Call_to_action Section == -->\n\n <!-- == Divider Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" height=\"60\" style=\"height:60px; border-bottom:1px solid #d7d7d7;\" class=\"el_h80\"> </td>\n </tr>\n\n <!-- == Divider Section == -->\n\n <!-- == 2col_section_v1 Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:32px; line-height:48px; color:#3a3a3a; text-align: -moz-center; font-family:'Tropiline', Georgia,Times New Roman,Times,serif; font-weight:500; padding-top:40px;\" class=\"el_defaultlink el_font25\">Banking With Purpose<br class=\"el_hide\" />\n </td>\n </tr>\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:40px;\" class=\"el_ptop50\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\">\n <table width=\"100\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"left\" style=\"width:167px;\">\n <tr>\n <td align=\"left\" valign=\"top\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/html_images_/icon_no_carbon.png?r=558038507\" width=\"110\" alt=\"\" style=\"display:block; max-width:167px; font-size:14px; line-height:18px; color:#000000; padding-bottom: 20; font-family:Arial, sans-serif;\" border=\"0\" /> </a></td>\n </tr>\n </table>\n\n <!--[if gte mso 9]></td>\n<td valign=\"top\"><![endif]-->\n <table width=\"390\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"right\" style=\"width:390px;\" class=\"el_wrapper\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\" width=\"30\" style=\"width:30px;\" class=\"el_hide\"> </td>\n <td align=\"left\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:20px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:bold;\" class=\"el_defaultlink el_ptop\">Banking for Balance</td>\n </tr>\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:16px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:400; padding-top:8px;\" class=\"el_defaultlink\">Zero monthly fees, no minimum balance, and a huge fee-free ATM network¹ means sustainable banking is more sustainable for everyone.</td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //2col_section_v1 Section == -->\n\n <!-- == 2col_section_v2 Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:50px;\" class=\"el_ptop50\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\">\n <table width=\"100\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"left\" style=\"width:167px;\">\n <tr>\n <td align=\"left\" valign=\"top\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/html_images_/icon_money_fly.png?r=2142250612\" width=\"110\" alt=\"\" style=\"display:block; max-width:167px; font-size:14px; line-height:18px; color:#000000; font-family:Arial, sans-serif;\" border=\"0\" /></a></td>\n </tr>\n </table>\n\n <!--[if gte mso 9]></td>\n<td valign=\"top\"><![endif]-->\n <table width=\"390\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"right\" style=\"width:390px;\" class=\"el_wrapper\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\" width=\"30\" style=\"width:30px;\" class=\"el_hide\"> </td>\n <td align=\"left\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:20px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:bold;\" class=\"el_defaultlink el_ptop\">Banking with Clarity</td>\n </tr>\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:16px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:400; padding-top:8px;\" class=\"el_defaultlink\">Most banks use your deposits to fund fossil fuels. ²Not Ando. Our investments only support green initiatives, giving you unprecedented insights into how you’re helping to save the planet.</td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //2col_section_v2 Section == -->\n\n <!-- == 2col_section_v3 Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:50px;\" class=\"el_ptop50\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\">\n <table width=\"100\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"left\" style=\"width:167px;\">\n <tr>\n <td align=\"left\" valign=\"top\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/html_images_/icon_fdic_shield.png?r=1132411367\" width=\"88\" alt=\"Bank With Confidence\" style=\"display:block; max-width:167px; font-size:14px; line-height:18px; color:#000000; font-family:Arial, sans-serif;\" border=\"0\" /></a> </td>\n </tr>\n </table>\n\n <!--[if gte mso 9]></td>\n<td valign=\"top\"><![endif]-->\n <table width=\"390\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"right\" style=\"width:390px;\" class=\"el_wrapper\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\" width=\"30\" style=\"width:30px;\" class=\"el_hide\"> </td>\n <td align=\"left\" valign=\"top\">\n <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:20px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:bold;\" class=\"el_defaultlink el_ptop\">Bank with Confidence</td>\n </tr>\n <tr>\n <td align=\"left\" valign=\"top\" style=\"font-size:16px; line-height:26px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-left; font-weight:400; padding-top:8px;\" class=\"el_defaultlink\">Your deposits are FDIC insured up to $250,000 through Community Federal Savings Bank, member FDIC.</td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //2col_section_v3 Section == -->\n\n <!-- == Call_to_action Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:30px;\">\n <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\" width=\"170\" style=\"width:170px; min-width:170px; border-radius:32px;\" bgcolor=\"#EFCE60\">\n <tr>\n <td align=\"center\" valign=\"middle\" height=\"54\" style=\"font-size:14px; color:#000000; height:54px; font-weight:bold; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; text-align: -moz-center;\" class=\"el_defaultlink \"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZhcHAuYW5kb21vbmV5LmNvbSUyRiUyMyUyMSUyRmxvZ2lu&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2405\" target=\"_blank\" style=\"text-decoration:none; color:#000000; line-height:54px; display:block;\">Open My Account</a></td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //Call_to_action Section == -->\n\n <!-- == Divider Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" height=\"45\" style=\"height:45px; border-bottom:1px solid #d7d7d7;\" class=\"el_h50\"> </td>\n </tr>\n\n <!-- == Divider Section == -->\n\n <!-- == Footer_logo Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:40px;\" class=\"el_ptop50\">\n <table width=\"75\" style=\"min-width:75px; width:75px;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZ3d3cuYW5kb21vbmV5LmNvbSUyRg==&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2398\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://andomoney.imgus11.com/public//d7dd232a77df187d6b8e0e48756e2506.png?r=868092789\" width=\"75\" alt=\"Ando\" style=\"display:block; max-width:75px; font-size:14px; line-height:18px; color:#ffffff; font-family:Arial, sans-serif;\" border=\"0\" /></a></td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //Footer_logo Section == -->\n\n <!-- == Copyright Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:13px; line-height:18px; color:#3a3a3a; text-align: -moz-center; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; padding-top:28px; padding-left:20px; padding-right:20px;\" class=\"el_defaultlink\">© 2021 Ando Inc. All Rights Reserved.<br />\n Ando Inc., 8996 Miramar Road, Suite 310, San Diego, CA 92126, United States</td>\n </tr>\n\n <!-- == //Copyright Section == -->\n\n <!-- == Social_icon Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"padding-top:37px;\" class=\"el_ptop30\">\n <table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\" width=\"145\" style=\"min-width:145px; width:145px;\">\n <tr>\n <td align=\"center\" valign=\"middle\" style=\"padding-right:23px;\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZ3d3cuZmFjZWJvb2suY29tJTJGYW5kby5tb25leQ==&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2399\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/updated_ando/fb_grey.png?r=1464504408\" width=\"33\" alt=\"FB\" style=\"display:block; max-width:33px; font-size:14px; line-height:18px; color:#ffffff; font-family: Arial, sans-serif;\" border=\"0\" /></a></td>\n <td align=\"center\" valign=\"middle\" style=\"padding-right:23px;\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZ3d3cuaW5zdGFncmFtLmNvbSUyRmFuZG8ubW9uZXklMkY=&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2400\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/updated_ando/iconfinder_instagram_1217174.png?r=1667089082\" width=\"33\" alt=\"INSTA\" style=\"display:block; max-width:33px; font-size:14px; line-height:18px; color:#ffffff; font-family: Arial, sans-serif;\" border=\"0\" /></a></td>\n <td align=\"center\" valign=\"middle\"><a href=\"https://updates.andomoney.com/Prod/link-tracker?redirectUrl=aHR0cHMlM0ElMkYlMkZ0d2l0dGVyLmNvbSUyRmFuZG9fbW9uZXk=&a=476537907&account=andomoney%2Eactivehosted%2Ecom&email=%2Bra1JSeoBI356Y5%2FM1XmyND8bjJpCHl33qvDqYu5emM%3D&s=2ad87194132d03c99740e0ec5a8c1ada&i=311A343A5A2401\" target=\"_blank\" style=\"text-decoration:none;\"><img src=\"https://ac-image.s3.amazonaws.com/1/6/4/8/2/1/7/home/Megha%40elevated.com/updated_ando/iconfinder_twitter_1217163.png?r=2104098364\" width=\"33\" alt=\"TW\" style=\"display:block; max-width:33px; font-size:14px; line-height:18px; color:#ffffff; font-family: Arial, sans-serif;\" border=\"0\" /></a></td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- == //Social_icon Section == -->\n\n <!-- == Footer_body_copy Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:13px; line-height:23px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; padding-top:41px; text-align: -moz-center;\" class=\"el_defaultlink el_ptop30\">Banking services provided by Community Federal Savings Bank, member FDIC.<br class=\"el_hide\" />\n The Ando Visa® Debit Card is issued by Community Federal Savings Bank<br class=\"el_hide\" />\n pursuant to a license from Visa U.S.A. Inc. and may be used everywhere<br class=\"el_hide\" />\n Visa <span style=\"white-space:nowrap;\">debit cards are accepted.</span></td>\n </tr>\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:13px; line-height:23px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; padding-top:41px; text-align: -moz-center;\" class=\"el_defaultlink el_ptop30\">¹Fee-free withdrawals MoneyPass® ATMs. Out-of-Network cash withdrawal fees apply.<br /> Third-party and cash deposit fees may apply. ²Global Banks, Led by JPMorgan Chase, <br />Invested $2.7 Trillion in Fossil Fuels Since Paris Climate Pact\n <br /><br />*Global Warming Is Driving Polar Bears Toward Extinction, Researchers Say\n </td>\n </tr>\n\n <!-- == //Footer_body_copy Section == -->\n\n <!-- == Unsubscribe Section == -->\n <tr>\n <td align=\"center\" valign=\"top\" style=\"font-size:13px; line-height:22px; color:#3a3a3a; font-family:'GT Walsheim Pro', Helvetica, Arial, sans-serif; padding-top:27px; text-align: -moz-center;\" class=\"el_defaultlink1 el_ptop30\"><a href=\"#\" target=\"_blank\" style=\"text-decoration:underline; color:#3a3a3a;\"><span style=\"text-decoration:underline; color:#3a3a3a;\">Unsubscribe</span></a> | <a href=\"#\" target=\"_blank\" style=\"text-decoration:underline; color:#3a3a3a;\"><span style=\"text-decoration:underline; color:#3a3a3a;\">Send to Friend</span></a></td>\n </tr>\n\n <!-- == //Unsubscribe Section == -->\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n\n <!-- == //Header Section == -->\n \n </body>\n</html>"
{
"message": "Success"
}
Welcome to the React Quickstart Guide for embedding Beefree SDK's no-code email builder in your React application.
This Quickstart Guide shows you step by step how to embed Beefree SDK’s Email Builder into a React application using the /loginV2
authorization process. By the end of the guide, you'll have a functional React app running locally, with Beefree SDK's no-code email builder integrated and properly authenticated—following best practices for React development.
Prior to getting started, ensure you:
Understand the React framework and what it is.
Have a Beefree SDK account.
Create an application within the Developer Console.
Obtain your Client ID and Client Secret.
Throughout this guide, you'll learn how to:
Create a React app
Install Beefree SDK in the React app
Successfully complete the authorization process using /loginV2
Initialize the builder
Run the React app and the builder
First, set up a React app with TypeScript. Navigate to your terminal and run the following commands to create a React app with TypeScript. In the following example, the app is called beefree-demo. After creating the app, navigate to its directory.
npx create-react-app beefree-demo --template typescript
cd beefree-demo
npm start
Run the following command in your terminal to install the official Beefree SDK npm package.
npm install @beefree.io/sdk
Now that the package is installed, the next step is to create a simple user interface (UI) to embed the builder within.
The simple UI for this step is creating a "Read the Docs" Button with a link to the docs site. This serves as a simple visual to see the contrast between the application and builder UI once the app is running locally.
Copy and paste the code below in your App.tsx
file to modify it to include a button linking to Beefree SDK's docs. You can use any url you'd like to experiment with this locally, simply replace href="https://docs.beefree.io/beefree-sdk"
in the code below with your preferred url.
App.tsx
import React from 'react';
import './App.css';
function DocsButton() {
return (
<a
href="https://docs.beefree.io/beefree-sdk"
target="_blank"
rel="noopener noreferrer"
>
<button style={{ padding: '10px 20px', fontSize: '16px' }}>
Read the Docs
</button>
</a>
);
}
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Welcome to My Beefree Demo</h1>
<DocsButton />
</header>
</div>
);
}
export default App;
This code uses React concepts that are important to understand. The key React concepts used in the code are the following:
DocsButton
is a functional component—a reusable UI piece.
React renders components in a tree structure (App
→ DocsButton
).
Create src/BeefreeEditor.tsx
to initialize the SDK. Navigate to your src
directory and add a new file called BeefreeEditor.tsx
. Copy and paste the following code in this file. This code sets up the Beefree SDK builder component within the React app.
BeefreeEditor.tsx
Codeimport { useEffect, useRef } from 'react';
import BeefreeSDK from '@beefree.io/sdk';
export default function BeefreeEditor() {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
async function initializeEditor() {
// Beefree SDK configuration
const beeConfig = {
container: 'beefree-container',
language: 'en-US',
onSave: (json: any, html: string) => {
console.log('Saved!', { json, html });
},
onError: (error: any) => {
console.error('Error:', error);
}
};
// Get a token from your backend
const token = await fetch('http://localhost:3001/proxy/bee-auth', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ uid: 'demo-user' })
}).then(res => res.json());
// Initialize the editor
const bee = new BeefreeSDK(token);
bee.start(beeConfig, {});
}
initializeEditor();
}, []);
return (
<div
id="beefree-container"
ref={containerRef}
style={{
height: '600px', // Larger container
width: '90%',
margin: '20px auto',
border: '1px solid #ddd',
borderRadius: '8px'
}}
/>
);
}
In the code above code, there are a few concepts related to both React and Beefree SDK that are important to be aware of for successfully launching your local environment. These concepts are the following:
The following section discusses these concepts thoroughly.
Beefree SDK requires that you create a configuration object in order to initialize and load the builder within your application. In the following code, beeConfig
represents this. While there are several optional Configuration Parameters you can add to your configuration object to customize the builder for your application, there is only one mandatory parameter to successfully launch the Beefree SDK. This is the container
parameter, which must always be included.
useEffect(() => {
async function initializeEditor() {
// Beefree SDK configuration
const beeConfig = {
container: 'beefree-container',
language: 'en-US',
onSave: (json: any, html: string) => {
console.log('Saved!', { json, html });
},
onError: (error: any) => {
console.error('Error:', error);
}
};
useRef
const containerRef = useRef<HTMLDivElement>(null)
creates a reference to a DOM element.
The <div id="bee-plugin-container">
is where Beefree SDK mounts the editor.
useEffect
ensures initialization only runs once (on component mount).
React → Backend (/proxy/bee-auth
) → Beefree (loginV2
).
Beefree SDK returns a token, passed to new BeefreeSDK(token)
.
onSave
: Called when a user saves, returning JSON
(template structure) and HTML
(rendered output).
onError
: Handles errors (e.g., token expiration).
Create proxy-server.js
in the root directory. Copy and paste the code in the following section into the proxy-server.js
file in the root directory. The following code is responsible for a very important part of running Beefree SDK within your React app, which is authentication and successfully completing the authorization process. Beefree SDK requires that you pass a Client ID
, Client Secret
, and UID
on the server-side to successfully complete the authorization process. The following code shows an example of how you can use the /loginV2
to complete this.
proxy-server.js
const express = require('express');
const cors = require('cors');
const axios = require('axios');
const app = express();
const PORT = 3001;
app.use(cors());
app.use(express.json());
// Replace with your Beefree credentials
const BEE_CLIENT_ID = 'YOUR_CLIENT_ID';
const BEE_CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
// V2 Auth Endpoint
app.post('/proxy/bee-auth', async (req, res) => {
try {
const { uid } = req.body;
const response = await axios.post(
'https://auth.getbee.io/loginV2',
{
client_id: BEE_CLIENT_ID,
client_secret: BEE_CLIENT_SECRET,
uid: uid || 'demo-user'
},
{ headers: { 'Content-Type': 'application/json' } }
);
res.json(response.data);
} catch (error) {
console.error('Auth error:', error.message);
res.status(500).json({ error: 'Failed to authenticate' });
}
});
app.listen(PORT, () => {
console.log(`Proxy server running on http://localhost:${PORT}`);
});
Once the authorization process is complete, it is important to run the proxy sever prior to launching the frontend. Run the following commands in your terminal to complete this step.
npm install express cors axios
node proxy-server.js
App.tsx
to Include the EditorNow that the Beefree SDK editor component is set up and so is the proxy server, the App.tsx
file can be updated to include the Beefree SDK builder. Copy and paste the following code into the App.tsx
file to update it accordingly.
import React from 'react';
import './App.css';
import BeefreeEditor from './BeefreeEditor';
function DocsButton() {
return (
<a
href="https://docs.beefree.io/beefree-sdk"
target="_blank"
rel="noopener noreferrer"
>
<button style={{ padding: '10px 20px', fontSize: '16px' }}>
Read the Docs
</button>
</a>
);
}
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Welcome to My Beefree Demo</h1>
<DocsButton />
<BeefreeEditor />
</header>
</div>
);
}
export default App;
The final step is to run the application. Keep in mind that the proxy server needs to run in its own terminal, while the application runs in a separate terminal.
The terminal commands for running the application and proxy server are the following:
Terminal 1 (React):
npm start
Terminal 2 (Proxy):
node proxy-server.js
Now you can visit http://localhost:3000 and start experimenting with your new React application with Beefree SDK embedded. The following image shows what the final result should look like:
Now you have a functional React app running locally, with Beefree SDK's no-code email builder integrated and properly authenticated—following best practices for React development.
Remember the following core concepts covered throughout this guide to easily integrate Beefree SDK into your React application:
React Components: Reusable UI (e.g., DocsButton
, BeefreeEditor
).
Beefree SDK: Loads in a useRef
container, with callbacks for save/error
.
V2 Auth: Securely handles tokens via a proxy server.
Proxy Server: Must be in the root directory (proxy-server.js
).
Beefree SDK is highly customizable. Now that you have a React application running locally on your machine with the Beefree SDK Email Builder embedded, you can start experimenting with customizing the UI of the email of the builder.
A few common customizations you can easily apply to your beeConfig
object to continue experimenting are the following:
Custom Languages and overriding default text
const beeConfig = {
container: 'beefree-container',
translations: {
'bee-common-top-bar': {
'actions': 'Design Management',
'send-test': 'Test your design',
'help': 'Need support? Contact us.',
'preview': 'View your masterpiece',
'save': 'Save changes',
'save-as-template': 'Download your design',
'show-structure': 'Show outline',
},
},
{
// ...
defaultModulesOrder: [
'Button',
'Html',
'Icons',
'Video',
],
// ...
}
modulesGroups: [
{
label: "Text ✏️",
collapsable: false,
collapsedOnLoad: false,
modulesNames: [
"List",
"Paragraph",
"Heading"
]
},
{
label: "Media",
collapsable: true,
collapsedOnLoad: false,
modulesNames: [
"Video",
"Image"
]
},
{
label: "AddOns",
collapsable: true,
collapsedOnLoad: true,
modulesNames: [
"Stickers",
"Gifs"
]
}
]
var beeConfig = {
sidebarPosition: 'right',
...
Explore the technical documentation to learn more about the other customization options within Beefree SDK.
Learn more about the Content Services API offering in Beefree SDK.
Beefree SDK includes a comprehensive API offering designed to expand upon the builder's capabilities. By leveraging Beefree SDK's APIs, you can extend the builder's functionality into other aspects of your application.
Beefree SDK's API offering includes three APIs. They are the following:
This section of the documentation discusses the , which includes resources for exporting, converting, processing, and styling templates within Beefree SDK. This collection of resources extends the functionality of the builder to offer your end users a complete content creation solution.
The Content Services API is a -based API that enables Beefree SDK integrators to programmatically manipulate template JSON. It is built to follow predictable resource url patterns, and to utilize standard HTTP response codes and methods.
Beefree SDK requires that you prior to accessing the Content Services API's resources. You can generate API keys for both production and . API keys associated with development applications are intended for pre-production environments and endpoint testing. They should not be used in production environments.
There are five categories of resources within the Content Services API. Each of these categories includes a group of endpoints with resources to support various workflows.
These categories are the following:
Export: Services that allow users to extract content into various formats (such as HTML, PDF, or image files), making it easy to repurpose or distribute designs across different platforms.
Convert: Tools that transform content from one format to another (for example, converting template JSON to HTML ). This enables compatibility with different systems and workflows.
AI Collection: AI-powered capabilities for text generation, such as creating metadata for emails, summarizing content, or creating SMS messages.
Row Processing: Services that operate at the structural level, such as analyzing, modifying, or extracting specific rows or sections within a design for granular control over the content layout.
Brand Style: Resources focused on enforcing or applying brand guidelines, including applying consistent colors, typography, and spacing rules to ensure brand integrity across all generated content.
Check: Perform checks on email, page, and row content. Report design feedback to end users.
The following diagram displays each of the five categories within the Content Services API, and their corresponding resources.
This section provides a high level overview of the Content Services API's capabilities, and lists a few scenarios in which this API is particularly helpful.
One of the most common use cases for the Content Services API is exporting different format types. Once your end users complete their designs within the no-code builder, they'll want to export their designs and distribute them. That is where the stands out. By using this category of endpoints, you can provide your end users with the option to export their no-code designs in HTML, plain text, PDF, or image formats.
Your end users may want to export their templates into various formats in the following scenarios:
HTML: For sending email campaigns, publishing landing pages, or embedding popups.
Plain Text: For accessibility, compatibility with text-only email clients, improved deliverability, and compliance with communication regulations.
PDF: For attaching designs to emails, SMS, WhatsApp, printing hard copies, or creating flyers, while preserving the design's layout.
Image: For creating visual galleries, dashboards, social media posts, internal presentations, or campaign planning visuals.
Another common use case of the Content Services API is converting one format to another. The formats in the Convert category differ from those in the Export category, and serve a separate purpose. This category of endpoints is for creating designs and loading them within the builder.
These endpoints allow you to:
Page to Email: Convert existing page templates into email templates. This saves your end users time by allowing them to use their favorite designs across multiple content channels.
Email to Page: Convert existing email templates into page templates. This saves your end users time by allowing them to use their favorite designs across multiple content channels.
Simple to Full JSON: Convert an into full Beefree JSON that can be loaded within the builder for your end users to edit.
This category of endpoints requires that you configure an AI Provider within the . Through the integration with your AI Provider, these endpoints generate the following supporting details for your end users templates:
SMS: Generates concise text versions (e.g., promotional SMS).
Metadata: Generates subject lines and preheaders based on a template's content.
Summary: Generate summaries based on a template's content.
These endpoints manage rows within templates to maintain consistency and reduce redundancy:
Index: List saved rows available.
Merge: Merge row updates across multiple templates. Particularly useful when applying global updates.
Synced Rows: Retrieve a list of synced rows available.
Brand consistency can be enforced or retroactively applied across templates:
/templates and /rows endpoints allow updating visual properties (colors, fonts, spacings, etc.) across multiple templates or rows based on defined brand styles.
The Check group of endpoints enables you to provide content feedback to your end users directly within the builder. With the Check endpoints, you can inform your end users when their emails, pages, or rows are missing valuable information (for example, links for Calls-to-Action), before they export their designs.
You can use these endpoints to provide feedback on:
Email designs
Page designs
Rows within designs
Learn more about all the available checks in the .
All API access is over HTTPS, and accessed from the following URL:
You can reference each resource and its corresponding collection options in the following section.
The following tables list the available collection options for resources within the category.
The following table lists the resources available in this category of endpoints and their corresponding collection options.
The following table lists the resources available in this category of endpoints and their corresponding collection options.
The following table lists the resources available in this category of endpoints and their corresponding collection options.
The following table lists the resources available in this category of endpoints and their corresponding collection options.
The following table lists the resources available in this category of endpoints and their corresponding collection options.
The following table lists the resources available in this category of endpoints and their corresponding collection option.
The following table provides a few examples of URLs you can reference as an example for making specific types of requests.
API requests rate limits exist independently of API key’s monthly usage allowance.
By default, the API has the following rate limits:
Per minute: 500 requests
Per second: 100 requests
X-Rate-Limit: An integer representing the total number of requests available per cycle. Exceeding the limit per cycle results in a 429 error. (e.g. 500)
X-Rate-Limit-Remaining: An integer representing the number of remaining requests before the next cycle begins, and the count resets. (e.g. 100)
X-Rate-Limit-Reset: A Unix timestamp representing the time the next cycle will begin, and the count will reset.
Retry-After: A Unix timestamp representing the time the application may resume submitting requests.
To stay within the default limits and ensure reliable delivery, the following practices are recommended. These not only help distribute traffic more evenly but also provide resilience against transient network issues:
Monitor rate limit headers and handle 429 responses gracefully.
Response metadata indicates remaining capacity and reset timing. When receiving a 429 Too Many Requests
, it’s best to pause requests and retry after the time specified in the Retry-After
header.
Use exponential backoff. On retries, apply an exponentially increasing delay with a small random variation. This helps prevent synchronized retry storms that can worsen congestion.
Throttle traffic using a queue. In applications that generate burst traffic or scale horizontally, a request queue with rate-based throttling can smooth spikes and prevent exceeding per-second or per-minute thresholds.
Debounce high-frequency updates. Debouncing can be especially effective in scenarios like autosaving. For example, it's not typically necessary to request new HTML after every change.
Cache repeated GET requests.
Short-lived caching for frequently accessed data helps reduce redundant requests and conserves rate limit capacity.
Monitor usage patterns. Set up alerting for repeated 429 errors to catch rate limit issues early. Monitoring request patterns can also help anticipate scale needs.
Reference the answers to the most frequently asked questions in this section.
The Content Services API allows you to carry out a number of useful tasks, like converting an email or a page into a thumbnail image or a PDF document, or updating a footer into all the emails that use it (for example, a ).
These tasks consume resources in our Amazon Web Services environment, so we have to account for that. We did extensive research to define pricing that is consistent with other APIs.
Here is a quick summary:
An additional charge, CSAPI, will be added to your current subscription plan invoice. When you activate the Content Services API, your billing statement will change, and you'll notice a new line item on your Beefree SDK invoice for the service.
The Content Services API is provided as a component for your current subscription and the charges will be applied to the subscription payment method. Currently, there is no option to use an alternative payment method specific to these charges.
API requests rate limits exist independently of any API key’s monthly usage allowance.
The API has the following rate limits:
Per minute: 500 requests
Per second: 100 requests
Use this endpoint to transform a design's HTML into an Image, which can be used for thumbnails and similar purposes. Compatible with Email and Page builder.
The collection ID or name
A string field for file_type
A string field for size
A string field for html
POST /v1/{collection}/image HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 37420
{
"file_type": "png",
"size": "1000",
"html": "<!DOCTYPE html>\r\n<html lang=\"en\" xmlns:v=\"urn:schemas-microsoft-com:vml\">\r\n <head></head>\r\n <head>\r\n <meta charset=\"utf-8\">\r\n <meta name=\"x-apple-disable-message-reformatting\">\r\n <meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n <meta name=\"format-detection\" content=\"telephone=no, date=no, address=no, email=no\">\r\n <meta name=\"color-scheme\" content=\"light dark\">\r\n <meta name=\"supported-color-schemes\" content=\"light dark\">\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t<noscript>\r\n\t\t\t\t\t\t\t\t\t\t<xml>\r\n\t\t\t\t\t\t\t\t\t\t\t<o:OfficeDocumentSettings\r\n\t\t\t\t\t\t\t\t\t\t\t\txmlns:o=\"urn:schemas-microsoft-com:office:office\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<o:PixelsPerInch>96</o:PixelsPerInch>\r\n\t\t\t\t\t\t\t\t\t\t\t</o:OfficeDocumentSettings>\r\n\t\t\t\t\t\t\t\t\t\t</xml>\r\n\t\t\t\t\t\t\t\t\t</noscript>\r\n\t\t\t\t\t\t\t\t\t<style>\r\n td,th,div,p,a,h1,h2,h3,h4,h5,h6 {font-family: \"Segoe UI\", sans-serif; mso-line-height-rule: exactly;}\r\n </style>\r\n\t\t\t\t\t\t\t\t\t<![endif]-->\r\n <title>Black Friday Booster 50% OFF</title>\r\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\r\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin=\"\">\r\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap\" rel=\"stylesheet\" media=\"screen\">\r\n <style>\r\n .hover-bg-cool-gray-100:hover {\r\n background-color: #f7f8fa !important;\r\n }\r\n\r\n .hover-bg-primary-600:hover {\r\n background-color: #003cdf !important;\r\n }\r\n\r\n .hover-text-cool-gray-600:hover {\r\n color: #585e83 !important;\r\n }\r\n\r\n @media (max-width: 648px) {\r\n .sm-block {\r\n display: block !important;\r\n }\r\n\r\n .sm-hidden {\r\n display: none !important;\r\n }\r\n\r\n .sm-h-px {\r\n height: 1px !important;\r\n }\r\n\r\n .sm-w-full {\r\n width: 100% !important;\r\n }\r\n\r\n .sm-py-12 {\r\n padding-top: 12px !important;\r\n padding-bottom: 12px !important;\r\n }\r\n\r\n .sm-px-0 {\r\n padding-left: 0 !important;\r\n padding-right: 0 !important;\r\n }\r\n\r\n .sm-px-24 {\r\n padding-left: 24px !important;\r\n padding-right: 24px !important;\r\n }\r\n\r\n .sm-pb-12 {\r\n padding-bottom: 12px !important;\r\n }\r\n\r\n .sm-text-center {\r\n text-align: center !important;\r\n }\r\n\r\n .sm-text-4xl {\r\n font-size: 36px !important;\r\n }\r\n\r\n .sm-leading-16 {\r\n line-height: 16px !important;\r\n }\r\n\r\n .sm-leading-2 {\r\n line-height: 2px !important;\r\n }\r\n\r\n .sm-leading-40 {\r\n line-height: 40px !important;\r\n }\r\n }\r\n\r\n @media (prefers-color-scheme: dark) {\r\n .dark-border-gray-600 {\r\n border-color: #272727 !important;\r\n }\r\n\r\n .dark-bg-gray-800 {\r\n background-color: #1e1e1e !important;\r\n }\r\n\r\n .dark-bg-gray-900 {\r\n background-color: #121212 !important;\r\n }\r\n\r\n .dark-bg-white {\r\n background-color: #ffffff !important;\r\n }\r\n\r\n .dark-bg-gray-600 {\r\n background-color: #272727 !important;\r\n }\r\n\r\n .dark-bg-gray-700 {\r\n background-color: #222222 !important;\r\n }\r\n\r\n .dark-bg-gray-500 {\r\n background-color: #2d2d2d !important;\r\n }\r\n\r\n .dark-text-gray-200 {\r\n color: #ababab !important;\r\n }\r\n\r\n .dark-text-gray-800 {\r\n color: #1e1e1e !important;\r\n }\r\n\r\n .dark-text-gray-900 {\r\n color: #121212 !important;\r\n }\r\n\r\n .dark-text-gray-50 {\r\n color: #f9fafb !important;\r\n }\r\n\r\n .dark-text-primary-500 {\r\n color: #0047ff !important;\r\n }\r\n\r\n .dark-hover-bg-gray-50:hover {\r\n background-color: #f9fafb !important;\r\n }\r\n\r\n .dark-hover-text-gray-100:hover {\r\n color: #d5d5d5 !important;\r\n }\r\n }\r\n </style>\r\n </head>\r\n <body class=\"dark-bg-gray-900\" style=\"margin: 0; width: 100%; padding: 0; word-break: break-word; -webkit-font-smoothing: antialiased; background-color: #f7f8fa;\">\r\n <div role=\"article\" aria-roledescription=\"email\" aria-label=\"Black Friday Booster 50% OFF\" lang=\"en\" style=\"font-size: 16px; font-size: 1rem; font-size: max(16px, 1rem)\">\r\n <table style=\"width: 100%; font-family: 'Inter', -apple-system, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td align=\"center\">\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<v:rect\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\txmlns:v=\"urn:schemas-microsoft-com:vml\" fill=\"true\" stroke=\"false\" style=\"height:300px; mso-width-percent: 1000; position: absolute; left: -10px; top: -20px; z-index: -1;\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<v:fill type=\"tile\" color=\"#dee2e9\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<v:textbox inset=\"0,0,0,0\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n <div style=\"max-height: 40px;\">\r\n <div class=\"dark-bg-gray-900\" style=\"height: 300px; background-color: #dee2e9;\"></div>\r\n </div>\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</v:textbox>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</v:rect>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n <table class=\"sm-w-full\" style=\"position: relative; max-height: 0; width: 568px; opacity: 0.999;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"vertical-align: top;\" valign=\"top\">\r\n <div class=\"sm-px-24\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-px-24\" style=\"padding-left: 40px; padding-right: 40px;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td>\r\n <a href=\"https://example.com\" style=\"text-decoration: none;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/logo-dark_2x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/logo_2x.png\" width=\"88\" alt=\"Company Logo\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </a>\r\n </td>\r\n <td align=\"right\">\r\n <a href=\"https://example.com\" class=\"dark-text-gray-900 dark-bg-white hover-bg-cool-gray-100\" style=\"display: inline-block; border-radius: 8px; background-color: #ffffff; padding: 7px 12px; text-align: center; font-size: 12px; font-weight: 700; color: #191847; text-decoration: none; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.06), 0px 1px 3px rgba(0, 0, 0, 0.1);\">\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i style=\"letter-spacing: 24px; mso-font-width: -100%; mso-text-raise: 30px;\"> </i>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n <span style=\"mso-text-raise: 15px; margin-right: 6px;\"> Shop\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i style=\"letter-spacing: 6px; mso-font-width: -100%;\"> </i>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </span>\r\n <span style=\"mso-text-raise: 10px;\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/cart_2x.png\" width=\"18\"></span>\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i style=\"letter-spacing: 24px; mso-font-width: -100%;\"> </i>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </a>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n <div role=\"separator\" style=\"line-height: 40px;\">‌</div>\r\n <table class=\"dark-bg-gray-600\" style=\"width: 100%; border-radius: 8px; background-color: #ffffff; box-shadow: 0px 10px 10px -5px rgba(0, 0, 0, 0.04), 0px 20px 25px -5px rgba(0, 0, 0, 0.1);\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-px-24\" style=\"padding: 40px;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td>\r\n <div>\r\n <a href=\"https://example.com\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/hero/black-friday.png\" width=\"488\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\" alt=\"\">\r\n </a>\r\n </div>\r\n <div role=\"separator\" style=\"line-height: 24px;\">‌</div>\r\n <h2 class=\"sm-text-4xl dark-text-gray-50\" style=\"margin: 0; font-size: 60px; font-weight: 700; line-height: 1; letter-spacing: -0.025em; color: #191847;\"> Black Friday <br class=\"sm-hidden\"> Booster <br>\r\n <span style=\"font-family: -apple-system-ui-serif, ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; font-weight: 400; font-style: italic;\">50% OFF</span>\r\n </h2>\r\n <div role=\"separator\" style=\"line-height: 24px;\">‌</div>\r\n <p class=\"dark-text-gray-50\" style=\"margin: 0; font-size: 16px; line-height: 26px; color: #191847;\"> Hi Smiles Davis, <br>\r\n <br> This Black Friday, we’re offering loyal [Product Name] customers like you the chance to take advantage of our entire range of Teams services for only HALF the usual price. <br>\r\n <br> For <strong>$XX / month</strong>, you can upgrade your experience to include all these great benefits:\r\n </p>\r\n </td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 24px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-border-gray-600 dark-bg-gray-700 dark-text-gray-50\" style=\"border-radius: 8px; border: 1px solid #dee2e9; background-color: #f7f8fa; padding: 24px; color: #191847;\">\r\n <h3 style=\"margin: 0; font-size: 12px; font-weight: 700;\"> Free Plan <em class=\"dark-text-gray-200\" style=\"font-weight: 400; color: #424670;\">(Currently 15 Members)</em>\r\n </h3>\r\n <div role=\"separator\" style=\"line-height: 4px;\">‌</div>\r\n <p style=\"margin: 0; font-size: 18px; font-weight: 700; line-height: 28px;\"> $0 </p>\r\n <div role=\"separator\" style=\"line-height: 12px;\">‌</div>\r\n <p style=\"margin: 0; font-size: 14px; line-height: 21px;\"> Free Plan features include: </p>\r\n <div role=\"separator\" style=\"line-height: 12px;\">‌</div>\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-w-full sm-block sm-pb-12\" style=\"width: 50%;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 12px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n </table>\r\n </td>\r\n <td class=\"sm-w-full sm-block\" style=\"width: 50%;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 12px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 24px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-border-gray-600 dark-bg-gray-500 dark-text-gray-50\" style=\"border-radius: 8px; border: 1px solid #dee2e9; background-color: #ffffff; padding: 24px; color: #191847;\">\r\n <h3 style=\"margin: 0; font-size: 12px; font-weight: 700;\"> Team Plan </h3>\r\n <div role=\"separator\" style=\"line-height: 4px;\">‌</div>\r\n <p style=\"margin: 0; font-size: 18px; font-weight: 700; line-height: 28px;\"> $7 monthly </p>\r\n <div role=\"separator\" style=\"line-height: 12px;\">‌</div>\r\n <p style=\"margin: 0; font-size: 14px; line-height: 21px;\"> All features of the Free plan plus: </p>\r\n <div role=\"separator\" style=\"line-height: 12px;\">‌</div>\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-w-full sm-block sm-pb-12\" style=\"width: 50%;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 12px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n </table>\r\n </td>\r\n <td class=\"sm-w-full sm-block\" style=\"width: 50%;\">\r\n <table style=\"width: 100%;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 12px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td style=\"width: 32px;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-dark-3x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/icon-check-3x.png\" width=\"24\" alt=\"✔\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </td>\r\n <td style=\"font-size: 14px;\">[Feature name]</td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n <div role=\"separator\" style=\"line-height: 24px;\">‌</div>\r\n <a href=\"https://example.com\" class=\"sm-block dark-text-primary-500 hover-bg-primary-600 dark-bg-white dark-hover-bg-gray-50\" style=\"display: inline-block; border-radius: 8px; background-color: #0047ff; padding: 14px 24px; text-align: center; font-size: 16px; font-weight: 700; color: #ffffff; text-decoration: none; box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.06), 0px 4px 6px -1px rgba(0, 0, 0, 0.1);\">\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i style=\"letter-spacing: 24px; mso-font-width: -100%; mso-text-raise:30px;\"> </i>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n <span style=\"mso-text-raise: 15px;\">Upgrade to Team Plan</span>\r\n <!--[if mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<i style=\"letter-spacing: 24px; mso-font-width: -100%;\"> </i>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </a>\r\n <div role=\"separator\" style=\"line-height: 16px;\">‌</div>\r\n <p class=\"dark-text-gray-200 sm-text-center\" style=\"margin: 0; font-size: 12px; line-height: 16px; color: #767e9d;\"> Upgrade and save 50% today. </p>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n <tr role=\"separator\">\r\n <td style=\"line-height: 24px;\">‌</td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <p class=\"dark-text-gray-50\" style=\"margin: 0; font-size: 16px; line-height: 26px; color: #191847;\"> But act fast — this deal is for a limited time only! </p>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r\n </td>\r\n </tr>\r\n </table>\r\n <div class=\"sm-leading-40\" role=\"separator\" style=\"line-height: 64px;\">‌</div>\r\n <table class=\"sm-w-full dark-text-gray-200\" style=\"width: 568px; color: #767e9d;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td style=\"padding-left: 40px; padding-right: 40px;\">\r\n <a href=\"https://example.com\" style=\"text-decoration: none;\">\r\n <picture>\r\n <source srcset=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/logo-footer-dark_2x.png\" media=\"(prefers-color-scheme: dark)\">\r\n <img src=\"https://res.cloudinary.com/dxa66e5ic/image/upload/v1637601683/holidays/logo-footer_2x.png\" width=\"79\" alt=\"Company Logo\" style=\"max-width: 100%; vertical-align: middle; line-height: 100%; border: 0;\">\r\n </picture>\r\n </a>\r\n <div role=\"separator\" style=\"line-height: 16px;\">‌</div>\r\n <table class=\"sm-w-full\" style=\"font-size: 12px; line-height: 16px;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Shop </a>\r\n </td>\r\n <td class=\"sm-block sm-py-12 sm-px-0\" style=\"padding-left: 12px; padding-right: 12px;\">\r\n <table class=\"sm-hidden\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-bg-gray-800\" style=\"height: 24px; width: 1px; background-color: #dee2e9;\"></td>\r\n </tr>\r\n </table>\r\n <!--[if !mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-->\r\n <div class=\"sm-block sm-h-px dark-bg-gray-800\" style=\"mso-hide: all; display: none; background-color: #dee2e9;\"></div>\r\n <!--\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </td>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://twitter.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Twitter </a>\r\n </td>\r\n <td class=\"sm-block sm-py-12 sm-px-0\" style=\"padding-left: 12px; padding-right: 12px;\">\r\n <table class=\"sm-hidden\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-bg-gray-800\" style=\"height: 24px; width: 1px; background-color: #dee2e9;\"></td>\r\n </tr>\r\n </table>\r\n <!--[if !mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-->\r\n <div class=\"sm-block sm-h-px dark-bg-gray-800\" style=\"mso-hide: all; display: none; background-color: #dee2e9;\"></div>\r\n <!--\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </td>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://instagram.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Instagram </a>\r\n </td>\r\n </tr>\r\n </table>\r\n <hr class=\"dark-bg-gray-800 dark-text-gray-800\" style=\"margin-top: 12px; margin-bottom: 16px; height: 1px; border-width: 0px; background-color: #dee2e9; color: #dee2e9;\">\r\n <p style=\"margin: 0; font-size: 12px; line-height: 16px;\"> If you have questions or need help, don't hesitate to contact our support team! <br>\r\n <br> DEMOCO USA Inc, 4 World Trade Center, 150 Greenwich Street, 62nd Floor, New York, NY 10007, USA\r\n </p>\r\n <div class=\"sm-leading-16\" role=\"separator\" style=\"line-height: 20px;\">‌</div>\r\n <table class=\"sm-w-full\" style=\"font-size: 12px; line-height: 16px;\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Terms & conditions </a>\r\n </td>\r\n <td class=\"sm-block sm-py-12 sm-px-0\" style=\"padding-left: 12px; padding-right: 12px;\">\r\n <table class=\"sm-hidden\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-bg-gray-800\" style=\"height: 24px; width: 1px; background-color: #dee2e9;\"></td>\r\n </tr>\r\n </table>\r\n <!--[if !mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-->\r\n <div class=\"sm-block sm-h-px dark-bg-gray-800\" style=\"mso-hide: all; display: none; background-color: #dee2e9;\"></div>\r\n <!--\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </td>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Privacy policy </a>\r\n </td>\r\n <td class=\"sm-block sm-py-12 sm-px-0\" style=\"padding-left: 12px; padding-right: 12px;\">\r\n <table class=\"sm-hidden\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">\r\n <tr>\r\n <td class=\"dark-bg-gray-800\" style=\"height: 24px; width: 1px; background-color: #dee2e9;\"></td>\r\n </tr>\r\n </table>\r\n <!--[if !mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-->\r\n <div class=\"sm-block sm-h-px dark-bg-gray-800\" style=\"mso-hide: all; display: none; background-color: #dee2e9;\"></div>\r\n <!--\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </td>\r\n <td class=\"sm-block sm-w-full\">\r\n <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\"> Contact us </a>\r\n </td>\r\n <td class=\"sm-block sm-px-0 sm-py-12\" style=\"mso-hide: all; display: none; padding-left: 12px; padding-right: 12px;\">\r\n <!--[if !mso]>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<!-->\r\n <div class=\"sm-block sm-h-px dark-bg-gray-800\" style=\"mso-hide: all; display: none; background-color: #dee2e9;\"></div>\r\n <!--\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<![endif]-->\r\n </td>\r\n </tr>\r\n </table>\r\n <div class=\"sm-leading-2\" role=\"separator\" style=\"line-height: 20px;\">‌</div>\r\n <p style=\"margin: 0; font-size: 12px; line-height: 16px;\"> This message was sent to [email protected]. If you don't want to receive these emails from DEMOCO in the future, you can <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\">edit your profile</a> or <a href=\"https://example.com\" class=\"hover-text-cool-gray-600 dark-text-gray-200 dark-hover-text-gray-100\" style=\"font-weight: 700; color: #767e9d; text-decoration: none;\">unsubscribe</a>. </p>\r\n <div role=\"separator\" style=\"line-height: 40px;\">‌</div>\r\n </td>\r\n </tr>\r\n </table>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r\n </body>\r\n</html>"
}
iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
Import custom HTML into Beefree SDK
✅ Yes, see authentication instructions.
Export, convert, and style templates and rows. Use AI to generate metadata, SMS, and summaries.
✅ Yes, see authentication instructions.
Access Beefree's catalog of templates
✅ Yes, see authentication instructions.
https://api.getbee.io/v1/{collection}/{resource}
/html
/message
/page
/popup
/amp
/plain-text
/message
/pdf
/message
/page
/image
/message
/page
/page-to-email
/conversion
/email-to-page
/conversion
/simple-to-full-json
/conversion
/sms
/ai
/metadata
/ai
/summary
/ai
/merge
/message
/page
/merge-rows
/message
/page
/synced-rows
/message
/page
/merge-index
/message
/page
/brand
/template
/row
/check
/message
/page
/row
Request HTML for email
https://api.getbee.io/v1/message/html
Landing Page
Request HTML for a landing page
https://api.getbee.io/v1/page/html
Popup
Request HTML for a popup
https://api.getbee.io/v1/popup/html
AMP
Request HTML for AMP
https://api.getbee.io/v1/amp/html
Essentials
15,000
$0.01
Core
50,000
$0.01
Superpowers
250,000
$0.003
Enterprise
Custom
Custom
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.
Important: This guide includes sample code snippets from a simple self-hosted saved rows implementation. You can reference the code for this sample integration in this GitHub repository. As you read along in this tutorial, you can copy, edit, and customize the sample code for your own use and experimentation.
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
Before writing any code changes, ensure you first activate the Self-hosted on your own infrastructure toggle in your Beefree SDK developer console account. This global setting tells Beefree SDK that your application will handle:
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.
This is in contrast to the other toggle in the Saved Rows section of the Application Configurations within the Developer console, Hosted Saved Rows, which automatically provides a user interface for end user actions and stores row data.
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:
Log in to the Developer Console.
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.
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.
// Define the type for the client configuration
type ClientConfig = {
uid: string; // Unique client identifier
container: string; // DOM element where the editor will mount
language: string;
saveRows: boolean;
hooks: {
// Custom hook to retrieve saved rows from your backend
getRows: { handler: (resolve: Function, reject: Function, args: any) => void };
};
rowsConfiguration: {
emptyRows: boolean;
defaultRows: boolean;
// Array of external content URLs dynamically generated based on categories
externalContentURLs: Array<{
name: string;
value: string;
handle: string;
behaviors: { canEdit: boolean; canDelete: boolean };
}>;
};
};
// Set up the configuration object for the Beefree SDK
const beeConfig: ClientConfig = {
uid: 'your-client-uid', // Your unique client ID
container: 'bee-plugin-container', // ID of the container element
language: 'en-US',
saveRows: true,
hooks: {
// Assign your custom getRows handler here
getRows: { handler: getRowsHandler },
},
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
externalContentURLs: externalContentURLs, // This array is built based on your categories
},
};
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:
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.
// Function to show a modal for saving a new row
function showSaveRowModal(resolve, reject, args) {
// Create modal container with inline styles for positioning and appearance
const modal = document.createElement('div');
modal.style.cssText =
'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:24px;background:#fff;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.15);z-index:1000;width:320px;font-family:Arial,sans-serif;';
// Input for Row Name
const nameInput = document.createElement('input');
nameInput.placeholder = 'Row Name'; // User enters the row name
nameInput.style.cssText = 'display:block;width:100%;padding:8px;margin-bottom:16px;';
modal.appendChild(nameInput);
// Input for Category
const categoryInput = document.createElement('input');
categoryInput.placeholder = 'Category'; // User enters the category
categoryInput.style.cssText = 'display:block;width:100%;padding:8px;margin-bottom:16px;';
modal.appendChild(categoryInput);
// Save button with click handler
const saveButton = document.createElement('button');
saveButton.textContent = 'Save';
saveButton.style.marginRight = '8px';
saveButton.onclick = async () => {
// Validate inputs before proceeding
if (!nameInput.value || !categoryInput.value) {
alert('Please provide both a name and a category.');
return;
}
// Build the row data object using provided inputs
const rowData = {
metadata: {
id: args.metadata?.id || generateUniqueId(), // Use helper to generate a unique ID
name: nameInput.value,
category: categoryInput.value,
},
synced: false, // Default synced state
};
try {
await updateSavedRows(rowData); // Call function to update or create the row in the backend
resolve(rowData);
document.body.removeChild(modal);
} catch (error) {
alert('Failed to save row');
reject(error);
document.body.removeChild(modal);
}
};
modal.appendChild(saveButton);
// Cancel button to close modal without saving
const cancelButton = document.createElement('button');
cancelButton.textContent = 'Cancel';
cancelButton.onclick = () => {
reject();
document.body.removeChild(modal);
};
modal.appendChild(cancelButton);
document.body.appendChild(modal);
}
Code Snippet
The following code snippet shows an example interaction.
class SavedRowsEditor extends React.Component {
componentDidMount() {
// Fetch initial saved rows and categories from the backend
fetch(`${BASE_URL}/rows`)
.then(res => res.json())
.then(savedRows => this.setState({ savedRows }));
// Similarly, fetch categories then initialize the Beefree SDK editor
this.initializeBeeEditor();
}
// Custom handler for retrieving rows, used by Beefree SDK
getRowsHandler(resolve, reject, args) {
fetch(`${BASE_URL}/rows/${encodeURIComponent(args.handle)}`)
.then(res => res.json())
.then(rows => resolve(rows))
.catch(error => reject(error));
}
render() {
return <div id="bee-plugin-container" style={{ minHeight: '600px' }} />;
}
}
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.
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 content URLs.
function updateExternalContentURLs(categories) {
// Map each category to an external content URL object
const externalContentURLs = categories.map(category => ({
name: category,
value: `${BASE_URL}/rows/${encodeURIComponent(category)}`, // URL endpoint for the category
handle: category, // Identifier used for row management
behaviors: { canEdit: true, canDelete: true }, // Permissions for row actions
}));
return externalContentURLs;
}
Supplementary Code Snippet
The following code snippet shows an example Beefree SDK Row Configuration.
// Example snippet showing how beeConfig integrates the rows configuration
const beeConfig = {
// ...other configuration properties...
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
// External content URLs dynamically set based on current categories
externalContentURLs: updateExternalContentURLs(currentCategories),
},
// ...hooks and additional configuration...
};
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.
app.post('/rows', (req, res) => {
const rowData = req.body;
// Validate that required metadata exists
if (!rowData.metadata || !rowData.metadata.name || !rowData.metadata.category) {
return res.status(400).json({ error: 'Missing required fields.' });
}
const { id, name, category } = rowData.metadata;
const synced = rowData.synced || false;
db.run(
// Insert the new row into the database
'INSERT INTO saved_rows (id, name, category, synced, row_data) VALUES (?, ?, ?, ?, ?)',
[id || generateUniqueId(), name, category, synced, JSON.stringify(rowData)],
(err) => {
if (err) res.status(500).json({ error: err.message });
else res.json({ message: 'Row saved successfully!' });
}
);
});
Additional Context
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 this GitHub repository.
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.
// Initialize SQLite database and create the saved_rows table if it doesn't exist
db.run(`
CREATE TABLE IF NOT EXISTS saved_rows (
id TEXT PRIMARY KEY,
name TEXT,
category TEXT,
synced BOOLEAN,
row_data TEXT
)
`);
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.
componentDidMount() {
// Fetch saved rows from the backend
fetch(`${BASE_URL}/rows`)
.then(res => res.json())
.then(savedRows => this.setState({ savedRows }));
// Fetch categories and update external content URLs accordingly
fetch(`${BASE_URL}/categories`)
.then(res => res.json())
.then(categories => {
const urls = updateExternalContentURLs(categories);
this.setState({ categories, externalContentURLs: urls });
});
}
Additional Context
By establishing these fetch connections, the frontend remains dynamic and responsive. Changes in the backend are quickly reflected in the UI.
Overview and Context
Before testing your Saved Rows implementation, it's important to test each endpoint to verify that the CRUD operations work as expected. Using tools like Postman or Insomnia allows you to make API requests and ensure that both the backend and frontend are interacting correctly.
Testing Steps
In this example, this step covers testing each of the following endpoints in Insomnia.
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 user-friendly modals with Content Dialog 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 an Express backend.
Set up an SQLite database (or your preferred database) to store row data.
Connected the frontend to the backend using standard HTTP requests.
Tested your endpoints to ensure a smooth integration.
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 Beefree SDK configuration, server code, and database set up) are available in this GitHub repository. This guide shows more concise, focused snippets to help you quickly understand the implementation while leaving the complete examples for additional reference in the repository.
Custom S3 Bucket is a Beefree application configuration feature that allows you to easily connect your own Amazon Web Services S3 bucket to your Beefree application.
By leveraging this feature, you will be able to store and manage your customers’ assets without having to build a new File System Provider, but rather by providing a compliant folder structure and filling out a simple form.
Our default file system provider uses two first level folders to manage assets:
Images folder – It defines where the user’s images will be stored.
Thumbnails folder – Is used by our API to store the thumbnails of the uploaded images.
These folders can be root folders or can be part of a more complex directory structure.
A few notes and recommendations:
These folders should not be parents/children between themselves.
Their name is restricted by AWS standard naming restrictions.
For performance reasons, you should use a dedicated bucket and place these folders in the root.
As an additional configuration option, you can provide shared files to your users, something that we do in the free version of the Beefree editor at beefree.io. These images are shown to all your customers as read-only assets.
The most common use case is providing sample images for the user’s first experience with the editor. Other use cases include providing application-specific images or documents that must not be deleted by the user.
To use this option you need to set-up two additional folders:
Shared images folder – This is the folder that your users will browse through the file manager.
Shared thumbnails folder – While the user images thumbnails are created when the images are uploaded, there is no automatic thumbnail creation for shared images. You must provide your own thumbnails using these settings:
200px as max. width/height (this guarantee a correct preview in the file manager)
Name: original_image_name.ext_thumb.png (so the thumbnail for cat.jpg must be cat.jpg_thumb.png)
PNG: use only PNG as image format
This section discusses how you can configure your own custom S3 bucket within the Developer Console, and also provides an example JSON of the Permission policy.
Prior to configuring your custom S3 bucket, ensure you configure Access keys in the Developer Console.
Take the following steps to configure Access keys in the Developer Console:
Log in to the Developer Console.
Navigate to the application you'd like to configure a custom S3 bucket for.
Click the Details button for that application.
Navigate to Application configuration and click View more.
You will be redirected to Storage options.
Toggle on Configure your own S3 storage system to enable the option.
Complete the required fields.*
Click the Test S3 settings button.
*The following image shows an example of the required fields within the Developer Console for configuring your own S3 bucket:
The following JSON is of the Permissions policy assigned to the AWS user.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CustomBucket01",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::the-bucket-name"
},
{
"Sid": "CustomBucket02",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::the-bucket-name/content-path/*"
}
]
}
The URLs for accessing files in your S3 bucket vary depending on whether the "Custom URL" field is set in the Developer Console:
If "Custom URL" is empty: URLs will follow this format:
https://<bucket-name>.s3.<region>.amazonaws.com/path/to/file.png
If "Custom URL" is set (e.g., https://my-cdn/
):
URLs will be generated like this:
<custom-url>/path/to/file.png
Public Access:
For the generated URLs to work, the bucket’s permissions should allow public access to the files.
Using a CDN as "Custom URL":
If you’re using a CDN (e.g., CloudFront) in the "Custom URL" field, you can restrict the bucket's access to only the CDN. In this case, the bucket itself doesn't need to be publicly accessible, as access is controlled through the CDN.
Ensure that bucket permissions are configured appropriately based on the type of URL being generated.
You can enable the move icon for files within the File manager. This move icon allows your end users to move their files between folders, locations, and so on within the File manger. They can access the move icon directly on the file within the File manager. The move icon is a folder with an arrow pointing right inside it. End users click this icon to initiate the process of relocating the corresponding file to a new destination.
If you are using a Custom AWS S3 Bucket, take the following steps to enable this feature for your File manager.
Take the following steps to enable the Move icon for your end users:
Log in to the Developer Console.
Navigate to the application you'd like to activate it for.
Click on the Details button.
Select the View more option located under Application configuration.
Navigate to the Services section.
Toggle on the Enable moving files between folders in file manager option.
The Move file option will automatically become available for your end users.
If a file an end user trying to move or copy has the same name as an existing file, the File Manager will show a pop-up asking how to handle the conflict.
The end user will have the following options:
Cancel: For this option, nothing will happen, and the operation will be stopped.
Keep Both: This option lets them keep both files. The new file will be saved with a slightly different name, adding a number at the end. For example, if the original file is called "pizza.jpg," the new one will be named "pizza_1.jpg."
Replace: Selecting this will replace the old file with the new one, meaning the existing file will be overwritten.
These options help them decide what to do when file names clash, ensuring they have control over how their files are managed.
To implement the new Move File feature in your application, follow these steps to change your file path from the old format to the new format. This change is important because it allows the host application to enable the Move File feature within the File Manager without breaking old URLs. Here's how to make the transition:
Understand the Changes: The file paths will change from /your-path/UID/user-path/filename.jpg
to /your-path/new-internal-id/random-path/filename.jpg
. This new structure decouples the logical path you see in the File Manager from the physical path in the storage, supporting the "move file" feature. For example, you can move the file in the File Manager, and the URL will remain the same.
Activate Move Feature: Once you are onboarded, activate the Move Feature inside your SDK Console to utilize the new file paths. Follow the steps outlined in the previous section to complete this process.
Decoupling Logical and Physical Paths: The new path structure separates the logical path (what you see in the File Manager) from the physical path (where the file is stored). This allows for more flexibility and new opportunities for future features.
Enable the Move File Feature: By adopting the new path structure, you can use the Move File feature in the File Manager, which allows you to move files without changing their URLs.
Existing Paths: Existing paths are not affected. The task done was to collect paths in the new database and keep files where they are.
Newly Uploaded Files: New uploaded files will be stored using the new path structure.
Logical and Physical Path Separation: The new path structure decouples the logical path you see in the File Manager from the physical path in the storage. This supports the "move file" feature, allowing you to move files in the File Manager without changing their URLs.
Changes: The key difference between the two paths is that the new path uses a random part to enhance security and reduce predictability, making it harder for unauthorized users to guess the URLs of stored files.
By following these steps, you can ensure a smooth transition to the new file paths and take full advantage of the Move File feature in your application.
Once you have set up a compliant folder structure, you can use the form in the Beefree SDK Console to connect your application. It’s one of the available server-side configurations for your Beefree application (Application details > Open configuration > Storage options).
This is a description of the form fields and what information you will need to provide in each of them:
Custom url
The hostname – typically a CDN – that will be prefixed to resources URLs referenced in the JSONs created with BEE.
No
Bucket name
The name you assigned to the bucket when you created it.
Yes
Access key & Access secret key
You can provide AWS Root Account Credentials or IAM User Credentials (we recommend the second option for security reasons). The provided account must have read and write access to the given bucket. .
Yes
Select Region
AWS region where you created the bucket. Uses EU as the default setting.
Yes
Images Path
The relative path (from the bucket root) to the images folder described above (use “/” symbol as path delimiter).
Yes
Thumbnails Path
The relative path (from the bucket root) to the thumbnails folder described above (use “/” symbol as path delimiter).
Yes
Shared images path
The relative path (from the bucket root) to the shared images folder described above. Cannot be the bucket root (use “/” symbol as path delimiter).
No
Shared thumbnails Path
The relative path (from the bucket root) to the shared thumbnails folder described above. Cannot be the bucket root (use “/” symbol as path delimiter).
No
Important: If you change the custom URL, the new URL is immediately used for all images.
To store images and thumbnails in separate folders at the root of your S3 bucket in the Beefree SDK Developer Console, follow these steps:
Configure the Images Path
Field Name: Images path
Example Value: your-images-folder
Format: Type the folder name where images should be stored.
Example: userlist
Configure the Thumbnail Path
Field Name: Thumbnail path
Example Value: your-thumbnails-folder
Format: Type the folder name where thumbnails should be stored.
Example: usrlistthump
Configure the Shared Images Path
Field Name: Shared images path
Example Value: your-shared-images-folder
Format: Type the folder name for shared images.
Example: usersShared
Configure the Shared Thumbnails Path
Field Name: Shared thumbnails path
Example Value: your-shared-thumbnails-folder
Format: Type the folder name for shared thumbnails.
Example: usersSharedThumb
Test the Configuration
Click Test S3 settings to validate the setup.
If successful, your files will be stored in the specified root-level folders in your S3 bucket.
The following image shows an example of how to configure single folders in the bucket root inside of the Beefree SDK Developer Console.
To store images and thumbnails inside a single nested folder within your S3 bucket in the Beefree SDK Developer Console, complete the following fields using your preferred nested folder names in the correct format:
1. Images Path
Field Name: Images path
Example Value: inner/your-folder-name
Format: Use a parent folder (for example, inner/
) followed by the subfolder name where images should be stored.
Example: inner/userlist
2. Thumbnail Path
Field Name: Thumbnail path
Example Value: inner/your-thumbnail-folder-name
Format: Use a parent folder (for example, inner/
) followed by the subfolder name for thumbnails.
Example: inner/usrlistthump
3. Shared Images Path
Field Name: Shared images path
Example Value: inner/your-shared-images-folder-name
Format: Use a parent folder (for example, inner/
) followed by the subfolder name for shared images.
Example: inner/usersShared
4. Shared Thumbnails Path
Field Name: Shared thumbnails path
Example Value: inner/your-shared-thumbnails-folder-name
Format: Use a parent folder (for example, inner/
) followed by the subfolder name for shared thumbnails.
Example: inner/usersSharedThumb
The following image shows an example of how to configure a single nested folder in the bucket root inside of the Beefree SDK Developer Console.
The button will become active once all required fields have been correctly filled out. It allows you to test your settings before saving the updated configuration. We recommend that you do so before saving any changes.
If you’ve just linked your custom bucket, you may find that you need to create your own thumbnails. Thankfully, this is an easy process.
For starters, the thumbnails in the File Manager are PNG files that are resized to 200×200 px.
Here is an example of thumbnail generation with image magick:
# convert one file
convert image1.jpg -resize 200x200 image1.jpg_thumb.png
# resize many files (WARNING this command overwrite files)
mogrify -resize 200x200 myimages/*jpg
# convert many files
mogrify -format png myimages/*jpg
As a quick example, we’ll be using this custom bucket configuration:
bucket_name : my-custom-bucket
path_images : /path/to/images/
path_thumbnails : /path/to/thumbnails/
…And starting the editor with this UID:
uid : my-uid
When uploading image1.jpg
in root dir, this key will be created in the custom bucket: s3://my-custom-bucket/path/to/images/my-uid/image1.jpg
. Following that, a thumbnail will be generated with name image1.jpg_thumb.png
with key: s3://my-custom-bucket/path/to/thumbnails/my-uid/image1.jpg_thumb.png
.
And one more example:
When uploading image2.jpg
in mydir
inside the root dir, this key is created in the custom bucket: s3://my-custom-bucket/path/to/images/my-uid/mydir/image2.jpg
. Similarly to above, a thumbnail will be generated with name image2.jpg_thumb.png
with key: s3://my-custom-bucket/path/to/thumbnails/my-uid/mydir/image2.jpg_thumb.png
.
If your Beefree application is currently using the default S3 bucket, you wish to switch to your own bucket, and you have files that you want to transfer between the two, please please log into the Beefree SDK Console and submit a support ticket.
In Beefree SDK, Custom Languages allow you to accomplish two things:
Translate the default text in the builder to your preferred language.
Override the default text in the builder to your preferred text, even if you keep the same language.
Translating the default text in the builder is useful when you have diverse end users and you'd like to provide them with a builder experience that resonates with them.
Overriding the default text in the builder with your preferred text is useful when you want to customize the builder experience and apply your application's unique tone.
This page discusses how you can accomplish both use cases with Custom Languages. Keep in mind that you can utilize Custom Languages for overriding default text in the builder, even if you are not translating any of it to another language.
Before getting started, ensure you access and familiarize yourself with the beefree-sdk-assets-languages GitHub repository. This repository includes important JSON files for you to utilize to accomplish the steps outlined on this page.
Important: Familiarize yourself with the beefree-sdk-assets-lanaguges GitHub repository prior to continuing into the steps.
This section includes two examples on how to use Custom Languages based on the above scenarios.
Example One: Overriding Default Text
In the .en-US JSON file, you'll find the following section at the beginning:
{
"bee-common-top-bar": {
"actions": "Actions",
"help": "Help",
"preview": "Preview",
"save": "SAVE",
"save-as-template": "Save as template",
"show-structure": "Show structure",
},
This JSON includes the default text in the builder, which you can see in the image of the Top bar below.
By adding the translations
parameter to the beeConfig
with the following configuration, the top bar can easily be customized.
const beeConfig = {
uid: config.uid,
container: 'bee-plugin-container',
translations: {
'bee-common-top-bar': {
'actions': 'Design Management',
'send-test': 'Test your design',
'help': 'Need support? Contact us.',
'preview': 'View your masterpiece',
'save': 'Save changes',
'save-as-template': 'Download your design',
'show-structure': 'Show outline',
},
},
The following image shows how this configuration appears in the builder.
Example Two: Translating Default Text
Translating the content to another language follows the same approach. The following configuration overrides the default text with the Spanish translation.
const beeConfig = {
uid: config.uid,
container: 'bee-plugin-container',
translations: {
'bee-common-top-bar': {
'actions': 'Acciones',
'send-test': 'Enviar prueba',
'help': 'Ayuda',
'preview': 'Vista Previa',
'save': 'GUARDAR',
'save-as-template': 'Guardar como plantilla',
'show-structure': 'Mostrar estructura',
},
The following image shows the result of the configuration with the Spanish configuration.
You can override the default Beefree SDK language file by providing a URL to your own translations. This is an advanced feature and will replace all languages used by the editor with the languages defined in the custom file.
var beeConfig = {
uid: config.uid,
...
translationsUrl: 'https://www.yourdomain.com/xx-XX.json',
...
}
The easiest method to override specific text labels is to pass a JSON object in your beeConfig
, which contains the segments of the language file you want to override.
var beeConfig = {
uid: config.uid,
// additional configuration properties...
language: 'en-US',
translations: {
'bee-common-widget-bar': {
content: 'MODULES',
},
// additional translations...
},
// other properties...
};
Overriding the Help icon label in the default toolbar
var beeConfig = {
uid: config.uid,
...
translations: {
"bee-common-top-bar": {
help: "Support"
},
}
...
}
Overriding the Rows tab label in the sidebar
var beeConfig = {
uid: config.uid,
...
translations: {
"bee-common-widget-bar": {
"structure": "Catalog"
}
},
}
...
}
Overriding the Preheader
{
"translations": {
"bee-head-meta-preheader": {
"name": "New Preheader",
"placeholder": "New Enter Preheader"
}
}
}
Defining or adding a translation for "email"
The following code defines a translation object where the title for "bee-settings-details" is set to "New Email Details" specifically for the "email" field.
translations: {
"bee-settings-details": {
"title": {
"email": "New Email Details"
}
}
}
You can override the default text for the AI Writing Assistant. The following configuration sample includes the AI component and the various default text fields you can override.
const beeConfig = {
uid: config.uid,
container: 'bee-plugin-container',
translations: {
'bee-common-top-bar': {
'actions': 'Design Management',
'send-test': 'Test your design',
'help': 'Need support? Contact us.',
'preview': 'View your masterpiece',
'save': 'Save changes',
'save-as-template': 'Download your design',
'show-structure': 'Show outline',
},
'mailup-bee-common-component-ai': {
'welcome-body-title': 'Welcome to Your Design Journey',
'welcome-body-subtitle': 'Start creating stunning emails with ease.',
'welcome-example': 'Example: Explore our templates to get inspired.',
'welcome-heading-title': 'Craft Your Message',
'welcome-heading-subtitle': 'Make every word count with our tools.',
'welcome-heading-example': 'Example: Write a compelling subject line.',
'welcome-list-title': 'Key Features to Explore',
'welcome-list-subtitle': 'Discover what makes our editor unique.',
'welcome-list-example': 'Example: Drag-and-drop functionality.',
'welcome-button-title': 'Get Started Now',
'welcome-button-subtitle': 'Click to begin your design adventure.',
'welcome-button-example': 'Example: Create your first email.',
},
},
};
The following image shows the results for the overwritten default text for AI Paragraph Assistant based on the above configuration.
The following image shows the results for the overwritten default text for AI Title Assistant based on the above configuration.
The following image shows the results for the overwritten default text for AI List Assistant based on the above configuration.
The following image shows the results for the overwritten default text for AI Button Assistant based on the above configuration.
Reference the Customize Prompt Suggestions section of the AI Writing Assistant page for additional customization options and details.
The following section lists translations that correspond with Confirmation Dialogs for Rows, Columns, Modules, and the File Manager.
This list details the translations corresponding with the Delete Row Confirmation Dialog.
Title: 🆕 Delete row
confirmation-dialogs.delete-row-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Primary Button: 🆕 Delete
confirmation-dialogs.delete-button
Reference the corresponding classnames for Delete Row.
This list details the translations corresponding with the Delete Column Confirmation Dialog.
Translations Variations
Title: 🆕 Delete column
confirmation-dialogs.delete-column-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Primary Button: 🆕 Delete
confirmation-dialogs.delete-button
Reference the corresponding classnames for Delete Column.
This list details the translations corresponding with the Delete Module Confirmation Dialog.
Translations Variations
Title: 🆕 Delete module
confirmation-dialogs.delete-module-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Primary Button: 🆕 Delete
confirmation-dialogs.delete-button
Reference the corresponding classnames for Delete Module.
This list details the translations corresponding with the Hide Row on Mobile Confirmation Dialog.
Translations Variations
Title: 🆕 Hide row
confirmation-dialogs.hide-row-confirmation-title
Heading: 🆕 Are you sure you want to hide this?
confirmation-dialogs.hide-row-confirmation-heading
Reference the corresponding classnames for Hide Row on Mobile with Module Already Hidden on Desktop.
This list details the translations corresponding with the Remove Custom Display Condition Confirmation Dialog.
Translations Variations
Title: 🆕 Delete display condition
confirmation-dialogs.delete-display-condition-confirmation-title
Reference the corresponding classnames for Remove Custom Display Condition.
This list details the translations corresponding with the Confirm Delete Single File Confirmation Dialog.
Translations Variations
Title: 🆕 Delete {filename}
confirmation-dialogs.delete-file-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Primary Button: 🆕 Delete
confirmation-dialogs.delete-button
Reference the corresponding classnames for Confirm Delete Single File.
This list details the translations corresponding with the Confirm Delete Multiple Files Confirmation Dialog.
Translations Variations
Title: 🆕 Delete {count} files
confirmation-dialogs.delete-files-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Primary Button: 🆕 Delete
confirmation-dialogs.delete-button
Reference the corresponding classnames for Confirm Delete Multiple Files.
This list details the translations corresponding with the Confirm Update Existing File Confirmation Dialog.
Text Updates:
Title: 🆕 Replace {filename}
confirmation-dialogs.replace-file-confirmation-title
Secondary Button: 🆕 Keep
confirmation-dialogs.keep-button
Reference the corresponding classnames for Confirm Update Existing File.
This list details the translations corresponding with the Update Existing File Confirmation Dialog.
Translations Variations
Title: 🆕 File {filename} already exists
confirmation-dialogs.file-already-exists-title
Heading: 🆕 Do you want to replace or keep both files?
confirmation-dialogs.replace-file-confirmation-heading
Reference the corresponding classnames: Not applicable.
This list details the translations corresponding with the Move File Replace Confirmation Dialog.
Title: 🆕 File {filename} already exists
confirmation-dialogs.file-already-exists-title
Heading: 🆕 Do you want to replace or keep both files?
confirmation-dialogs.replace-file-confirmation-heading
Reference the corresponding classnames: Not applicable.
Check out our Github repository for starter language templates in all supported languages.
The Authorization Process is an important step throughout your . This steps validates your Beefree SDK credentials and provides you with a token. Take the steps outlined in this document to ensure you accurately complete the authorization process.
Beefree SDK requires the host application to pass a container parameter in the This is the only required parameters for the configuration.
The following code sample shows an example of this parameter in the .
To initialize your instance of the Beefree SDK builder, call the /loginV2
endpoint shown in the sample code below with your Client ID, Client Secret, and UID. The Client ID and Secret are available on the application details page of the . UID represents your user as described in .
Important: Do not put your Beefree SDK credentials in client-side code.
The Beefree SDK system uses OAuth2 as the authorization framework.
Reference to learn more about UID.
The following code sample displays an example JSON response.
The Beefree SDK authorization service will return a temporary access token if the authentication is successful. The client application can use the full response that contains the token to start or refresh a Beefree SDK session.
The token you receive from the authorization server should be passed to the BeePlugin.create(...) as it is. We strongly suggest not altering it in any way. Also, don’t rely on the token response's content or structure. If you do, any change to the schema could make your integration stop working.
The token expires after 5 minutes for security reasons. Beefree SDK will refresh an expired token automatically for 12 hours without re-authenticating the application. Beefree SDK will trigger the onError
callback when the token can't be refreshed automatically.
The following code sample displays an example of how to call the Beefree SDK endpoint, obtain a token, and then start it.
Ensure to call the authorization endpoint server-side to protect your credentials.
Once you obtain the token, the object is passed to Beefree SDK to set up your customization options, for example setting the editor’s language to “Spanish”.
Then, you can use Beefree SDK methods to on your page.
Beefree SDK will keep this session alive for 12 hours from the login. After 12 hours, you have to manage the token expiration, as follows:
Obtain a new token via the new authorization endpoint.
Inject the token obtained from step one via the updateToken
method. Reference examples of this in the following section.
The following code example shows how to inject the token in the current Beefree SDK instance:
The following code example displays how to get the current JSON from the expiration error:
When you set up an onError
callback you will get the error
object as a parameter.
From that object, you can grab the code
property and use it as explained in the table below.
The following code samples display how to handle the 5101 and 5102 errors.
Error management error 5101
Error management 5102
Example error response for unsupported media type Only Content-Type: application/json
is allowed.
Example error response for an invalid UID. Look at the properties of .
Example error response for invalid credentials. Obtain your credentials using the .
Example error response for disabled apps. Contact support if you encounter this error.
var config = {
container: 'string'
}
POST /loginV2 HTTP/1.1
Host: auth.getbee.io
Accept: application/json
Content-Type: application/json
{
“client_id”: YOUR_CLIENT_ID,
“client_secret”: YOUR_CLIENT_SECRET,
“uid”: uid of choice
}
{
"access_token": "...",
"v2": true
}
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
// Obtain token
var token = req.responseText;
// Call create method and pass token and beeConfig to obtain an instance of Beefree SDK
BeePlugin.create(token, beeConfig, function(beePluginInstance) {
// Call start method of beefree SDK instance
beePluginInstance.start(template); // template is the JSON to be loaded in BEE
});
}
};
// This is a sample call to YOUR server-side application that calls the loginV2 endpoint on BEE the side
req.open(
'POST', // Method
'/YOUR_BACKEND_TOKEN_ENDPOINT', // your server endpoint
false // sync request
);
// obtain a new token with a new LoginV2 call
// update the token in the current Beefree SDK instance
beePluginInstance.updateToken(token);
onError: function (error) {
var code = error.code
var detail = error.detail
// the template the user was working on before the error occurred
var currentJson = error.template
...
beePluginInstance.updateToken(token);
// the beePluginInstance comes from the BeePlugin.create
...
5101
Expired token cannot be refreshed
You need to do a new login and update the token in the current Builder instance using updateToken
method.
5102
Expired token must be refreshed
You need to do a new login and create a new Builder instance using the new token, BeePlugin.create()
and the current JSON template present in this event
Example scenarios:
The version is outdated
Beefree SDK releases a security fix and every client must refresh
onError: function (error) {
var code = error.code
var detail = error.detail
switch (code) {
case 5101: // re-login and update token in the beeInstance
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
// Obtain token
var token = req.responseText;
// Call update method and pass the new token existent BeePlugin instance
BeePlugin.updateToken(token);
}
};
req.open(
'POST', // Method
'/token', // The server side endpoint that calls BEE REST auth endpoint
false // sync request
);
break
case 5102: // re-login and create a new beeInstance
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
// Obtain token
var token = req.responseText;
// Call update method and pass token and beeConfig to obtain an instance of BEE Plugin
BeePlugin.create(token, beeConfig, function(beePluginInstance) {
// Call start method of bee plugin instance
beePluginInstance.start(template); // template is the json to be loaded in BEE
});
}
};
req.open(
'POST', // Method
'/token', // The server side endpoint that calls BEE REST auth endpoint
false // sync request
);
break
}
},
onError: function (error) {
var code = error.code
var detail = error.detail
switch (code) {
case 5101: // re-login and update token in the beeInstance
...
case 5102: // re-login and create a new beeInstance
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4 && req.status === 200) {
// Obtain token
var token = req.responseText;
// Call update method and pass token and beeConfig to obtain an instance of BEE Plugin
BeePlugin.create(token, beeConfig, function(beePluginInstance) {
// Call start method of bee plugin instance
beePluginInstance.start(detail.template); // the template the user was working on before the error occurred
});
}
};
req.open(
'POST', // Method
'/token', // The server side endpoint that calls BEE REST auth endpoint
false // sync request
);
break
}
},
{
"code": 5001,
"message": "Unsupported media type 'application/x-www-form-urlencoded'",
"status_code": 415
}
{
"code": 5005,
"message": "Invalid UID",
"status_code": 400
}
{
"code": 5002,
"message": "Unable to authenticate with provided credentials.",
"status_code": 401
}
{
"code": 5003,
"message": "Application is disabled.",
"status_code": 403
}
You can enable your users to add forms in Beefree SDK with two methods:
by passing in the configuration parameters a single, default JSON form, potentially including all the fields your application supports, and then have customers build and style forms with our form content block.
by implementing a content dialog on top of the form content block and building a user interface on top of the builder, so that your users can either browse and select pre-built forms or build a new form.
Your application passes a single JSON form, potentially including all the fields that may be required in a form. You are in control of which fields are visibile when the form is dragged. From there, users have a vast control on how to customize the form, by:
adding or removing fields
rearranging their order
renaming their labels
editing their type
This is the quickest way to get started using forms. You may also decide to include such forms inside templates provided by your application.
If you want to pass more than one form to the builder, you can do so by implementing a Content dialog on top of the form content block.
With a content dialog, you have full control over the experience of adding a form. A few examples:
users can select a form from a predefined list
users can browse a list of forms and pick one
users can pick a form and have configuration options (e.g. define a layout) before adding it
Here is an example of form selection built with a Content Dialog.
Once the content dialog returns a form to the application, users can then change the form content properties in the builder, by adding and removing fields, rearranging their order. and customizing their labels and style
You may even want to go a step further and use the Content dialog to load your UI for form creation, on top of the builder; your users will be able to create a new form and add it to the web content they’re building, without interrupting their workflow.
As an alternative to the above-mentioned methods, your users can add an HTML block and easily embed forms created with any form builder available on the market (e.g. Typeform, JotForm, etc.).
Form builders typically offer different options to get an embed code:
if the embed code is a script, it will not appear in the stage when building the web content. Due to security reasons, we need to remove such scripts during edit mode. The form will appear regularly both in the preview and in the final HTML output. An example of this behavior is the embed code produced by Typeform;
If the embed code lives in an iframe, it will be visible during editing as well. For example, Jotform and Google Forms offer this kind of embedding option.
Once a form is added to the web content, the user has these options to manage fields:
Add and remove fields (unless they are marked as required)
Rearrange their order
Rename their labels
Besides, end users can edit fields, when the “edit” action is available.
Finally, users can apply various styling options to the form:
change font type, size, and style;
change colors for text and input backgrounds
change size for field inputs
define borders and paddings
position field labels on the top or on the side of the input fields
style buttons
and more . . .
When managing fields in a form block, users can click on the “Edit” action to change field types and properties. To facilitate the user, the icon next to the label highlights the current field type.
A modal window will pop up:
From this modal, users can:
change field type
change general field properties
label (available also in the sidebar)
placeholder (not available for date, multiple/single choice, dropdown)
required field
read-only field
Clicking on “Type” will open a dropdown with all the available field types:
All fields can be edited, unless:
you defined the field in the JSON form as not editable, using the canBeModified
attribute
the field type is
Submit
Hidden
File upload
Label (a special field type with plain text)
Now, let’s have a closer look at the field types that can be configured with the “Edit field” modal.
Email / Phone / Text / Url
These are the easiest field types to configure, as they only have the optional Placeholder property.
The email and URL types will check at form submission, through HTML5 validation, that the value entered is a formally correct email/web address.
Single choice / Multiple choice / Dropdown
Users need to enter the values that will be displayed to visitors. To do this, they will add those values under Options:
They can either:
Enter a single value, which will be both the label and the value passed to the host app in the form.
Enter couplets such as label | value to differentiate the label shown to visitors from the value passed to your app after form submission. In the example above, users will select Milan from the dropdown at the city they want to visit, but your app will receive “A” as the response for that field.
The Multiple choice type can also be used to create checkboxes, e.g. privacy policy acceptance. In this case, no value should be specified, and any external URL should be added in the field label, like in this example:
Date
This type has no additional properties. The date format of the value returned to the host app will be coherent with browser locale information.
Visitors will enter the date using the browser’s date picker. Otherwise, they can input the date directly, following the automatically generated placeholder for the expected date format.
Number
This type has the option to enter a minimum and/or a maximum allowed value. If not entered, the field will accept any number.
Number fields have a “spinner” input that visitors can use to cycle through allowed values. Visitors can also input a number directly, but the HTML 5 validation will verify if the submitted number falls into the permitted interval.
Long text
This type is just like a text field, but it’s meant for longer inputs. It has an additional “row height” property to define the default height for the text area – which can be adjusted by the visitor by dragging the bottom right corner. Here is how a long text field looks like in a form:
Beefree SDK just passes the data back to the host application. It doesn’t save anything or touch any of the data.
You can implement client-side validation in your JSON forms using the built-in HTML5 form validation, to validate things like:
required field;
response length, for strings (“must be less than” or “must be higher than” n characters);
response value for numbers (minimum or maximum value allowed);
correct type (i.e. the field must contain a number, email address, or some other specific preset type);
check against a regular expression that defines a pattern the entered data needs to follow.
Any other post-submission validation and action must be defined and performed by your application, for instance:
validating whether the data is acceptable, i.e. email already registered;
saving it into a database;
passing it to a 3rd application;
performing other actions (e.g. sending an email notification).
Learn how to implement the different methods to pass forms to the Builder
A closer look at how to structure a JSON form
Visit our GitHub account to:
dive into some sample forms and quick start your integration;
download templates that include those forms;
get a validation JSON schema to test your forms with.
Read this page to learn more about important the core concepts of implementing Self-hosted saved rows.
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:
const beeConfig = {
uid: 'dev-user',
language: 'en-US',
...
saveRows: false // boolean
...
}
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:
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
maxRowsDisplayed: 40, //optional parameter, the max number of displayed rows is 30 by default
externalContentURLs: [{
name: "Headers",
value: "https://URL-01"
},{
name: "Footers",
value: "https://URL-02"
},{
name: "Product grids",
value: "https://URL-03"
},{
name: "Main article",
value: "https://URL-04"
}]
},
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:
rowsConfiguration: {
emptyRows: true,
defaultRows: true,
externalContentURLs: [{
name: "Acquisition series",
value: "https://URL-01"
},{
name: "Newsletter",
value: "https://URL-02"
},{
name: "Transactional",
value: "https://URL-03"
},{
name: "Post-Purchase Drip",
value: "https://URL-04"
}]
},
You can set a category's maximum rows using the following configuration"
rowsConfiguration: {
maxRowsDisplayed: 50
}
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:
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
hooks: {
getRows: {
handler: async (resolve, reject, args) => {
}
}
},
}
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
rowsConfiguration: {
externalContentURLs: [
{
name: "Saved Rows via Hooks",
value: "category-value",
handle: "category-handle",
isLocal: true,
}
]
}
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.
{
value: "category-value",
handle: "category-handle",
}
Finally, we can call the resolve method, passing in an array of savedRows.
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
hooks: {
getRows: {
handler: async (resolve, reject, args) => {
// get the handle
const handle = args.handle
// pseudo code to get the rows with the handle...
const rows = await fakeRowsService(handle)
resolve([ ...rows ])
}
}
},
}
You can now deliver saved rows to the editor in chunks, which improves performance for large datasets.
Chunking avoids loading all saved rows at once. The editor progressively fetches them in smaller parts, which is more efficient and responsive.
To enable chunking:
In rowsConfiguration
, set isChunked: true
.
Optionally, customize the request interval using chunkPageInterval
(default is 1000ms).
In your getRows
hook, use the args.chunk
parameter to return the correct subset of rows.
The editor will automatically call the hook again every interval until it gets an empty array ([]
), which tells it to stop.
This section includes sample code related to implementing Chunking for Self-hosted Saved Rows.
The following code snippet shows an example rowsConfiguration:
rowsConfiguration: {
externalContentURLs: [
{
name: "Saved Rows via Hooks",
value: "category-value",
handle: "category-handle",
isLocal: true,
isChunked: true, // mandatory for sending chunked responses
chunkPageInterval: 2000, // optional to change the chunks interval
}
]
}
The following code snippet shows an example beeConfig with getRows
hook:
beeConfig: {
uid: 'CmsUserName', // [mandatory]
container: 'bee-plugin-container', // [mandatory]
hooks: {
getRows: {
handler: async (resolve, reject, args) => {
// get the handle
const handle = args.handle
// get the chunk requested (first is 0)
const chunk = args.chunk
// pseudo code to get the rows with the handle...
const rows = await fakeRowsService(handle, chunk)
resolve([ ...rows ])
}
}
},
}
Stopping condition: When your handler returns []
, the editor stops requesting more chunks.
Chunk size: You define it on your backend. The editor just shows whatever the hook returns.
Compatibility: This feature is optional, backward compatible, and only works with getRows
hooks (not with static externalContentURLs
).
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.
[
{
metadata: {
name: 'My row name' // Identifies the row, required.
}
columns: { ... }
...
}, // The row that was previously saved. - (*)
...
]
The metadata section of the rows schema allows you to keep track of row-specific information.
metadata: {
"name": "My Saved Row", // The row's title displayed in the "Rows" panel.
"tags": "product, two columns, blue",
... additional custom parameters
}
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.
contentDialog: {
saveRow: {
handler: function (resolve, reject, args) {
return window.bee.onHandleMetadata(args)
.then((metadata) => {
resolve(metadata, { synced: true }) // {
reject()
})
}
},
externalContentURLs: {
handler: function (resolve, reject, args) {
return window.bee.onSearchSavedRows(args)
.then((rows) => {
resolve(rows)
})
.catch(() => {
reject()
})
}
},
},
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.
{ synced: true }
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).
onSaveRow: function (rowJSON, rowHTML, pageJSON) {
// Do something with the returned values...
},
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.
With Commenting, teams using your application can collaborate asynchronously on the same email, page or popup, in order to get their work done more quickly and reach approval for going live more efficiently.
When Commenting is enabled, your end-users (or contributors, as we’ll call them in this context) can:
Add a new comment in any content block or row, so that the context of the discussion is always visible;
Reply to an existing comment and start a thread;
Mark existing threads as resolved, and reopen solved threads if necessary.
Copy the text of a comment, and paste it back to the content area
Preview comments by hovering over the comment icon
Automatically highlight the row where a thread is posted
Receive a notification straight in the builder when a new comment is added during a co-editing session (Superpowers users only).
With Commenting, you enable asynchronous, visual collaboration when multiple collaborators are creating, editing, and reviewing content in the Beefree builders. This collaborative feature can prove extremely beneficial in different contexts, regardless if contributors are in the same team, in separate teams, or even in different companies (e.g. digital marketing agencies collaborating with their clients):
have a single source of truth for feedback and requests on the content created with the builders;
cut time-to-publish, reducing back and forth conversations, both online and offline;
get sign-off for going live for email and web campaigns more efficiently.
Commenting – like most other features – is made available to Beefree SDK customers in an OFF state by default, and must be activated in the Beefree SDK Console.
To do so:
Click Details next to the application you want to configure
We recommend you first familiarize with Commenting in a Development or QA application
Learn more about
Click view more under Application configuration.
Toggle Enable commenting ON and click the Save button to activate Commenting for the application.
To activate Commenting when launching your Beefree application, you will need to pass a username
, userHandle
, and a userColor
in the configuration parameters. See this example:
When opening an email, a landing page or a popup, a contributor can add a new comment to a content block or a row by clicking the “Balloon” icon, available in two spots:
in the row or block outline, inside the editing stage
in the header of the Row properties or Content properties
Clicking one of these two icons will activate the commenting panel, which takes over the editor sidebar. From there, the user can insert a new comment. After the first comment, another contributor can start a thread by adding a second comment.
If you have implemented mentions, users can type @ to bring up a list of contributors and tag them in the comment. If the user starts typing, the list will be filtered If you’ve built a notification system around Commenting, you can use this piece of information to trigger a notification towards the mentioned person.
If you added a Content dialog for mentions, the action will be triggered by the button at the end of the list. You will define the CTA for this button as part of the Content dialog configuration (in this case, “Send an invite”).
If there has already been some activity, the editing stage shows whether a content block or row has any comments by displaying a small comment icon. The sidebar instead indicates the number of existing comments for the selected row or content block, three in this case.
Activating the Commenting panel will bring up the thread. In this case, it will show the three comments.
Existing comments can be edited or deleted by the contributor that added them. Contributors may also resolve comments when they have reached a consensus and completed any pending task.
Improved accessibility to in-line threads. Hover the mouse over the comment icon to see a preview of the last comment added.
Clicking on < All comments in the top section will bring up a list of all comment threads, indicating which ones have been resolved and which ones are still open. Contributors can search inside comments and filter out solved threads, or threads that were part of deleted content. Deleted and hidden comments will be filtered automatically.
To go back to the editor sidebar, contributors can close the Commenting panel by clicking the X icon in the upper right, or they can just click on another row or content block in the stage.
Quickly reopen resolved threads by adding a new comment, expand threads with a click, and show a comment thread preview straight from the content area.
Suggest edits in seconds, and save time with the copy/paste feature. Copy text from the comment body and paste it directly into the content area.
If you subscribed to a Superpowers plan, and have enabled, your users will never lose a new comment again with the new notification system. Users will receive real-time notifications whenever a new comment is added to the document straight in the builder.
By clicking on the notification, they will be able to quickly open the comment, and highlight the element where the conversation is taking place. The toast notification can be styled with to match your application look-and-feel.
If you want to learn how to implement co-editing in your application, check the related documentation article .
With the Reviewer role, you can now allow users to collaborate on your projects without changing the design. This role helps provide peace of mind by allowing inexperienced users to work with the team on their designs, without fear of accidentally changing it.
In short, this new role has the following characteristics:
Can’t apply changes to the message
Can add comments and start threads
Can edit their own comments
Can view other comments
This new role can be easily enabled by passing the following parameter in your configuration:
Once you turn on the feature in the Beefree SDK Console, you may want to disable Commenting for some customers. You can do so via the client-side configuration document that you feed to your Beefree application when initializing the editor.
Why? Because you may decide to make the feature available to customers of your application:
depending on the subscription plan that they are on (i.e. you could push users to a higher plan based on the ability to use Commenting);
depending on the purchase of an optional feature (same);
only if they are “beta” customers, so they see it while keeping it hidden from the rest of your users.
Here’s how to do so:
Enable Commenting in the Beefree SDK console, as mentioned above.
Add the configuration parameter commenting to the beeConfig document
Set it to false for all users that cannot comment.
Here is a simple example:
You can build a notification system around commenting by triggering a callback for events in the Commenting layer. When these events happen, the Beefree system triggers the onComment
callback.
You can react to that callback by taking the information provided in it (e.g. the user that created the comment, the text of the comment, any mentioned user, date & time of the comment, etc.) and send notifications.
You are free to define:
which events will trigger a notification
how it is sent (e.g. Email, In-app, Slack, etc.)
what exactly it says
Again, remember that the Beefree platform only triggers the callback, and it’s up to you to react, if you want. Below you can find the technical details on the comments schema and the onComment
callback.
We’ve put together a that illustrates how to send email notifications, triggered by a mention in a comment. This code shows how to:
Define an array to hold the list of mentioned users in the comment payload.
Loop through the comment payload and add any strings matching a regex to the array
Compare each value in the array with the ‘handle’ property of each user (as defined by the host application), to grab the active users
Loop through your array and pull the respective email address for the handle matches (for use in notifications)
Send the notification through email (via ajax), slack, etc… (you decide and implement how to send the notification)
The following JSON is saved as part of the template:
You may want to save multiple copies of a template, e.g. to create a history/revision or a draft feature.
In such cases, you may decide to store the comments in a database, and add the schema back to the template when it’s loaded. Alternatively, you can keep the comments inside the template, and it will become a static part of the history.
Comments can also be added dynamically, but it’s an advanced task, which requires matching the comment schema to the target content by its “elementId”.
When a thread or comment changes, the Beefree system triggers the onComment
callback. The callback returns the following details:
JSON contains all the details on the change
JSON array of the entire comments schema, as described in the previous section.
JSON contains the contributors
array with all users in a thread.
NEW_COMMENT
COMMENT_THREAD_RESOLVED
COMMENT_THREAD_REOPENED
COMMENT_EDITED
COMMENT_DELETED
JSON contains all the details of the change
You can activate a mention dialog for comments by adding a data source to the Beefree application configuration. You can use the “Hooks” data source method to fetch data from your application and pass it to the Beefree system in real-time.
To configure a hook data source, define the hooks
section in your bee config and implement the getMentions
method.
You can also extend the default mention dialog via Content Dialog. For example, you can enable end-users to to invite an external user not available in the data source.
To configure a hook content dialog, define the contentDialog
section in your Beefree application configuration and implement the getMention
method.
You can generate a link to a specific comment, which can be used to notify the user. Common use cases include sending a link via email, Slack, API, or via in-app messaging. To implement this action use the onComment
callback combined with a new instance method called showComment
.
The onComment
callback contains the comment’s id and a new section called “mentions” containing an array of mentioned users’ uid values.
With the uid
, your application can look-up the user’s contact details. The Beefree platform does not track any sensitive information, such as user emails!
Similarly, since mentions can trigger events and the uid
can generate notifications, you can match uid
to userHandle
.
Next, using the comment’s id, your app can generate a link back to the email containing the comment. The new showComment
instance method can be invoked from Beefree’s onLoad
callback to send the user directly to the comment as soon as the editor is fully loaded and ready.
Note: In the sample below, getParameterByName
is a function that takes the commentId
from the browser’s URL query string.
const beeConfig = {
uid: 'dev-user',
language: 'en-US',
...
username: 'Test User',
userColor: '#cae5f1'
userHandle: 'd09b0f5d-e08b-4dca-b7ae-6010b5da04d3' // unique id
...
}
beeConfig: {
role: 'reviewer',
...
}
const beeConfig = {
uid: 'dev-user',
language: 'en-US',
...
commenting: false // boolean
...
}
var beeConfig = {
...
contentDialog: {
...
getMention: {
label: 'Send an invite',
handler: userInput('Who do you want to mention?', {
username: 'Jerry Doe',
value: 'Jerry Doe',
uid: "f6287c33-6e77-40cb-8a5d-66d62b4f38bb",
})
},
"comments": {
"aab0227f-766d-439d-b3d9-8bf7d04d551f": {
"content": "Here is a comment",
"parentCommentId": null,
"elementId": "ab35241d-dd69-4980-9385-862fedd094e4",
"responses": [
"84f11738-a5a2-49db-956a-ae95b4d1db67"
],
"timestamp": "2020-09-07T13:58:43.147Z",
"author": {
"userHandle": "abfb7e82-3b9a-45fc-a40d-b22221f6a7f5",
"username": "Test User",
"userColor": "#dddddd"
},
"isElementDeleted": false
},
"84f11738-a5a2-49db-956a-ae95b4d1db67": {
"content": "Here is a second comment",
"parentCommentId": "aab0227f-766d-439d-b3d9-8bf7d04d551f",
"elementId": "ab35241d-dd69-4980-9385-862fedd094e4",
"responses": [],
"timestamp": "2020-09-07T13:59:51.954Z",
"author": {
"userHandle": "d09b0f5d-e08b-4dca-b7ae-6010b5da04d3",
"username": "Test User B",
"userColor": "#cae5f1"
},
"isElementDeleted": false
}
}
{
"change": {
"type": "NEW_COMMENT",
"payload": {
"commentId": "a2c555e4-72f7-4e7f-96cd-537e5eb2069c",
"comment": {
"content": "add new Text block and logo here!",
"parentCommentId": null,
"elementId": "73dcc71b-1ba7-458d-81b8-59ec54e534a5",
"mentions": [],
"responses": [],
"timestamp": "2022-04-05T13:53:28.089Z",
"author": {
"userHandle": "0.6379069806343958",
"username": "John Doe",
"userColor": "#ff4400"
}
}
}
},
"comments": {
"a2c555e4-72f7-4e7f-96cd-537e5eb2069c": {
"content": "add new Text block and logo here!",
"parentCommentId": null,
"elementId": "73dcc71b-1ba7-458d-81b8-59ec54e534a5",
"mentions": [],
"responses": [],
"timestamp": "2022-04-05T13:53:28.089Z",
"author": {
"userHandle": "0.6379069806343958",
"username": "John Doe",
"userColor": "#ff4400"
}
}
},
"threadUsers": {
"contributors": [
{
"userHandle": "0.6379069806343958",
"username": "John Doe",
"userColor": "#ff4400"
}
]
}
}
var beeConfig = {
...
hooks: {
getMentions: {
handler: async (resolve, reject, args) => {
const mentionedPeople = [{
"userColor": "#FF5733",
"username": "John Doe", // Displayed in dialog
"value": "John Doe", // Inserted mention value
"uid": "11c8482f-c05d-4480-9861-6d5c64ffbc4a"
}, {
"userColor": "#74FF33",
"username": "userdef5678",
"value": "Jane Doe",
"uid": "ed43043f-1c15-4133-bedb-e78efb69e0ba"
}]
let filtered = mentionedPeople
if (typeof args === "string") {
filtered = mentionedPeople.filter(item => item.username.toLowerCase().includes(args.toLowerCase()))
}
resolve(filtered)
}
},
...
var beeConfig = {
...
contentDialog: {
...
getMention: {
label: 'Send an invite',
handler: userInput('Who do you want to mention?', {
username: 'Jerry Doe',
value: 'Jerry Doe',
uid: "f6287c33-6e77-40cb-8a5d-66d62b4f38bb",
})
},
"mentions": [
"45b9cdd1-60af-4235-ac9f-ddcb7b07a9e0",
"04b3a1a3-ab04-46f7-b03b-e651357b54ab"
],
onLoad: function () {
bee.showComment(getParameterByName('commentId'))
},
As you may have noticed, when you create a new Beefree application, it comes with a default cloud storage option for files (images or files that the message uses or links to). This approach may fit well for applications that offer content creation for the first time, especially if they don’t need to share these files with other areas of the host application.
If you do want users to be able to access the same image and file directories that they use elsewhere in your application, we have a solution.
We created a way to connect to a custom file system provider, allowing you to use your own file storage, no matter which technology you use. A custom file system provider is an API that will allow a Beefree SDK application to perform actions with files outside of the Beefree SDK system, connecting your file system to the Beefree SDK File Manager.
It can be built with your preferred technology: just be sure to follow our instructions to ensure successful communication between the two systems.
Once successfully connected, when a user uploads a file or creates a new folder in the Beefree File Manager, this API will perform these actions in your storage, instead of our default cloud storage. Directories permissions, root directory to use, how thumbnails for images are generated, etc.: you decide.
In order to let your Beefree application consume your FSP (File system provider) API, you will need to provide a Base URL to reach the API.
Base URL: https://myfsp.com/path/to/your/base/endpoint
Note that:
the Base URL must not end with a trailing slash (/)
it must be hosted on the HTTPS protocol
The API uses JSON as the input and output data format: Responses are JSEND standard compliant.
In the event of a successful response, the API returns a “success” status code (ex. 200 OK
) and a JSON object such as the following:
{
"status": "success",
"data": { /* ... */ }
}
In the event an unexpected error occurred during request processing (i.e. missing mandatory request data), the API returns an “error” status code and a JSON object such as the following:
{"status":"error","message":"something went wrong accessing backend filesystem"}
In the event a request fails, the API returns the error codes described in the Error codes section.
Authentication is managed using Basic Authentication type. The Beefree SDK system’s resource server works as a proxy for FSP (File system provider) and consumes FSP API endpoints adding the following fields to HTTP Request Headers. Please note that the API must use HTTPS to grant secure connections and safe data transfer.
User information is segmented by UID parameter.
Authorization: Basic base64(username:password)
X-BEE-ClientId: ClientId
X-BEE-Uid: uid
Authorization
Authentication used is Basic. A string formatted as username:password and encoded in base64 is passed
X-BEE-ClientId
The ClientId (to identify the integrator)
X-BEE-Uid
The uid (ex. useful to identify the user of an integrator)
Ensure you save the username
, password
, and base URL
in the Configuration section of the Beefree SDK Console.
You can enable the move icon for files within the File manager. This move icon allows your end users to move their files between folders, locations, and so on within the File manger. They can access the move icon directly on the file within the File manager. The move icon is a folder with an arrow pointing right inside it. End users click this icon to initiate the process of relocating the corresponding file to a new destination.
Complete the following tasks to enable the move files feature for your custom FSP:
Add a can-move
field in the extra
object in the listing directory content response. Reference the Listing Directory Content section for steps on how to complete this.
Modify the listing response to limit its content when the request includes the x-bee-fsp-flags: move
header. Reference the Listing for Move Dialog section for steps on how to complete this.
Implement a PATCH method for file URLs with conflict_strategy
management. Reference the Implement PATCH Method section for steps on how to complete this.
This section will show samples of successful requests to FSP (File system provider) API. A response contains metadata about directory and files.
In this section, we define the following types of metadata:
The following table lists the fields, descriptions, types and examples for the FSP API response common meta.
mime-type
application/directory for directories and specific mime-type for files
string
“application/directory”, “images/png”, …
name
resource name
string
“my file.jpg”
path
absolute path to resource in FSP
string
“/absolute/path/to/my file.jpg”, “/absolute/path/to/my directory/”, …
last-modified
UNIX time with (milliseconds) of last modification of this resource
int
1445401740000
(stands for: Wed, 21 Oct 2015 04:29:00 GMT)
size
size (in byte) of the resource, this is zero (0) for directories
int
2048
permissions
defines the access grants to the resource, can be ro
for read-only access or rw
for read-write access
string
ro
or rw
extra
generic extra data (for future extensions)
object
The following table lists the fields, descriptions, notes and examples for the FSP API response file-specific meta.
public-url
Public url of this file
This field must be url-encoded
string
thumbnail
Public url of the thumbnail of this file
This field is optional and must be url-encoded
string
The following table lists the fields, descriptions, notes and examples for the FSP API response directory-specific meta.
item-count
number of contained items (directories + files)
This parameter is optional, if you don’t have this data, feel free to pass zero 0
int
Description: Use this to list the directories within the File manager.
The following code shows an example request for listing directories.
GET /
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
The following code shows an example response for listing directories.
{
"status": "success",
"data": {
"meta": {
"mime-type": "application/directory",
"name": "root",
"path": "/",
"last-modified": 1432982102000,
"size": 0,
"permissions": "ro",
"item-count": 2,
"extra": {}, // if null, please use empty object
},
"items": [
{
"mime-type": "application/directory",
"name": "shared",
"path": "/shared/",
"last-modified": 1432984102000,
"size": 0,
"permissions": "ro",
"item-count": 13,
"extra": {}, // if null, please use empty object
},
{
"mime-type": "application/directory",
"name": "mydir",
"path": "/mydir/",
"last-modified": 1432982102000,
"size": 0,
"permissions": "rw",
"item-count": 3,
"extra": {}, // if null, please use empty object
}
]
}
}
Each resource returned by the API has a meta
field with metadata. Directory content is returned into items
field as array of metadata of contained resources.
Some notes about resources access management in the previous example:
/shared/
cannot be renamed, because it is contained in a ro
directory
/mydir/
cannot be renamed, because it is contained in a ro
directory
user cannot “CRUD” resources in /shared/
, because it is ro
user can “CRUD” resources in /mydir/
, because it is rw
Description: This response tells the user interface (UI) whether or not to show the move icon for files within the File manager.
The can-move
property controls whether or not the move button is visible within the user interface (UI).
Take the following steps to display the move icon for file within the File manager:
In the response of the listing endpoint, add a new field named can-move
within the extra
object for each file item.
The can-move
field has a boolean value indicating whether the file can be moved. You can set this value to true
or false
.
The following code shows an example request for listing directory content.
GET /mydir/
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
The following code snippet shows an example of the can-move
property set to true.
{
"name": "image1.jpg",
"path": "/image1.jpg",
"last-modified": 1703065836532,
"permissions": "rw",
"mime-type": "image/jpeg",
"size": 184149,
"public-url": "https://myfsp.com/path/to/image1.jpg",
"thumbnail": "https://myfsp.com/path/to/image1.jpg_thumb.png",
"extra": {
"can-move": true
}
}
The following table shows the response metadata and its corresponding type and description.
name
string
File name.
path
string
File path.
last-modified
number
The date that the file was last modified.
permissions
string
The permissions for the file.
mime-type
string
The file mime type.
size
number
The size of the file.
public-url
string
The public-url to access the file.
thumbnail
string
The thumbnail URL.
extra
object
The object that contains the can-move
property to true or false.
can-move
boolean
A boolean key within the extra object that displays the move button on a file in the File manager when set to true
.
Description: When the move button is pressed, the "move dialog" appears and the usual listing URL is called.
The following image shows an example of the move dialog. This dialog appears after the end user clicks on the move icon for a file. In the image, you can see that the move dialog includes a list of directories for the end user to select from in order to relocate the file.
The following code shows an example of the GET
request that occurs when the move icon is pressed within the File manager and the "move dialog" appears. This GET
request includes the x-bee-fsp-flags: move
header, which is responsible for this behavior.
GET /mydir/
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
X-BEE-fsp-flags: move
The move dialog only shows folders. The GET
request will return the full response, including the folders and the files. However, the response will only show items with "mime-type": "application/directory"
. The File System Provider recognizes this call by the x-bee-fsp-flags: move
header.
For the move dialog to work effectively, it is important that you limit the size of the response. Ensure that the response to this request only contains folders and not any files.
Description: Use this when creating a new directory within the File manager.
The following code shows an example request for creating a new directory.
POST /mydir/new%20dir/
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
The following code shows an example response for creating a new directory.
{
"status": "success",
"data": {
"meta": {
"mime-type": "application/directory",
"name": "new dir",
"path": "/mydir/new dir",
"last-modified": 1432982102000,
"size": 0,
"permissions": "rw",
"item-count": 0,
"extra": {}, // if null, please use empty object
}
}
}
in order for the create directory operation to succeed, the containing directory must exist, and the contained (new) directory must not exist
directory names will match the following regular expression: [ a-zA-Z0-9._- \(\)]+
Description: You can only delete empty directories. Use this to delete a directory when it is empty.
The following code shows an example request for deleting a directory.
DELETE /my%20dir/docs/
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
The following code shows an example response for deleting a directory.
{
"status": "success",
"data": null
}
This section discusses how the Beefree editor interacts with a Custom File Storage Provider (FSP) when uploading images generated or modified via client-side features like Apply Effects or AI Image Generator.
When an end user finishes applying visual effects to an image or generates a new image via AI within the Beefree editor, the application performs the following:
Applies the effect client-side
Uploads the modified or generated image via a POST
request to the FSP
, using the following path structure:
POST /editor_images/random-file-name.ext
The custom FSP must handle folder creation dynamically based on the request path. If the /editor_images/
folder does not exist, it must be created programmatically before saving the uploaded file.
To support this functionality, your FSP should:
Inspect the request path: Check if /editor_images/
is part of the URL path.
Ensure the target folder exists: If it does not, create it before handling the file write.
Continue with the upload process: Once everything looks good, perform the upload.
Currently, there's no payload-based indicator to distinguish between uploads originating from Apply Effects, AI Image Generator, or other direct uploads. Uploads from both Apply Effects and AI Generator will include /editor_images/
in the request URL.
This section includes an example upload request and response for additional reference.
The following code shows an example request for uploading a file.
POST /mydir/my%20pic3.png
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
Content-Type: application/json
{
"source": "http://www.remotehost.com/remotepic.png",
"conflict_strategy": "keep"
}
The following code shows an example response for uploading a file.
{
"status": "success",
"data": {
"meta": {
"mime-type": "image/png",
"name": "my pic3.png",
"path": "/mydir/my pic3.png",
"last-modified": 1432982102000,
"size": 400000,
"permissions": "rw",
"public-url": "https://resources-bucket.s3.amazonaws.com/1111-2222-333-444/my%20pic3.png",
"thumbnail": "https://my-thumbnail-service.com/my%20pic3.png",
"extra": {}, // if null, please use empty object
}
}
}
If an upload has a name conflict with an existing file in the target folder, the FSP must decide how to manage this conflict:
Return an Error: Notify the user about the conflict and do not proceed with the upload.
Ask the User: Prompt the user for instructions on how to handle the conflict.
Overwrite File: Replace the existing file with the new upload.
Rename and Complete: Complete the upload using a different name, usually by appending a suffix. Ensure the metadata is consistent with the newly created file.
Ask the user what to do:
The FSP can prompt the user for action only if the conflict_strategy
field is set to ask
. In this scenario, the FSP must return a 3400
error code, instructing the Builder to display a dialog to the user.
Example response:
{
"code": 3400,
"message": "Resource Already Present"
}
When the user clicks the keep or replace buttons, a new upload request is sent to the FSP with the conflict_strategy
field set to either keep
or replace
.
If there's a filename conflict, the FSP should return a 3401
error code. This instructs the Builder to show a toast notification to the user and prompt them with a dialog.
Uploads are proxied by Beefree’s resource APIs, which enforce the maximum file size configured by the Console. Uploads from various sources are handled as follows:
Image Editor: POST to /editor_images/{filename}
. Filename is a UUID.
Page Builder Favicons: POST to /favicon_images/{filename}
.
Stage: POST to /editor_images/{filename}
.
Description: Use this to delete a file within the File manager.
The following code shows an example request for deleting a file.
DELETE /mydir/my%20pic2.png
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
The following code shows an example response for deleting a file.
{
"status": "success",
"data": null
}
Description: When the move icon is clicked in the File manager, the File System Provider (FSP) will receive this call. It is a PATCH on the URL of the file to move.
The final step in activating the move feature within your File manager is to configure a conflict resolution strategy. This strategy is triggered when there is a file conflict within the File manager.
An example of a conflict is when you are moving a file from one folder to another, but the destination folder has an existing file with the same name as the file being moved to that folder. For example, you want to move a pizza.jpg file to a folder that already contains a pizza.jpg file. In this scenario, there is a conflict because both files cannot have the same name.
The PATCH Method enables you set a conflict_strategy
that resolves scenarios like these when they occur.
The following code shows an example of this method.
PATCH /mydir/file-to-move.jpg
Authorization: Basic 5AMPL3
X-BEE-ClientId: BeeFree
X-BEE-Uid: 1111-2222-333-444
Content-Type: application/json
{
"new_path": "/my/other/dir/",
"conflict_strategy": ""
}
The following response is the same as the upload method. This is the response you will see in the event that a file was successfully moved to a new location.
{
"status": "success",
"data": {
"meta": {
...
}
}
}
This is the response you will see in the event that a file was not successfully moved to a new location, and an error occurred.
{
"code": 3400,
"message": "Resource Already Present"
}
In the event a name conflict occurs, the File manager displays a dialog to the user. You have three options to select from to resolve this conflict using the conflict_strategy
which is passed to the FSP.
These three conflict resolution options are the following:
cancel ( "conflict_strategy": "" ): nothing happens
keep both ( "conflict_strategy": "keep" ): move the file, in order to keep both files our implementation appends a suffix to the new one. For example, the pizza.jpg file will become pizza_1.jpg ( _2 , _3 , ...)
replace ( "conflict_strategy": "replace" ): move the file, it overwrites the old file with the new one
In case of errors, the API returns a JSON object structured like this:
{
"code": 3200,
"message": "Resource Not Found",
"details": "http://myfsp.com/docs/errorcodes/404"
}
To read the full list of possible errors, please refer to this page.
Thumbnail generation is up to the developer of the file system provider.
In case you don’t want to develop your own thumbnail generation procedure, you can use a service like rethumb by Rapid to create a thumbnail URL.
The thumbnail
field is optional, so if you don’t want a thumbnail for your file, do not pass the field and the Beefree system will show you a generic icon based on the mime type you passed.
The thumbnail image must be contained in a 200px by 200px virtual square (see pictures below).
When designing a message or a landing page with Beefree’s editors, 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 things scale up. For example…
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?
Since the Beefree builders are 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 and provides a large amount of flexibility.
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 allows you to build user interfaces for your users to locate & insert merge tags, links, conditional statements, and more. It 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, etc.). 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.
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:
a text placeholder (merge tag)
a dynamic link or a link to specific content (special link)
a markup placeholder (merge content)
a conditional statement (display conditions).
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 Beefree SDK editor’s UI to trigger that action (e.g. “Locate a merge tag”), keeping a consistent UX with other areas of your application.
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:
The editor will start waiting mode (same as when the save action is triggered)
This mode prevents users from further editing and keeps the focus on the user selection
The waiting mode is interrupted if the host application cancels the action
The host application will display to the user a UI element to select or define a content item
When the selection is done, the host application closes the UI and passes it to the editor
The editor receives from the host application the selected content and exits waiting mode
The content is applied to the selected item
The same example applied to special links (link to a product) in a text selection:
The editor starts waiting mode
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.
The editor receives the link and exits waiting mode
The link is applied to the selected text
To set up 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, currentCondition) {
// Your function
}
},
externalContentURLs: {
label: 'Custom text for custom rows',
handler: function(resolve, reject) {
// Your function
}
},
saveRow: {
handler: function (resolve, reject, args) {
// Your function
}
},
editSyncedRow: {
label: 'Custom text for synced rows',
description: 'Custom description for synced rows',
notPermittedDescription: 'Custom description for synced rows when not permitted',
handler: function (resolve, reject, args) => {
// Your function
}
}
}
For rowDisplayConditions
, there is a third parameter called currentCondition
. Use this parameter to return a row's current display condition. This parameter returns an object with the following format:
{
label: '',
description: '',
before: '',
after: '',
type: 'BEE_CUSTOM_DISPLAY_CONDITION'
}
Note: You do not have to name the parameter currentCondition
. You can use any name that works best for your application and workflow.
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).
Defines the text displayed in the editor UI.
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.
The following code snippet displays and example of applying 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'
})
}
},
}
The above code snippet is an 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.
The following code snippet displays and example of applying 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)
}
},
}
The setTimeout
function in the above code sample is used to delay the execution of the enclosed code. It delays the call to the resolve
function by 2000 milliseconds, or 2 seconds. This means that after initiating the special link dialog process, the application will wait for 2 seconds before adding and displaying the specified special link with the label 'external special link' and the URL 'http://www.example.com'.
The following code snippet displays and example of 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.
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 allow you to dynamically insert values into your content, such as user information or other variables. This section will guide you on how to configure merge tags in your host application. See the following section for sample code on setting up merge tags in your content dialog configuration.
Take the following steps to configure merge tags in your application:
Open your content dialog configuration file:
Locate the file where you configure your application's content dialog.
Add the contentDialog
object:
If it doesn't already exist, add the contentDialog
object into your configuration file.
Configure the mergeTags
property:
Inside the contentDialog
object, insert the mergeTags
property as shown below:
contentDialog: {
mergeTags: {
label: 'Apply dynamic syntax',
handler: function(resolve, reject) {
//your function goes here
}
},
},
Define the handler function:
Within the handler
function, write your logic to dynamically insert values into the content.
Add a corresponding action in the text toolbar:
Ensure that the text toolbar includes an action for the merge tag element, allowing users to apply dynamic syntax easily.
Test your implementation:
Validate that the merge tags are working correctly within the UI, ensuring that the dynamic values are properly inserted.
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:
A few of the most common use case for merge tags are the following:
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
The following code snippet defines an object with name
and value
parameters meant for handling placeholders in an application. The name
parameter, although not immediately displayed, is useful for later reference if the user selection is saved and reloaded. The value
parameter contains a text string with specific syntax. This is for inserting dynamic content. This setup is important for applications to manage many placeholders or custom text fields efficiently.
{
name: 'Placeholder name', // Will not be shown
value: '{{ syntax }}' // Text string that will be added
}
Special links are dynamic URLs embedded within emails to execute predefined actions, such as:
Unsubscribing a recipient: Allowing users to easily opt-out from mailing lists.
Loading a Web version of an email: Enabling recipients to view the email content in a browser.
Sending the email to a friend: Facilitating users to share the email with others.
A few end user benefits of using special links are the following:
User Convenience: Simplifies adding recurring URLs and actions to designs, which increases efficiency throughout the design creation process.
Consistent Implementation: Ensures URLs and actions are consistent and accessible across various platforms.
By incorporating special links, end users benefit from the ease of managing various links efficiently across diverse platforms.
This section will explain how to configure special links with steps and provide a code sample to help get you started.
Take the following steps to configure special links in your application:
Define a contentDialog
object within your configuration or settings file.
Add a specialLinks
property to the contentDialog
object.
Set the label
property to the desired name for your link, for example, 'Search a post link'.
Create a handler
function within the specialLinks
object where you will define the custom logic for handling the link.
Ensure this handler
function takes resolve
and reject
parameters to manage its behavior.
The following code snippet provides an example of how you can configure special links.
contentDialog: {
specialLinks: {
label: 'Search a post link',
handler: function(resolve, reject) {
//your function goes here
}
},
},
Links can be applied to different content types. When you define a link dialog action, it will be displayed in the text-toolbar, which is the same behavior for merge tags, as shown in the following image.
The following image shows an example action that applies to image or button content types.
A few of the most common use case for special links are the following:
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
In the following code sample, the parameters serve the following purposes:
type: Represents the type of link but will not be shown to the user directly.
label: Provides default text for the link if no specific text is selected.
link: Contains the URL that will be applied when creating the link, with the possibility of using placeholders.
{
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
}
Merge contents is a feature that allows you to consolidate multiple content sources into a unified display. This section will cover how to configure this feature and its most common use cases.
Access the configuration file of your application.
Locate the contentDialog
object within the file.
Add a mergeContents
property to the contentDialog
object.
Inside the mergeContents
property, set a label
with the description you want to appear, such as 'Set up a new product recommendation'.
Implement a handler
function that will process your custom logic. This function should accept two parameters: resolve
and reject
.
Insert your specific code inside the handler
function where indicated.
Your configuration should look like the following:
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 as shown in the following image.
A few of the most common use case for merge contents are the following:
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
In the following code snippet, the properties perform the following tasks:
name: This property specifies the display name of the content. It appears in the editor UI and helps users identify the content item within the messaging interface.
value: This property represents the actual content that will be injected into the HTML output, shown in the preview. The {{ syntax }}
is typically used for dynamic content insertion.
{
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 allow you to control when specific content is shown based on predefined criteria. This section will cover how to configure display conditions in your application and common use cases.
To configure display conditions in your host application, take the following steps:
Define the contentDialog
Object: Start by defining an object called contentDialog
in your code. This object will hold the configuration for the display conditions.
contentDialog: {
// Configuration properties go here
},
Add the rowDisplayConditions
Property: Within the contentDialog
object, add a property named rowDisplayConditions
. This property will specify the conditions under which a particular row is displayed.
contentDialog: {
rowDisplayConditions: {
// Properties for display conditions go here
},
},
Set the label
Property: Inside the rowDisplayConditions
object, define a label
property. This property sets the text label for the display condition. For example, to set the label as "Open builder":
contentDialog: {
rowDisplayConditions: {
label: 'Open builder',
},
},
Define the handler
Function: Add a handler
property inside the rowDisplayConditions
object. This property is a function that determines the logic for your display conditions. It accepts two parameters: resolve
and reject
, which are typically used for promise handling.
contentDialog: {
rowDisplayConditions: {
label: 'Open builder',
handler: function(resolve, reject) {
// Your function goes here
}
},
},
Implement the Display Logic: Within the handler
function, implement the logic to determine whether the row should be displayed. Use the resolve
function to indicate the conditions are met, and the reject
function to indicate they are not.
contentDialog: {
rowDisplayConditions: {
label: 'Open builder',
handler: function(resolve, reject) {
// Your custom logic to determine display conditions
if (/* condition */) {
resolve();
} else {
reject();
}
}
},
},
Complete the Configuration: Make sure your configuration object is properly closed and integrated into your application. Ensure that all necessary conditions and logic are correctly defined within the handler
function.
contentDialog: {
rowDisplayConditions: {
label: 'Open builder',
handler: function(resolve, reject) {
// Your custom logic to determine display conditions
if (/* condition */) {
resolve();
} else {
reject();
}
}
},
},
Customize the logic within the handler
function to meet your specific needs.
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.
A few of the most common use case for display conditions are the following:
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
The following code snippet configures a display condition with a specific label, description, and delimiters that define the start and end of the condition block in the template. This will be shown in the editor UI and inserted around the selected row based on the specified conditions.
{
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
}
In this example, a window is shown to users when they click on the button to open the builder.
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.
Of course, it can be edited in the editor like any other Display condition, if the user has the rights to do so.
Reference our Advanced Permissions documentation to learn more about managing the visibility of the Add Condition and Edit Condition buttons.
Custom rows allow you to import products or news using various patterns, set up predefined content layouts, and create dynamic sections for recommendations, codes, and advertisements. This section will discuss how to configure custom rows in your host application.
The following code snippet displays an example of how to configure custom row.
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:
A few of the most common use case for custom rows are the following:
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.
The following code snippet configures a custom row with a specific name and value. This will be shown in the editor UI in reference to a specific custom row based on the specified conditions.
{
"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:
Create a new drop-down choice with the provided name
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:
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.
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:
Synced rows are rows that are used across multiple designs, ensuring consistency when updates to a row are made. This section will cover how to configure synced rows in your application.
The following code snippet displays an example of how to configure synced rows.
contentDialog: {
editSyncedRow: {
label: 'Edit synced rows',
description: `This row is used in other designs.
You can decide to update all the designs or transform this single row into a regular one`,
notPermittedDescription: `This row is used in other designs.
Your plan does not permit you to edit it. Please contact your account administrator`,
handler: function (resolve, reject, args) => {
resolve(false) // the boolean will be the value of 'Label of the sidebar button that triggers the contentDialog'`synced`
// if false the row will be un-synced, if true nothing will happen.
}
}
}
The label
, description
and notPermittedDescription
fields handle the wording related to the “Edit synced row” call-to-action/button. Here’s how and where they are used:
label
: Label related to the sidebar button that triggers the content dialog
description
: Description of the action on top of the button
notPermittedDescription
: Description of the action when the button is hidden from the dedicated advanced permission
Here’s an example of what label
and description
would look like:
And here’s an example of what notPermittedDescription
would look like:
Save rows refer to the functionality that allows users to save changes made to specific rows in a data table. This section will discuss how to configure the Save rows feature in your host application.
The following code snippet displays an example of how to configure save rows.
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.
The following code snippet configures a save row with a specific name and category. This will be shown in the editor UI in reference to a specific saved row.
{
"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 asset (email, page, popup) 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.
Forms are interactive elements that allow users to input and submit data. This section will discuss how to configure forms to meet specific requirements in your host application.
The following code snippet displays an example of how to configure forms.
manageForm: {
label: 'Edit form',
handler: async (resolve, reject, args) => {
// Your function
}
},
If you want to have total control on the forms that a Beefree SDK application displays and renders, you can use this forms Content Dialog rather than passing a single form to the Beefree SDK application.
The forms Content Dialog works the same way as the previous Content Dialog for save rows – but in this case, the resolve
function should return the structure for the desired form.
The args
object in the handler function returns to the host application the form object already applied. With this information, the application can decide what to display to the user (e.g., edit the current form, suggest a similar form, etc.).
To understand how this data is structured, refer to the form structure page on this website.
Custom attributes are user-defined metadata that can be added to links and images within an editor. This section will discuss how to configure custom attributes in your host application.
The following code snippet displays an example of how to configure custom attributes.
customAttribute: {
label: 'Search Attributes',
handler: (resolve, reject) => {
resolve({
key: '2783f0ea-f6af-44f3-856e-d7a01cd87714',
name: '100% Custom',
value: 'My custom value',
target: 'link',
})
}
},
If your end users need to apply custom attributes to the links and images in their content, you can completely customize the user experience and workflow for adding those attributes with a Content Dialog that will take over the editor’s UI. The dialog will need to return the attribute to apply.
Custom video allows you to integrate and configure videos from custom sources other than standard platforms like YouTube and Vimeo. This section will discuss how to configure custom video for your host application.
The following code snippet displays an example of how to configure custom video.
addVideo: {
label: 'Choose a video',
handler: async (resolve, reject) => {
resolve({
videoSrc: 'https://link.to.your.custom.video', // mandatory
thumbSrc: 'https://my.beautifulimages.com/thebest.jpg', // mandatory
thumbAlt: 'The title of my custom video!', // optional
})
}
}
It is possible to leverage the Content Dialog method to add videos from custom sources – other than YouTube and Vimeo.
You can use the addVideo
Content Dialog modal, which will take over the builder’s UI. The video will be added as a thumbnail in the content area.
The user must fill out the video URL from a custom source, the image used as a thumbnail, and an alt text/title by implementing a custom modal window (optional). When the user clicks on the video thumbnail, it will open videoSrc
in a new tab/window.
In Beefree SDK we introduced the idea that some content may be editable by some users and not others. For example, you may want the header and footer section of an email newsletter to be locked, so that it cannot be inadvertently modified when creating the latest version of your weekly news digest.
Internally, we’ve been calling this feature “Restricted editing”. Others refer to it as “locked regions”, “blocked content”, and more.
To allow for this, we created ways for the application hosting the builder to define user roles and set their permissions. Let’s take a look at how the feature works first and then show you how to configure your application to take advantage of it.
The user roles that you create (e.g. Brand Manager, Senior Editor, Junior Editor, etc.) can have different permissions. You can create as many or few user roles as you wish. The permissions that you can assign to them refer to:
Locking content (entire rows or specific content blocks)
Editing locked content
Using Display Conditions
Specifically, the permission settings that can be configured for each role are:
Can lock rows (if active, all other permissions are granted)
Can lock modules
Can edit locked rows
Can edit locked modules
Can select Display Conditions
Can edit Display Conditions
Can remove Display Conditions
For example, a Brand Manager all four permissions checked, whereas a Senior Editor might have editing access to rows and modules, but won’t be able to lock rows and modules. Let’s take a look at a few scenarios.
If the user has this permission, locking a row is very easy to do. That user will simply select the row they would like to lock and click on the lock/unlock radio button in the row properties panel.
If a user does not have the permissions needed to edit a locked row, they will see a friendly error when they attempt to select the row, notifying them that the row can’t be edited:
Likewise, they will not be able to drag & drop any content blocks on the locked row, as shown here:
You can restrict access to layout changes while granting access to content modifications by using user roles and permissions.
This allows you to give your users editing access to the content, while ensuring that the overall layout of the message is not altered, and that specific content blocks that should not be modified are left “as is”. This way, for example, a junior member of the marketing team could focus on updating text & images, without worrying about potentially modifying the structure of the message in an unwanted and/or unauthorized way.
Or, as shown in the example below, the same user could update social media icons and links in the footer of an email, without altering legal language and dynamic fields used in the same footer. That’s accomplished by setting us a social media module that’s editable (unlocked), but in a row that’s locked.
When users without the proper permissions try to edit, move or remove the row, they are told that they may not do so.
Similarly, if they try to edit any content is the row that has not been specifically unlocked, they are told that they are not able to do so. In this case, for instance, the user is not able to edit the merge tags used in the footer of the email.
However, when they click on the social media icons, they are able to edit it.
To accomplish the above, a user with higher permissions needs to:
Open the message in the builder
Lock a row
Unlock one or more specific pieces of content within the row.
Log into the Beefree SDK Console and click on Manage roles under Application configuration for the selected application:
In the Manage Roles section you’ll be able to create different user roles and set their permissions. For example, your user roles could be Brand Manager, Account Manager, Junior Editor, etc depending on your needs and nomenclature. For each user role you create, you can set and restrict editing permissions, such as the ability to lock or edit rows and content blocks, as you can see below:
Once you create your user roles you’ll be able to see them listed:
While Role Name is a friendly description of that user role, Role Hash is the parameter that identifies that particular role in Beefree SDK. It must be an alphanumeric string between 8 to 30 characters: it can contain letters and numbers, but cannot contain spaces or special characters (such as “-“, “_”, etc.). You will need to save these role hashes in your application, at the user level – or at the user role level, if you have the concept of “roles” in your application – so that you can retrieve them and pass them to the application when you initialize the builder for that specific user.
The property name is: roleHash
.
For user roles to become active in the builder , you will need to add this new property to your Beefree SDK configuration when you configure the builder for a specific user. You will pass:
roleHash: "roleSpecified"
for each of the user, depending on its role. For example, if the Role Hash for a “Junior Editor” is “juniorEditor”, the application configuration will include:
roleHash: "juniorEditor"
Please refer to configuring the builder for more details.
This section goes in more details about the various combinations of permissions. It might help you understand how to best put this feature to work in Beefree SDK with regard to locking & unlocking rows and content blocks.
First, we created some hypothetical roles by using all application combinations of the available user permissions at the row/content level.
admin
✅
✅
✅
✅
designer
❌
✅
❌
✅
designer2
❌
✅
✅
✅
copy
❌
❌
✅
✅
modules
❌
❌
❌
✅
rows
❌
✅
❌
❌
user
❌
❌
❌
❌
Then, we created a table with a number of possible “actions” and see which user role would have access to which actions. This allows you to map a certain combination of permissions (from above) to a specific task carried out in the Beefree SDK builder.
Lock/unlock a module
✅
❌
widget not provided
✅
✅
❌
widget not provided
❌
widget not provided
❌
widget not provided
Lock/unlock a row
✅
❌
widget not provided
❌
widget not provided
❌
widget not provided
❌
widget not provided
❌
widget not provided
❌
widget not provided
Add a module to locked row (the module is automatically locked)
✅
✅
✅
❌
can’t drop modules in locked rows
❌
can’t drop modules in locked rows
✅
❌
can’t drop modules in locked rows
Move a locked module from an unlocked row to a locked one
✅
✅
✅
❌
can’t drop modules in locked rows
❌
can’t drop modules in locked rows
✅
❌
module handler not provided
Move a locked module from a locked row to a locked one
✅
✅
✅
❌
module handler not provided
❌
module handler not provided
✅
❌
module handler not provided
Move a locked module from a locked row to an unlocked one
✅
✅
✅
❌
module handler not provided
❌
module handler not provided
✅
❌
module handler not provided
Move a locked module from an unlocked row to an unlocked one
✅
✅
✅
✅
✅
✅
❌
module handler not provided
Move an unlocked module from an unlocked row to a locked one
✅
✅
✅
❌
can’t drop modules in locked rows
❌
can’t drop modules in locked rows
✅
❌
can’t drop modules in locked rows
Move an unlocked module from a locked row to a locked one
✅
✅
✅
❌
module handler not provided
❌
module handler not provided
✅
❌
module handler not provided
Move an unlocked module from a locked row to an unlocked one
✅
✅
✅
❌
module handler not provided
❌
module handler not provided
✅
❌
module handler not provided
Move an unlocked module from an unlocked row to an unlocked one
✅
✅
✅
✅
✅
✅
✅
Move a locked row
✅
✅
✅
❌
row handler not provided
❌
row handler not provided
✅
❌
row handler not provided
Move an unlocked row
✅
✅
✅
✅
✅
✅
✅
Delete/duplicate a locked module in locked row
✅
✅
✅
❌
show warning
❌
show warning
✅
❌
show warning
Delete/duplicate an unlocked module in locked row
✅
✅
✅
❌
show warning
❌
show warning
✅
❌
show warning
Delete/duplicate a locked module in unlocked row
✅
✅
✅
✅
✅
✅
❌
show warning
Delete/duplicate an unlocked module in unlocked row
✅
✅
✅
✅
✅
✅
✅
Delete/duplicate unlocked row containing locked modules
✅
✅
✅
✅
✅
❌
show error
❌
show error
Delete/duplicate locked row
✅
✅
✅
❌
show warning
❌
show warning
✅
❌
show warning
Change properties of a locked module
✅
✅
✅
✅
✅
❌
show warning
❌
show warning
Change properties of an unlocked module
✅
✅
✅
✅
✅
✅
✅
Change text of a text/button locked module
✅
✅
✅
✅
✅
❌
show warning
❌
show warning
Change text of a text/button unlocked module
✅
✅
✅
✅
✅
✅
✅
Add an image to a locked image module
✅
✅
✅
✅
✅
❌
show warning
❌
show warning
Add an image to an unlocked image module
✅
✅
✅
✅
✅
✅
✅
Change properties of a locked row
✅
✅
✅
❌
show warning
❌
show warning
✅
❌
show warning
Change properties of an unlocked row
✅
✅
✅
✅
✅
✅
✅
If you use Display Conditions in your builder application, then you can use additional user roles to control the access users have to creating and editing Display Conditions.
Learn more about how to use the Check endpoints.
The Check group consists of three endpoints that scan a template's JSON or a row's JSON, to identify and report critical design elements that are missing. With these endpoints, you can bring design QA functionality into your application. They automatically check a design for common mistakes (including missing links, missing alt text, overly large images, or HTML file sizes that might cause your users' emails to get clipped in Gmail). This is possible through a POST
request where you define the language
, types of checks
to perform, and the template
or row
JSON to check. The response will report any instances within the JSON where an item is missing, a limit is exceeded, and so on. It’ll also include the location (called target
in the response body) of the item that needs attention within the JSON. For example, the uuid
of an image module that is missing alt text.
When coupled with Frontend Commands, these endpoints act as a core pillar of an interactive feedback experience for your end users. Frontend Commands work by displaying visual cues within the user interface. These cues navigate end users to the part of the design and builder that requires their attention. From there, they can easily apply the changes, perform an additional check if they’d like, and export their designs.
Overall, the Check endpoints identify critical design elements, while Frontend Commands help your end users navigate to the elements that need fixing. Together, they create a tool kit that helps your end users create error-free designs, and support them in ensuring their content is complete and ready for their audiences to consume and enjoy.
For a comprehensive list of all the available checks, reference the Available Checks section of this page.
The Check endpoints accept three parameters in the request body: languages
, checks
, and template
or row
. Reference the descriptions for each parameter below:
languages
: Define the language of the template.
checks
: Define the checks you want to perform on the template or row JSON. Do this by adding the category, the check, and the details for the check if applicable. The following code snippet displays an example of this.
"checks": [
{
"category": "missingAltText" // Checks for images missing the 'alt' attribute for accessibility.
},
{
"category": "missingImageLink" // Ensures that clickable images have a valid href/link target.
},
{
"category": "missingCopyLink" // Validates that "Copy" CTAs (like copy-to-clipboard buttons) are correctly linked or wired.
},
{
"category": "overageImageWeight", // Flags images whose file size exceeds the limit.
"limit": 500 // Size limit in kilobytes (KB). Images above this threshold trigger a warning.
},
{
"category": "missingDetailsEmail" // Checks that required email details (e.g. footer info, contact address) are included in the template.
},
{
"category": "overageHtmlWeight", // Detects if the total HTML weight is too large.
"limit": 80, // Maximum allowed HTML size in kilobytes (KB).
"beautified": true // Indicates the HTML should be beautified (formatted) before measuring its size.
}
]
template
or row
: Include the JSON for either an email template, a page template, or a row. This is the JSON that will be checked in ways defined in the checks section of the POST
request.
To use these endpoints, authenticate by creating a Content Services API key in the Beefree SDK Developer Console. For steps on how to obtain a Content Services API key, visit the Content Services API Authentication page.
Reference the available checks you can perform using the Check endpoints in this section. You can perform checks on:
Email template JSON: Use the v1/message/check
endpoint to perform a check on email template JSON.
Page template JSON: Use the v1/page/check
endpoint to perform a check on page template JSON.
Row JSON within a template: Use the v1/row/check
endpoint to perform a check on row JSON within a template.
This section covers the available checks you can perform using these endpoints. Each check listed in this section will include which endpoints it applies to, how it looks in an example API request, and how it looks in an example response. It also explains each field and includes its corresponding data type and description.
Comprehensively, across all endpoints, the available checks are the following:
Missing alt text: Shown as missingAltText
in requests and responses.
Missing link on copy: Shown as missingCopyLink
in requests and responses.
Missing link on images: Shown as missingImageLink
in requests and responses.
Image overage weight: Shown as overageImageWeight
in requests and responses.
Missing email details: Shown as missingEmailDetail
in requests and responses.
Missing page details: Shown as missingDetailsPage
in requests and responses
HTML overage size: Shown as overageHtmlWeight
in requests and responses.
This section covers the Missing Alt Text check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
Type
Warning
Available for
Email and page messages, email and page templates, rows
Applicable widgets
Image, gif, sticker, icon, social
Perform this check by adding {"category":"missingAltText"}
to your API call's request body.
The following JSON response shows an example of a missing alt text check that passed. This means that within the email, page, or row JSON, an instance of missing alt text was not identified, and the end user can confidently export their design knowing alt text is where it should be.
{
"type": "missingAltText",
"targetsCount": 0,
"checkStatus": "passed",
"targets": []
}
The following JSON response shows an example of a missing alt text check that resulted in a warning. This means that within the email, page, or row JSON, an instance of missing alt text was identified, and the end user should resolve the missing alt text in the corresponding target prior to exporting their design.
{
"type": "missingAltText",
"targetsCount": 5,
"checkStatus": "warning",
"targets": [
{
"locked": false,
"synced": false,
"uuid": "f7ba2e08-c88f-4eda-9fc9-ab482a2dcfd0",
"widgetLabel": "https://media0.giphy.com/media/wIePCLOwUQ4RW/giphy.gif?cid=20eb4e9dky638ndajzn0mwpk6hqv3oi8ov705jq2nd4c7rll&ep=v1_gifs_trending&rid=giphy.gif&ct=g",
"widgetType": "gif",
},
{
"locked": false,
"synced": false,
"uuid": "9c38bcc0-71a0-4baa-9b61-43b3c30a620d",
"widgetLabel": "laptop-workspace-flat-design-3214756.jpg",
"widgetType": "image"
},
{
"locked": false,
"synced": false,
"uuid": "c07bcd67-fb72-4218-85d7-1c5e97d5c79c",
"widgetLabel": "https://media2.giphy.com/media/in35qBAr9VKLtpPDe0/giphy.gif?cid=20eb4e9drwe6c1smz42ak0w4qims5tolgkij9rrut8vghj1s&ep=v1_stickers_search&rid=giphy.gif&ct=s",
"widgetType": "sticker"
},
{
"locked": false,
"synced": false,
"uuid": "ab6589c0-414f-4075-ac31-28369511be4d",
"widgetLabel": "custom-icon-placeholder.png",
"widgetType": "icon"
},
{
"locked": false,
"synced": false,
"uuid": "27386d37-df5b-4f5a-b3df-f3e8a2c9d640",
"widgetLabel": "facebook",
"widgetType": "social"
}
]
}
The following table lists and defines all the fields related to the missingAltText
check.
type
string
Check type, equal to missingAltText
targetsCount
integer
The number of widgets missing alt text
checkStatus
string
The status of this check: passed
or warning
targets
array
The list of widgets missing alt text
locked
boolean
If the widget missing alt text is in a locked row
synced
boolean
If the widget missing alt text is in a synced row
uuid
string
uuid
of the row containing this widget
widgetLabel
string
Label of the widget missing alt text: filename for icon
, url for image
, gif
and sticker
and name for social
widgetType
string
Type of the widget missing alt text: image
, gif
, sticker
, icon
, social
This section covers the Missing Link on Copy check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
Type
Warning
Available for
Email and page messages, email and page templates, rows
Applicable widgets
Button, social, menu
Perform this check by adding {"category":"missingCopyLink"}
to your API call's request body.
The following JSON response shows an example of a missing copy link check that passed. This means that within the email, page, or row JSON, an instance of a missing copy link was not identified, and the end user can confidently export their design knowing copy links are where they should be.
{
"type": "missingCopyLink",
"targetsCount": 0,
"checkStatus": "passed",
"targets": []
}
The following JSON response shows an example of a missing copy link check that resulted in a warning. This means that within the email, page, or row JSON, an instance of a missing copy link was identified, and the end user should resolve the missing copy link in the corresponding target prior to exporting their design.
{
"type": "missingCopyLink",
"targetsCount": 3,
"checkStatus": "warning",
"targets": [
{
"locked": false,
"synced": false,
"uuid": "9c38bcc0-71a0-4baa-9b61-43b3c30a620d",
"widgetLabel": "Button name 1",
"widgetType": "button"
},
{
"locked": false,
"synced": false,
"uuid": "c07bcd67-fb72-4218-85d7-1c5e97d5c79c",
"widgetLabel": "Social name,
"widgetType": "social"
},
{
"locked": false,
"synced": false,
"uuid": "ab6589c0-414f-4075-ac31-28369511be4d",
"widgetLabel": "Menu name",
"widgetType": "menu"
}
]
}
The following table lists and defines all the fields related to the missingCopyLink
check.
type
string
Check type, equal to missingCopyLink
targetsCount
integer
The number of widgets missing a link
checkStatus
string
The status of this check: passed
or warning
targets
array
The list of widgets miss link
locked
boolean
If the widget missing link is in a locked row
synced
boolean
If the widget missing link is in a synced row
uuid
string
uuid
of the row containing this widget
widgetLabel
string
Label of the widget missing link
widgetType
string
Type of the widget missing alt text: button
, menu
, social
This section covers the Missing Link on Images check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
Type
Suggestion
Available for
Email and page messages, email and page templates, rows
Applicable widgets
Image, gif, sticker, icon
Perform this check by adding {"category":"missingImageLink"}
to your API call's request body.
The following JSON response shows an example of a missing image link check that passed. This means that within the email, page, or row JSON, an instance of a missing image link was not identified, and the end user can confidently export their design knowing image links are where they should be.
{
"type": "missingImageLink",
"targetsCount": 0,
"checkStatus": "passed",
"targets": []
}
The following JSON response shows an example of a missing image link check that resulted in a warning. This means that within the email, page, or row JSON, an instance of a missing image link was identified, and the end user should resolve the missing image link in the corresponding target prior to exporting their design.
{
"type": "missingImageLink",
"targetsCount": 4,
"checkStatus": "suggestion",
"targets": [
{
"locked": false,
"synced": false,
"uuid": "f7ba2e08-c88f-4eda-9fc9-ab482a2dcfd0",
"widgetLabel": "https://media0.giphy.com/media/wIePCLOwUQ4RW/giphy.gif?cid=20eb4e9dky638ndajzn0mwpk6hqv3oi8ov705jq2nd4c7rll&ep=v1_gifs_trending&rid=giphy.gif&ct=g",
"widgetType": "gif",
},
{
"locked": false,
"synced": false,
"uuid": "9c38bcc0-71a0-4baa-9b61-43b3c30a620d",
"widgetLabel": "laptop-workspace-flat-design-3214756.jpg",
"widgetType": "image"
},
{
"locked": false,
"synced": false,
"uuid": "c07bcd67-fb72-4218-85d7-1c5e97d5c79c",
"widgetLabel": "https://media2.giphy.com/media/in35qBAr9VKLtpPDe0/giphy.gif?cid=20eb4e9drwe6c1smz42ak0w4qims5tolgkij9rrut8vghj1s&ep=v1_stickers_search&rid=giphy.gif&ct=s",
"widgetType": "sticker"
},
{
"locked": false,
"synced": false,
"uuid": "ab6589c0-414f-4075-ac31-28369511be4d",
"widgetLabel": "custom-icon-placeholder.png",
"widgetType": "icon"
}
]
}
The following table lists and defines all the fields related to the missingImageLink
check.
type
string
Check type, equal to missingImageLink
targetsCount
integer
The number of widgets miss link
checkStatus
string
The status of this check: passed
or suggestion
targets
array
The list of widgets miss link
locked
boolean
If the widget missing link is in a locked row
synced
boolean
If the widget missing link is in a synced row
uuid
string
uuid
of the row containing this widget
widgetLabel
string
Label of the widget missing link: filename for icon
, url for image
, gif
and sticker
widgetType
string
Type of the widget missing alt text: image
, gif
, sticker
, icon
This section covers the Image Overage Weight check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
In the example detailed in this section, the weight limit is set to 500KB for emails and rows, and 700KB for pages. The "Content-Length" header in the response of HEAD requests from image, gif, sticker, icon, and social URLs is used to determine if the content size exceeds the specified limits. If the header is missing or the URL cannot be evaluated within 20 seconds, it is considered an error, and the URL is logged for review.
Type
Suggestion
Available for
Email and page messages, email and page templates, rows
Applicable widgets
Image, gif, sticker, icon, social
Perform this check by adding {"category":"overageImageWeight", "limit": 500}
to your API call's request body.
limit
int
Other such limit the image weight is considered overage in KB
The following JSON response shows an example of an image weight overage check that passed. This means that within the email, page, or row JSON, an instance of a limit overage was not identified, and the end user can confidently export their design.
{
"type": "overageImageWeight",
"targetsCount": 0,
"checkStatus": "passed",
"targets": [],
"limit": 500,
"evaluated": 13,
"errored": 3
}
The following JSON response shows an example of an image weight overage check that resulted in a warning. This means that within the email, page, or row JSON, an instance of an image weight overages was identified, and the end user should resolve the overage prior to exporting their design.
{
"type": "overageImageWeight",
"targetsCount": 5,
"checkStatus": "warning",
"limit": 500,
"evaluated": 13,
"errored": 0,
"targets": [
{
"locked": false,
"synced": false,
"weight": 51.32,
"uuid": "f7ba2e08-c88f-4eda-9fc9-ab482a2dcfd0",
"widgetLabel": "https://media0.giphy.com/media/wIePCLOwUQ4RW/giphy.gif?cid=20eb4e9dky638ndajzn0mwpk6hqv3oi8ov705jq2nd4c7rll&ep=v1_gifs_trending&rid=giphy.gif&ct=g",
"widgetType": "gif",
},
{
"locked": false,
"synced": false,
"weight": 51.32,
"uuid": "9c38bcc0-71a0-4baa-9b61-43b3c30a620d",
"widgetLabel": "laptop-workspace-flat-design-3214756.jpg",
"widgetType": "image"
},
{
"locked": false,
"synced": false,
"weight": 51.32,
"uuid": "c07bcd67-fb72-4218-85d7-1c5e97d5c79c",
"widgetLabel": "https://media2.giphy.com/media/in35qBAr9VKLtpPDe0/giphy.gif?cid=20eb4e9drwe6c1smz42ak0w4qims5tolgkij9rrut8vghj1s&ep=v1_stickers_search&rid=giphy.gif&ct=s",
"widgetType": "sticker"
},
{
"locked": false,
"synced": false,
"weight": 51.32,
"uuid": "ab6589c0-414f-4075-ac31-28369511be4d",
"widgetLabel": "custom-icon-placeholder.png",
"widgetType": "icon"
},
{
"locked": false,
"synced": false,
"weight": 51.32,
"uuid": "27386d37-df5b-4f5a-b3df-f3e8a2c9d640",
"widgetLabel": "facebook",
"widgetType": "social"
}
]
}
The following table lists and defines all the fields related to the overageImageWeight
check.
type
string
Check type, equal to overageImageWeight
targetsCount
integer
The number of widgets miss alt text
checkStatus
string
The status of this check: passed
or warning
limit
integer
The limit given in the request
evaluated
integer
The number of evaluated images
errored
integer
The number of images impossible to get the content-length in head requests
targets
array
The list of widgets miss alt text
locked
boolean
if the widget missing alt text is in a locked row
synced
boolean
If the widget missing alt text is in a synced row
weight
float
The weight of the image in KB
uuid
string
uuid
of the row containing this widget
widgetLabel
string
Label of the widget missing alt text
widgetType
string
Type of the widget missing alt text: image
, gif
, sticker
, icon
, social
This section covers the Missing Email Details check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
Type
Suggestion
Available for
Email messages
Use general features in JSON
Head
Perform this check by adding {"category": "missingDetailsEmail"}
to your API call's request body.
The following JSON response shows an example of a missing email details check that passed. This means that within the email, an instance of missing email details was not identified, and the end user can confidently export their design.
{
"type": "missingDetailsEmail",
"targetsCount": 0,
"checkStatus": "passed",
"targets": [],
}
The following JSON response shows an example of a missing email details check that resulted in a warning. This means that within the email, an instance of a missing email details was identified, and the end user should resolve the missing email details prior to exporting their design.
{
"type": "missingDetailsEmail",
"targetsCount": 2,
"checkStatus": "suggestion",
"targets": [{"detailType": "subject"}, {"detailType": "preheader"}],
}
The following table lists and defines all the fields related to the missingDetailsEmail
check.
type
string
Check type, equal to missingDetailsEmail
targetsCount
integer
The number of missing email details
checkStatus
string
The status of this check: passed
or suggestion
targets
array
The list of missing details
detailType
string
Type of the widget missing alt text: subject
, preheader
This section covers the Missing Page Details check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
Type
Suggestion
Available for
Page messages
Use general features in JSON
Head
Perform this check by adding {"category": "missingDetailsPage"}
to your API call's request body.
The following JSON response shows an example of a missing page details check that passed. This means that within the page, an instance of missing page details was not identified, and the end user can confidently export their design.
{
"type": "missingDetailsPage",
"targetsCount": 0,
"checkStatus": "passed",
"targets": [],
}
The following JSON response shows an example of a missing page details check that resulted in a warning. This means that within the page, an instance of a missing page details was identified, and the end user should resolve the missing details prior to exporting their design.
{
"type": "missingDetailsPage",
"targetsCount": 2,
"checkStatus": "suggestion",
"targets": [{"detailType": "title"}, {"detailType": "description"}],
}
The following table lists and defines all the fields related to the missingDetailsPage
check.
type
string
Check type, equal to missingDetailsPage
targetsCount
integer
The number of missing page details
checkStatus
string
The status of this check: passed
or suggestion
targets
array
The list of missing details
detailType
string
Type of the widget missing text: title
, description
This section covers the HTML Overage Weight check, detailing the process of adding the check to the POST
API call, and how it appears in example responses. It includes examples of both a successful check and one that returns a warning.
In the example detailed in this section, the weight limit is set to 80KB for emails and rows, and 700KB for pages. The given JSON HTML is translated and the weight is checked against the specified limit, with the "beautified" boolean determining whether the check applies to the beautified HTML or not. If the weight exceeds the limit, it is considered an error and should be flagged for review.
Type
Warning
Available for
Email messages
Use general features in JSON
displayConditions
Perform this check by adding {"category":"overageHtmlWeight", "limit": 20, "beautified": true}
to your API call's request body.
limit
int
Other such limit the image weight is considered overage in KB.
beautified
string
Optional, default true
The weight is considered on beautified html or minified HTML
The following JSON response shows an example of an HTML weight overage check that passed. This means that within the email, an instance of a limit overage was not identified, and the end user can confidently export their design.
{
"type": "overageHtmlWeight",
"targets": [],
"maxWeight": 11.2,
"displayConditions": false,
"targetsCount": 0,
"checkStatus": "passed",
"processed": true,
"limit": 80
}
The following JSON response shows an example of an HTML weight overage check that resulted in a warning. This means that within the email, an instance of an HTML weight overages was identified, and the end user should resolve the overage prior to exporting their design.
{
"type": "overageHtmlWeight",
"targets": [
{"weight": 11.2, "beautified": true},
],
"maxWeight": 11.2,
"displayConditions": false,
"targetsCount": 1,
"checkStatus": "warning",
"processed": true,
"limit": 80
}
The following table lists and defines all the fields related to the overageHtmlWeight
check.
type
string
Check type, equal to overageHtmlWeight
targetsCount
integer
The number of widgets miss alt text
checkStatus
string
The status of this check: passed
or warning
maxWeight
float or null
The max weight on the generated html files. null if the parser does not response
displayConditions
boolean
If the given json includes display conditions
processed
boolean
If the check has been processed. It is false
when the parser does not response
limit
integer
The limit given in the request
targets
array
The list of html files generated if the parser is responding and at least 1 has the weight other the limit
weight
float
The weight of the generated HTML in KB
beautified
boolean
If the coupled weight is related on beautified HTML
This page discusses how to perform API calls on the backend in order to run checks again email, page, and row JSON. An important part of connecting the backend API calls to frontend feedback is the response body of these API calls. When a check is performed against the JSON, if an issue is identified, the target
in the API response specifies the element that needs attention. This target is what connects to Frontend Commands, the execCommand
method and actions (select
, highlight
, scroll
, and focus
), and provides feedback visually to the end users on the frontend.
The following code snippet provides an example email check response from an API call to the v1/message/check
endpoint.
This section lists and describes each of the Check endpoints. You can use this section to learn about endpoint and how they work. You can also test each endpoint in the interactive testing environment available by clicking Test it.
This section includes details on how to make an API call using the email check endpoint. In the following environment, you can reference comprehensive endpoint details and use the interactive testing environment to get started with the endpoint.
This section includes details on how to make an API call using the page check endpoint. In the following environment, you can reference comprehensive endpoint details and use the interactive testing environment to get started with the endpoint.
This section includes details on how to make an API call using the row check endpoint. In the following environment, you can reference comprehensive endpoint details and use the interactive testing environment to get started with the endpoint.
This page discusses how to effectively track message and UI changes in Beefree SDK. It explains how you can use the onChange
function to monitor real-time JSON updates, enabling efficient application updates and debugging, if needed. It also covers how to implement the onRemoteChange
function to track edits made by other users for Collaborative Editing.
In addition to these, the onViewChange
callback offers a way to monitor changes in the SDK’s interface — such as when users open or close the File Manager, Preview, or Image Editor. This allows you to better understand user behavior, enhance session monitoring, and potentially optimize UX flows based on user navigation.
By leveraging these three callbacks — onChange
, onRemoteChange
, and onViewChange
— you can develop a comprehensive workflow for tracking both content and interaction changes your end users make, whether they are within a single session or a collaborative editing session.
The following table provides a quick reference of callbacks related to tracking changes.
onChange
Fired when the message JSON is updated locally.
The new message JSON object.
onRemoteChange
Fired when changes are made to the message by a different user in a collaborative session.
The updated JSON from the remote user.
onViewChange
Fired when the user navigates between different views in the SDK interface (e.g., opening preview).
One of: 'fileManager'
, 'editor'
, 'preview'
, 'imageEditor'
.
How can I monitor what my customers do in the builder?
How can I tell when a message has actually been updated?
How can I tell when a collaborative editing session has been updated?
How can I track which part of the UI a user is interacting with?
This section includes use cases for the onChange
, onRemoteChange
, and onViewChange
callbacks.
Understanding how users interact with the builder helps improve UX, prioritize development, and identify friction points.
The onChange
callback lets your app detect when users are actively editing a message, using specific features, or possibly reproducing a reported issue.
Use it to:
Detect active vs. abandoned editing sessions
Monitor usage of new features
Investigate and reproduce bugs
Unlike the default autosave (which triggers at fixed intervals regardless of changes), onChange
enables saving only when actual edits occur. This reduces false-positive recovery dialogs and improves the message recovery experience.
Tracking changes over time allows users to compare and restore previous message versions — especially helpful in collaborative environments where mistakes can lead to lost work.
When users edit text or images, onChange
returns the updated content, enabling your app to run validations or custom logic.
Example use cases:
Content suggestions
Blocking restricted content
Validating links and their reputation
Checking custom HTML
Handling conditional syntax with custom workflows
To enable tracking message changes, you need to add the following in the beeConfig:
Add trackChanges
and set it to true
.
The onChange
callback, with the related response function.
(Optional) Add and set the onRemoteChange
boolean to true
for multi-user message tracking during collaborative editing session.
Enable "onChange" Event
Set the following parameter to true
in the beeConfig
file to enable onChange
.
trackChanges: true, // boolean
When you enable onChange
and your end users edit their message, the callback provides you with:
Information on the new content or section
The action that was performed on existing content
The JSON update (as the entire page, as well as JSON patches)
The following code provides an example callback function for onChange
.
onChange: function (jsonFile, response) {
console.log('json', jsonFile);
console.log('response', response);
},
The onRemoteChange
callback is a bit different than onChange
, because it monitors and tracks the changes of other users (those who are not the primary user) during collaborative editing sessions. Using this callback allows you to monitor the changes of all end users in the same session.
Consider the following when using the onRemoteChange
callback:
onChange
and onRemoteChange
have the same prerequisites.
onChange
and onRemoteChange
have the same callback response schema structure.
The following code provides an example callback function for onRemoteChange
.
onRemoteChange: function (jsonFile, response) {
console.log('json', jsonFile);
console.log('response', response);
},
The onViewChange
callback differs from onChange
and onRemoteChange
because it doesn't track content changes in the message itself — instead, it fires when the user interacts with different interface views inside the Beefree SDK. This includes navigating to the File Manager, opening the Preview mode, or launching the Image Editor. It’s especially useful for understanding user behavior, enhancing user experience analytics, or conditionally triggering application logic based on view changes.
Consider the following when using the onViewChange
callback:
onViewChange
does not return a message JSON object like onChange
or onRemoteChange
.
It returns a single string representing the current view.
Typical values include:
'fileManager'
– when the File Manager is opened
'editor'
– when the user returns to the main editor (including on initial load)
'preview'
– when the Preview mode is opened
'imageEditor'
– when the Image Editor is opened
The following code provides an example callback function for onViewChange
:
onViewChange: function (view) {
console.log('Current SDK view:', view);
}
This section discusses how to configure onChange
and onRemoteChange
.
This parameter defines when the tracking is active in the builder.
onChange: function (jsonFile, response) { // do something with response... },
The onChange
callback is triggered every time the builder tracks a change in the message. It returns the message JSON and a response JSON which contains all the information needed to handle any of the use cases described above.
{
"code": "01", // See content and action codes bellow
"description": "string",
"value": "string", // See the chart below
"patches": {...} // JSON patch formatted object
}
The following table lists the parameters in the onChange and onRemoteChange callback response schema and their corresponding types and values.
code
string
Unique identifier for the event created by combining the content code with the action code.
description
string
A text description of the event in the chosen language. (e.g. Image Block Padding Left: 5px)
value
string
If available, this is the new value. (e.g. If padding changes to 5px, then the value returned is “5px”)
patches
array
An array of patches in the JSON Patch specification. JSON Patch is specified in from the IETF.
01
Text Block
02
Image Block
03
Button Block
04
Divider Block
05
Social Block
06
Dynamic Content Block
07
HTML Block
08
Video Block
09
Form
10
Icons
11
Menu
14
Row
16
Message
18
Spacer
22
Paragraph
23
List
26
Table
00
Dropped
01
Dragged
02
Deleted
03
Duplicated
04
Changed
05
Opened
06
Closed
07
Locked
08
Saved
09
Restored
10
Content area background color
11
Do not stack on mobile
12
Row background image
13
Background Center
14
Background Repeat
15
Background Full width
16
Row Display condition
17
Reverse stack order on mobile
20
Text color
21
Link color
23
Text edited
24
Line height
25
Content area width
27
Background color
28
Default font
30
Padding All sides
31
Padding Left
32
Padding Right
33
Padding Top
34
Padding Bottom
40
Hide on mobile
41
Video url
42
Play icon type
43
Play icon color
44
Play icon size
50
Align
51
Automatic image resizing
52
Full width on mobile
53
Image width
60
Alternate text
61
Dynamic image src
62
Dynamic image toggle
63
Change image
64
Image link
70
Button Align
71
Button Link type
72
Button width
73
Button Auto width
74
Button Background color
75
Border radius
80
HTML edited
81
Border All sides
82
Border Left
83
Border Right
84
Border Top
85
Border Bottom
90
Divider Line toggle
91
Divider Width
92
Divider Height
93
Divider Align
95
Icon Name
96
Icon Alternate text
97
Icon Url
98
Icon spacing
99
Icon Align
128
Background Video
129
Paragraph Spacing
130
Font Weight
131
List Type
132
Start List
133
List Spacing
134
List Indent
135
List Style Position
0100
Text dropped
module
0101
Text dragged
module
0102
Text deleted
module
0103
Text duplicated
module
0120
Text color {{value}}
string
Hex color code (e.g. #FFFFFF)
0121
Link color {{value}}
string
Hex color code (e.g. #FFFFFF)
0123
Text edited
string
HTML
0124
Line height {{value}}
string
Value as percent (e.g. 150%)
0130
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0131
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0132
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0133
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0134
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0140
Hide on mobile
boolean
true | false
0200
Image dropped
module
0201
Image dragged
module
0202
Image deleted
module
0203
Image duplicated
module
0230
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0231
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0232
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0233
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0234
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0240
Hide on mobile
boolean
true | false
0250
Align {{value}}
string
left | right | center
0251
Automatic image resizing
boolean
true | false
0252
Full width on mobile
boolean
true | false
0253
Image width {{value}}
string
%
0260
Alternate Text
string
text value
0261
Dynamic image
string
Image path
0262
Dynamic image toggle
boolean
false (only triggered when disabled)
0263
Change image
string
Image path
0264
Image link
string
Url
0300
Button dropped
module
0301
Button dragged
module
0302
Button deleted
module
0303
Button duplicated
module
0320
Text color {{value}}
string
Hex color code (e.g. #FFFFFF)
0324
Line height {{value}}
string
Value as percent (e.g. 150%)
0330
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0331
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0332
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0333
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0334
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0340
Hide on mobile
boolean
true | false
0370
Align {{value}}
string
left | right | center
0371
Link type {{value}}
string
Url
0372
Button width {{value}}
string
%
0373
Auto width
boolean
true | false
0374
Background color {{value}}
string
Hex Color Code (e.g. #FFFFFF)
0375
Border radius
string
Value in pixels (e.g. 5px)
0381
Border Add sides {{value}}
string
Value in pixels | Border Style | Hex color (e.g. 1px solid #C7702E)
0382
Border Left {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
0383
Border Right {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
0384
Border Top {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
0385
Border Bottom {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
0400
Divider dropped
module
0401
Divider dragged
module
0402
Divider deleted
module
0403
Divider duplicated
module
0430
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0431
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0432
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0433
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0434
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0440
Hide on mobile
boolean
true | false
0490
Line
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
0491
Width {{value}}
string
Value as percent (e.g. 150%)
0492
Height {{value}}
string
Value in pixels (e.g. 25px)
0493
Align {{value}}
string
left | right | center
0500
Social dropped
module
0501
Social dragged
module
0502
Social deleted
module
0503
Social duplicated
module
0530
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0531
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0532
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0533
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0534
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0540
Hide on mobile
boolean
true | false
0595
Name {{value}}
string
Icon Name
0596
Alternate Text {{value}}
string
Icon Alternate text
0597
Image Url
string
Icon Url
0598
Icon spacing {{value}}
string
Value in pixels (e.g. 0 0 5px 15px)
0599
Align {{value}}
string
left | right | center
0600
Dynamic content dropped
module
0601
Dynamic content dragged
module
0602
Dynamic content deleted
module
0603
Dynamic content duplicated
module
0604
Dynamic content changed
string
value
0640
Hide on mobile
boolean
true | false
0700
HTML dropped
module
0701
HTML dragged
module
0702
HTML deleted
module
0703
HTML duplicated
module
0740
Hide on mobile
boolean
true | false
0780
HTML edited
string
HTML
0800
Video dropped
module
0801
Video dragged
module
0802
Video deleted
module
0803
Video duplicated
module
0830
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
0831
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
0832
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
0833
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
0834
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
0840
Hide on mobile
boolean
true | false
0841
Video url
string
Video Url
0842
Play icon type {{value}}
string
Play icon type (e.g. Round outline)
0843
Play icon color {{value}}
string
light | dark
0844
Play icon size {{value}}
string
Value in pixels (e.g. 25px)
1400
Row dropped
row
1401
Row dragged
row
1402
Row deleted
row
1403
Row duplicated
row
1410
Content background color {{value}}
string
Hex Color Code (e.g. #FFFFFF)
1411
Do not stack on mobile
boolean
true | false
1412
Row background image
string
Image path
1413
Center
boolean
true | false
1414
Repeat
boolean
true | false
1415
Full width
boolean
true | false
1416
Display Condition
object
Display condition object
1417
Reverse stack order on mobile
boolean
true | false
1430
Padding Add sides {{value}}
string
Value in pixels (e.g. 25px)
1431
Padding Left {{value}}
string
Value in pixels (e.g. 25px)
1432
Padding Right {{value}}
string
Value in pixels (e.g. 25px)
1433
Padding Top {{value}}
string
Value in pixels (e.g. 25px)
1434
Padding Bottom {{value}}
string
Value in pixels (e.g. 25px)
1474
Background color {{value}}
string
Hex Color Code (e.g. #FFFFFF)
1481
Border Add sides {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
1482
Border Left {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
1483
Border Right {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
1484
Border Top {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
1485
Border Bottom {{value}}
string
Value in pixels | Border Style | Hex color 1px solid #C7702E
1625
Content area width {{value}}
string
Value in pixels (e.g. 25px)
1626
Background color {{value}}
string
Hex Color Code (e.g. #FFFFFF)
1627
Content area background color: {{value}}
string
Hex Color Code (e.g. #FFFFFF)
1628
Default font
string
Font
1529
Link color {{value}}
string
Hex Color Code (e.g. #FFFFFF)
1605
Message opened
page
JSON template
1609
Message restored (e.g. undo or redo history)
page
JSON template
13130
Button Font Weight
string
14128
Row Background Video
string
Video URL
22130
Paragraph Font Weight
string
Font Weight value
Check a row JSON for missing alt text, image urls, copy links, and more. Use this endpoint with Frontend Commands to inform the end user where to correct what was reported in the check.
An array of strings for languages
POST /v1/row/check HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 15707
{
"languages": [
"it-IT"
],
"checks": [
{
"category": "missingAltText"
},
{
"category": "missingImageLink"
},
{
"category": "missingCopyLink"
},
{
"category": "overageImageWeight",
"limit": 500
}
],
"row": {
"columns": [
{
"grid-columns": 12,
"modules": [
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "360px"
},
"image": {
"alt": "english gif",
"height": "640px",
"href": "",
"prefix": "",
"src": "https://media1.giphy.com/media/v1.Y2lkPTIwZWI0ZTlkbmtibHF4emFxbTdmZjlzdmZ6M3ptaWxhb2xxdzc4cm1nZ2gxZnI3eSZlcD12MV9naWZzX3RyZW5kaW5nJmN0PWc/cYZkY9HeKgofpQnOUl/giphy.gif",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian gif"
}
},
"type": "image",
"url": "https://giphy.com/gifs/moodman-funny-dog-cYZkY9HeKgofpQnOUl",
"width": "360px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/gifs"
}
},
"ctaLabel": "Browse Gifs",
"entity": "GIF",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGl2ZWxsb18xIiBkYXRhLW5hbWU9IkxpdmVsbG8gMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjUwMCAyNjQzLjM0Ij48dGl0bGU+Z2lmLWdpcGh5LW91dGxpbmUtdGlsZTwvdGl0bGU+PHBhdGggZD0iTTIzMTUsMjYxMi45MUgxODVWMjIuOTFIMTczMi4xM1YzMDguNjZoMjkxLjVWNTk0LjI5SDIzMTVabS0yMDQwLTkwSDIyMjVWNjg0LjI5SDE5MzMuNjNWMzk4LjY2aC0yOTEuNVYxMTIuOTFIMjc1Wm0xNzQ4LjYzLTE5NS43NUg0NzYuMzhWMzA4LjY2aDk2NC4zN1Y4ODBoNTgyLjg4Wm0tMTQ1Ny4yNS05MEgxOTMzLjYzVjk3MEgxMzUwLjc1VjM5OC42Nkg1NjYuMzhaIiBzdHlsZT0iZmlsbDojNTA1NjU5Ii8+PC9zdmc+",
"placeholder": "File is too large",
"uid": "b17dc240-b226-415c-af71-246fc51bd088"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "b17e02eb-f92d-4c1c-b012-a1c91a865756"
},
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "220px"
},
"image": {
"alt": "english sticker ",
"height": "220px",
"href": "",
"prefix": "",
"src": "https://media3.giphy.com/media/tr4TTyG4BjxfDioymO/giphy.gif?cid=20eb4e9d0msqngsoluirfx8m5m93cqwa5xyj7l0lkud65cmo&ep=v1_stickers_trending&rid=giphy.gif&ct=s",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian sticker"
}
},
"type": "image",
"url": "https://giphy.com/stickers/baruchgeuze-baby-tired-smh-tr4TTyG4BjxfDioymO",
"width": "220px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/stickers"
}
},
"ctaLabel": "Browse Stickers",
"entity": "STICKER",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48dGl0bGU+c3RpY2tlcjwvdGl0bGU+PHBhdGggZD0iTTUxMS42NSwxOTUuNTRoMGMtMTEuNDQtNDUuNi0zNC04Ni4xNi02OC0xMTkuMjd2LS4wOUMzOTQuOSwyNy4xLDMyOS4zLDAsMjU5Ljg5LDBBMjU5Ljg0LDI1OS44NCwwLDAsMCwwLDI1OS44M2MwLDY5LjQxLDI3LjQ3LDEzNC42Niw3Ni41NSwxODMuNzRhMjU4LjQxLDI1OC40MSwwLDAsMCwxMjAsNjguMDl2MGMwLC4yMiwxLjI5LjM0LDIuMTYuMzRhMTAuMDcsMTAuMDcsMCwwLDAsNy4yNy0zLjExTDUwOSwyMDUuNzFBMTAuODksMTAuODksMCwwLDAsNTExLjY1LDE5NS41NFpNMTgwLDQzOS4xbDAtLjA1YTE5My44LDE5My44LDAsMCwxLTU4Ljg1LTQwLjQ4Yy03Ni41LTc2LjUtNzYuNS0yMDEsMC0yNzcuNDlhMTk2LjI1LDE5Ni4yNSwwLDAsMSwzMTgsNTguODZsLjA3LDBBMjU5Ljg5LDI1OS44OSwwLDAsMCwxODAsNDM5LjFabTI0LjYxLDQxYTIzOC43MiwyMzguNzIsMCwwLDEsMjM1LjItMjc4LjkyYzQuNzksMCw5LjYxLjE0LDE0LjQzLjQzYTI0MS41OCwyNDEuNTgsMCwwLDEsMjUuODcsM1pNNDYyLjQzLDE4MC45M2EyMTUsMjE1LDAsMCwwLTQ4Ljg1LTc0Ljg1Yy04NC43Ny04NC43Ny0yMjIuNzEtODQuNzctMzA3LjQ4LDBzLTg0Ljc3LDIyMi43MSwwLDMwNy40OEEyMTQuNzUsMjE0Ljc1LDAsMCwwLDE4MSw0NjIuNDFxMSwxMS45NCwzLjE3LDIzLjczYTIzOC42MywyMzguNjMsMCwxLDEsMzAyLTMwMkM0NzguMzEsMTgyLjY4LDQ3MC4zOCwxODEuNjIsNDYyLjQzLDE4MC45M1oiIHN0eWxlPSJmaWxsOiM1MDU2NTkiLz48L3N2Zz4=",
"placeholder": "File is too large",
"uid": "686279a5-1006-47a2-8d7b-6a69004e18ab"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "231445c3-8b29-44fc-8c36-08f734bdacb9"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "32px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
},
"itemSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "english",
"textPosition": "right",
"title": "",
"width": "64px"
}
],
"translations": {
"it-IT": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "italian",
"textPosition": "right",
"title": "",
"width": "64px"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#000000",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "8c2fda6f-3fe2-4e04-9018-72ee4c348085"
},
{
"descriptor": {
"computedStyle": {
"height": 57,
"hideContentOnMobile": false,
"iconsDefaultWidth": 32,
"padding": "0 2.5px 0 2.5px",
"width": 151
},
"iconsList": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "english Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
],
"translations": {
"it-IT": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "italian Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
]
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "40px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "40px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-social",
"uuid": "ec01e2b4-5716-455c-a8ef-732a8e0ff561"
},
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "700px"
},
"image": {
"alt": "english image",
"height": "853px",
"href": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/pub/bfra/rqqybms6/jcx/izz/k5l/baseball-usa-lol-lol-lol-lol-lol-6557888.jpg",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian image"
}
},
"width": "1280px"
},
"mobileStyle": {},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "1f4850b4-4146-4649-95ef-17c40214ce69"
},
{
"descriptor": {
"button": {
"href": "example.com/english",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button english</p></div>",
"style": {
"background-color": "#3b498f",
"border-bottom": "1px solid #8a3b8f",
"border-left": "1px solid #8a3b8f",
"border-radius": "4px",
"border-right": "1px solid #8a3b8f",
"border-top": "1px solid #8a3b8f",
"color": "#ffffff",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank",
"translations": {
"it-IT": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button italian</p></div>"
}
}
},
"computedStyle": {
"height": 44,
"hideContentOnMobile": false,
"width": 102
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "df1b6f51-d8a7-43ae-a5b9-7699918eccdd"
},
{
"descriptor": {
"computedStyle": {
"hamburger": {
"backgroundColor": "#000000",
"foregroundColor": "#ffffff",
"iconSize": "36px",
"iconType": "normal",
"mobile": false
},
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"layout": "horizontal",
"linkColor": "#8a3c90",
"menuItemsSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
}
},
"menuItemsList": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "english menu"
}
],
"translations": {
"it-IT": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "italian menu"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#101112",
"font-family": "inherit",
"font-size": "16px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-menu",
"uuid": "598ecce1-4b00-4484-bb47-bb6c3b5c6b07"
},
{
"descriptor": {
"heading": {
"style": {
"color": "#274daa",
"direction": "ltr",
"font-family": "Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "50px",
"font-weight": "700",
"letter-spacing": "1px",
"line-height": "150%",
"link-color": "#09eca4",
"text-align": "left"
},
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block english</span>",
"title": "h1",
"translations": {
"it-IT": {
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block italian</span>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "e18f9584-1396-4ff0-a6a5-0fb56ac92555"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"mobileStyle": {},
"paragraph": {
"computedStyle": {
"linkColor": "#3c09ec",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block. english</p>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"translations": {
"it-IT": {
"html": "<p>I'm a new paragraph block. italian</p>"
}
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "dbeb062e-f713-422b-a7d7-10df637c0c28"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"list": {
"computedStyle": {
"liIndent": "30px",
"liSpacing": "0px",
"linkColor": "#8a3b8f",
"listStylePosition": "inside",
"listStyleType": "revert",
"startList": "1"
},
"html": "<ul><li>This is an unordered list english</li></ul>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"tag": "ul",
"translations": {
"it-IT": {
"html": "<ul><li>This is an unordered list italian</li></ul>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-list",
"uuid": "12801c59-2a03-489e-b155-02c7ac843e74"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "#f5f5ef",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "700px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
}
}
{
"message": "Success"
}
Check a message JSON for missing alt text, image urls, copy links, and more. Use this endpoint with Frontend Commands to inform the end user where to correct what was reported in the check.
An array of strings for languages
POST /v1/message/check HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 16434
{
"languages": [
"it-IT"
],
"checks": [
{
"category": "missingAltText"
},
{
"category": "missingImageLink"
},
{
"category": "missingCopyLink"
},
{
"category": "overageImageWeight",
"limit": 500
},
{
"category": "missingDetailsEmail"
},
{
"category": "overageHtmlWeight",
"limit": 80,
"beautified": true
}
],
"template": {
"comments": {},
"page": {
"body": {
"container": {
"style": {
"background-color": "#8e7777"
}
},
"content": {
"computedStyle": {
"linkColor": "#3c09ec",
"messageBackgroundColor": "#f5f5ef",
"messageWidth": "700px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica Neue, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"name": "Cabin",
"url": "https://fonts.googleapis.com/css2?family=Cabin:wght@100;200;300;400;500;600;700;800;900"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "360px"
},
"image": {
"alt": "english gif",
"height": "640px",
"href": "",
"prefix": "",
"src": "https://media1.giphy.com/media/v1.Y2lkPTIwZWI0ZTlkbmtibHF4emFxbTdmZjlzdmZ6M3ptaWxhb2xxdzc4cm1nZ2gxZnI3eSZlcD12MV9naWZzX3RyZW5kaW5nJmN0PWc/cYZkY9HeKgofpQnOUl/giphy.gif",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian gif"
}
},
"type": "image",
"url": "https://giphy.com/gifs/moodman-funny-dog-cYZkY9HeKgofpQnOUl",
"width": "360px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/gifs"
}
},
"ctaLabel": "Browse Gifs",
"entity": "GIF",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGl2ZWxsb18xIiBkYXRhLW5hbWU9IkxpdmVsbG8gMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjUwMCAyNjQzLjM0Ij48dGl0bGU+Z2lmLWdpcGh5LW91dGxpbmUtdGlsZTwvdGl0bGU+PHBhdGggZD0iTTIzMTUsMjYxMi45MUgxODVWMjIuOTFIMTczMi4xM1YzMDguNjZoMjkxLjVWNTk0LjI5SDIzMTVabS0yMDQwLTkwSDIyMjVWNjg0LjI5SDE5MzMuNjNWMzk4LjY2aC0yOTEuNVYxMTIuOTFIMjc1Wm0xNzQ4LjYzLTE5NS43NUg0NzYuMzhWMzA4LjY2aDk2NC4zN1Y4ODBoNTgyLjg4Wm0tMTQ1Ny4yNS05MEgxOTMzLjYzVjk3MEgxMzUwLjc1VjM5OC42Nkg1NjYuMzhaIiBzdHlsZT0iZmlsbDojNTA1NjU5Ii8+PC9zdmc+",
"placeholder": "File is too large",
"uid": "b17dc240-b226-415c-af71-246fc51bd088"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "b17e02eb-f92d-4c1c-b012-a1c91a865756"
},
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "220px"
},
"image": {
"alt": "english sticker ",
"height": "220px",
"href": "",
"prefix": "",
"src": "https://media3.giphy.com/media/tr4TTyG4BjxfDioymO/giphy.gif?cid=20eb4e9d0msqngsoluirfx8m5m93cqwa5xyj7l0lkud65cmo&ep=v1_stickers_trending&rid=giphy.gif&ct=s",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian sticker"
}
},
"type": "image",
"url": "https://giphy.com/stickers/baruchgeuze-baby-tired-smh-tr4TTyG4BjxfDioymO",
"width": "220px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/stickers"
}
},
"ctaLabel": "Browse Stickers",
"entity": "STICKER",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48dGl0bGU+c3RpY2tlcjwvdGl0bGU+PHBhdGggZD0iTTUxMS42NSwxOTUuNTRoMGMtMTEuNDQtNDUuNi0zNC04Ni4xNi02OC0xMTkuMjd2LS4wOUMzOTQuOSwyNy4xLDMyOS4zLDAsMjU5Ljg5LDBBMjU5Ljg0LDI1OS44NCwwLDAsMCwwLDI1OS44M2MwLDY5LjQxLDI3LjQ3LDEzNC42Niw3Ni41NSwxODMuNzRhMjU4LjQxLDI1OC40MSwwLDAsMCwxMjAsNjguMDl2MGMwLC4yMiwxLjI5LjM0LDIuMTYuMzRhMTAuMDcsMTAuMDcsMCwwLDAsNy4yNy0zLjExTDUwOSwyMDUuNzFBMTAuODksMTAuODksMCwwLDAsNTExLjY1LDE5NS41NFpNMTgwLDQzOS4xbDAtLjA1YTE5My44LDE5My44LDAsMCwxLTU4Ljg1LTQwLjQ4Yy03Ni41LTc2LjUtNzYuNS0yMDEsMC0yNzcuNDlhMTk2LjI1LDE5Ni4yNSwwLDAsMSwzMTgsNTguODZsLjA3LDBBMjU5Ljg5LDI1OS44OSwwLDAsMCwxODAsNDM5LjFabTI0LjYxLDQxYTIzOC43MiwyMzguNzIsMCwwLDEsMjM1LjItMjc4LjkyYzQuNzksMCw5LjYxLjE0LDE0LjQzLjQzYTI0MS41OCwyNDEuNTgsMCwwLDEsMjUuODcsM1pNNDYyLjQzLDE4MC45M2EyMTUsMjE1LDAsMCwwLTQ4Ljg1LTc0Ljg1Yy04NC43Ny04NC43Ny0yMjIuNzEtODQuNzctMzA3LjQ4LDBzLTg0Ljc3LDIyMi43MSwwLDMwNy40OEEyMTQuNzUsMjE0Ljc1LDAsMCwwLDE4MSw0NjIuNDFxMSwxMS45NCwzLjE3LDIzLjczYTIzOC42MywyMzguNjMsMCwxLDEsMzAyLTMwMkM0NzguMzEsMTgyLjY4LDQ3MC4zOCwxODEuNjIsNDYyLjQzLDE4MC45M1oiIHN0eWxlPSJmaWxsOiM1MDU2NTkiLz48L3N2Zz4=",
"placeholder": "File is too large",
"uid": "686279a5-1006-47a2-8d7b-6a69004e18ab"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "231445c3-8b29-44fc-8c36-08f734bdacb9"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "32px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
},
"itemSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "english",
"textPosition": "right",
"title": "",
"width": "64px"
}
],
"translations": {
"it-IT": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "italian",
"textPosition": "right",
"title": "",
"width": "64px"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#000000",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "8c2fda6f-3fe2-4e04-9018-72ee4c348085"
},
{
"descriptor": {
"computedStyle": {
"height": 57,
"hideContentOnMobile": false,
"iconsDefaultWidth": 32,
"padding": "0 2.5px 0 2.5px",
"width": 151
},
"iconsList": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "english Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
],
"translations": {
"it-IT": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "italian Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
]
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "40px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "40px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-social",
"uuid": "ec01e2b4-5716-455c-a8ef-732a8e0ff561"
},
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "700px"
},
"image": {
"alt": "english image",
"height": "853px",
"href": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/pub/bfra/rqqybms6/jcx/izz/k5l/baseball-usa-lol-lol-lol-lol-lol-6557888.jpg",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian image"
}
},
"width": "1280px"
},
"mobileStyle": {},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "1f4850b4-4146-4649-95ef-17c40214ce69"
},
{
"descriptor": {
"button": {
"href": "example.com/english",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button english</p></div>",
"style": {
"background-color": "#3b498f",
"border-bottom": "1px solid #8a3b8f",
"border-left": "1px solid #8a3b8f",
"border-radius": "4px",
"border-right": "1px solid #8a3b8f",
"border-top": "1px solid #8a3b8f",
"color": "#ffffff",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank",
"translations": {
"it-IT": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button italian</p></div>"
}
}
},
"computedStyle": {
"height": 44,
"hideContentOnMobile": false,
"width": 102
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "df1b6f51-d8a7-43ae-a5b9-7699918eccdd"
},
{
"descriptor": {
"computedStyle": {
"hamburger": {
"backgroundColor": "#000000",
"foregroundColor": "#ffffff",
"iconSize": "36px",
"iconType": "normal",
"mobile": false
},
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"layout": "horizontal",
"linkColor": "#8a3c90",
"menuItemsSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
}
},
"menuItemsList": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "english menu"
}
],
"translations": {
"it-IT": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "italian menu"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#101112",
"font-family": "inherit",
"font-size": "16px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-menu",
"uuid": "598ecce1-4b00-4484-bb47-bb6c3b5c6b07"
},
{
"descriptor": {
"heading": {
"style": {
"color": "#274daa",
"direction": "ltr",
"font-family": "Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "50px",
"font-weight": "700",
"letter-spacing": "1px",
"line-height": "150%",
"link-color": "#09eca4",
"text-align": "left"
},
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block english</span>",
"title": "h1",
"translations": {
"it-IT": {
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block italian</span>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "e18f9584-1396-4ff0-a6a5-0fb56ac92555"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"mobileStyle": {},
"paragraph": {
"computedStyle": {
"linkColor": "#3c09ec",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block. english</p>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"translations": {
"it-IT": {
"html": "<p>I'm a new paragraph block. italian</p>"
}
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "dbeb062e-f713-422b-a7d7-10df637c0c28"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"list": {
"computedStyle": {
"liIndent": "30px",
"liSpacing": "0px",
"linkColor": "#8a3b8f",
"listStylePosition": "inside",
"listStyleType": "revert",
"startList": "1"
},
"html": "<ul><li>This is an unordered list english</li></ul>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"tag": "ul",
"translations": {
"it-IT": {
"html": "<ul><li>This is an unordered list italian</li></ul>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-list",
"uuid": "12801c59-2a03-489e-b155-02c7ac843e74"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "#f5f5ef",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "700px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
}
}
}
{
"message": "Success"
}
Check a Page JSON for missing alt text, image urls, copy links, and more. Use this endpoint with Frontend Commands to inform the end user where to correct what was reported in the check.
An array of strings for languages
POST /v1/page/check HTTP/1.1
Host: api.getbee.io
Authorization: Bearer Enter Dev Console API Key as Bearer token
Content-Type: application/json
Accept: */*
Content-Length: 16371
{
"languages": [
"it-IT"
],
"checks": [
{
"category": "missingAltText"
},
{
"category": "missingImageLink"
},
{
"category": "missingCopyLink"
},
{
"category": "missingDetailsPage"
},
{
"category": "overageImageWeight",
"limit": 500
}
],
"template": {
"comments": {},
"page": {
"body": {
"container": {
"style": {
"background-color": "#8e7777"
}
},
"content": {
"computedStyle": {
"linkColor": "#3c09ec",
"messageBackgroundColor": "#f5f5ef",
"messageWidth": "700px"
},
"style": {
"color": "#000000",
"font-family": "Arial, Helvetica Neue, Helvetica, sans-serif"
}
},
"type": "mailup-bee-page-properties",
"webFonts": [
{
"fontFamily": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"name": "Cabin",
"url": "https://fonts.googleapis.com/css2?family=Cabin:wght@100;200;300;400;500;600;700;800;900"
}
]
},
"description": "",
"rows": [
{
"columns": [
{
"grid-columns": 12,
"modules": [
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "360px"
},
"image": {
"alt": "english gif",
"height": "640px",
"href": "",
"prefix": "",
"src": "https://media1.giphy.com/media/v1.Y2lkPTIwZWI0ZTlkbmtibHF4emFxbTdmZjlzdmZ6M3ptaWxhb2xxdzc4cm1nZ2gxZnI3eSZlcD12MV9naWZzX3RyZW5kaW5nJmN0PWc/cYZkY9HeKgofpQnOUl/giphy.gif",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian gif"
}
},
"type": "image",
"url": "https://giphy.com/gifs/moodman-funny-dog-cYZkY9HeKgofpQnOUl",
"width": "360px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/gifs"
}
},
"ctaLabel": "Browse Gifs",
"entity": "GIF",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGl2ZWxsb18xIiBkYXRhLW5hbWU9IkxpdmVsbG8gMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMjUwMCAyNjQzLjM0Ij48dGl0bGU+Z2lmLWdpcGh5LW91dGxpbmUtdGlsZTwvdGl0bGU+PHBhdGggZD0iTTIzMTUsMjYxMi45MUgxODVWMjIuOTFIMTczMi4xM1YzMDguNjZoMjkxLjVWNTk0LjI5SDIzMTVabS0yMDQwLTkwSDIyMjVWNjg0LjI5SDE5MzMuNjNWMzk4LjY2aC0yOTEuNVYxMTIuOTFIMjc1Wm0xNzQ4LjYzLTE5NS43NUg0NzYuMzhWMzA4LjY2aDk2NC4zN1Y4ODBoNTgyLjg4Wm0tMTQ1Ny4yNS05MEgxOTMzLjYzVjk3MEgxMzUwLjc1VjM5OC42Nkg1NjYuMzhaIiBzdHlsZT0iZmlsbDojNTA1NjU5Ii8+PC9zdmc+",
"placeholder": "File is too large",
"uid": "b17dc240-b226-415c-af71-246fc51bd088"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "b17e02eb-f92d-4c1c-b012-a1c91a865756"
},
{
"contentType": "image",
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "220px"
},
"image": {
"alt": "english sticker ",
"height": "220px",
"href": "",
"prefix": "",
"src": "https://media3.giphy.com/media/tr4TTyG4BjxfDioymO/giphy.gif?cid=20eb4e9d0msqngsoluirfx8m5m93cqwa5xyj7l0lkud65cmo&ep=v1_stickers_trending&rid=giphy.gif&ct=s",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian sticker"
}
},
"type": "image",
"url": "https://giphy.com/stickers/baruchgeuze-baby-tired-smh-tr4TTyG4BjxfDioymO",
"width": "220px"
},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"moduleInternal": {
"configurationUi": {
"external": {
"url": "https://addons-giphy.getbee.io/search/stickers"
}
},
"ctaLabel": "Browse Stickers",
"entity": "STICKER",
"icon": "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48dGl0bGU+c3RpY2tlcjwvdGl0bGU+PHBhdGggZD0iTTUxMS42NSwxOTUuNTRoMGMtMTEuNDQtNDUuNi0zNC04Ni4xNi02OC0xMTkuMjd2LS4wOUMzOTQuOSwyNy4xLDMyOS4zLDAsMjU5Ljg5LDBBMjU5Ljg0LDI1OS44NCwwLDAsMCwwLDI1OS44M2MwLDY5LjQxLDI3LjQ3LDEzNC42Niw3Ni41NSwxODMuNzRhMjU4LjQxLDI1OC40MSwwLDAsMCwxMjAsNjguMDl2MGMwLC4yMiwxLjI5LjM0LDIuMTYuMzRhMTAuMDcsMTAuMDcsMCwwLDAsNy4yNy0zLjExTDUwOSwyMDUuNzFBMTAuODksMTAuODksMCwwLDAsNTExLjY1LDE5NS41NFpNMTgwLDQzOS4xbDAtLjA1YTE5My44LDE5My44LDAsMCwxLTU4Ljg1LTQwLjQ4Yy03Ni41LTc2LjUtNzYuNS0yMDEsMC0yNzcuNDlhMTk2LjI1LDE5Ni4yNSwwLDAsMSwzMTgsNTguODZsLjA3LDBBMjU5Ljg5LDI1OS44OSwwLDAsMCwxODAsNDM5LjFabTI0LjYxLDQxYTIzOC43MiwyMzguNzIsMCwwLDEsMjM1LjItMjc4LjkyYzQuNzksMCw5LjYxLjE0LDE0LjQzLjQzYTI0MS41OCwyNDEuNTgsMCwwLDEsMjUuODcsM1pNNDYyLjQzLDE4MC45M2EyMTUsMjE1LDAsMCwwLTQ4Ljg1LTc0Ljg1Yy04NC43Ny04NC43Ny0yMjIuNzEtODQuNzctMzA3LjQ4LDBzLTg0Ljc3LDIyMi43MSwwLDMwNy40OEEyMTQuNzUsMjE0Ljc1LDAsMCwwLDE4MSw0NjIuNDFxMSwxMS45NCwzLjE3LDIzLjczYTIzOC42MywyMzguNjMsMCwxLDEsMzAyLTMwMkM0NzguMzEsMTgyLjY4LDQ3MC4zOCwxODEuNjIsNDYyLjQzLDE4MC45M1oiIHN0eWxlPSJmaWxsOiM1MDU2NTkiLz48L3N2Zz4=",
"placeholder": "File is too large",
"uid": "686279a5-1006-47a2-8d7b-6a69004e18ab"
},
"type": "mailup-bee-newsletter-modules-addon",
"uuid": "231445c3-8b29-44fc-8c36-08f734bdacb9"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"iconHeight": "32px",
"iconSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
},
"itemSpacing": "0px"
},
"iconsList": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "english",
"textPosition": "right",
"title": "",
"width": "64px"
}
],
"translations": {
"it-IT": {
"icons": [
{
"alt": "",
"height": "64px",
"href": "",
"id": "d087217b-345a-4ebe-ac09-27c8ab0fdabd",
"image": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_self",
"text": "italian",
"textPosition": "right",
"title": "",
"width": "64px"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#000000",
"font-family": "inherit",
"font-size": "14px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-icons",
"uuid": "8c2fda6f-3fe2-4e04-9018-72ee4c348085"
},
{
"descriptor": {
"computedStyle": {
"height": 57,
"hideContentOnMobile": false,
"iconsDefaultWidth": 32,
"padding": "0 2.5px 0 2.5px",
"width": 151
},
"iconsList": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "english Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "english Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "english Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
],
"translations": {
"it-IT": {
"icons": [
{
"id": "linkedin",
"image": {
"alt": "linkedin",
"href": "https://www.linkedin.com/",
"prefix": "linkedin",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian linkedin"
},
"name": "linkedin",
"text": "linkedin",
"type": "follow"
},
{
"id": "instagram",
"image": {
"alt": "instagram",
"href": "https://www.instagram.com/",
"prefix": "instagram",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian instagram"
},
"name": "instagram",
"text": "instagram",
"type": "follow"
},
{
"id": "twitter",
"image": {
"alt": "Twitter",
"href": "https://www.twitter.com",
"prefix": "https://www.twitter.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_self",
"title": "italian Twitter"
},
"name": "twitter",
"text": "Twitter",
"type": "follow"
},
{
"id": "tripadvisor",
"image": {
"alt": "Tripadvisor",
"href": "https://www.tripadvisor.com",
"prefix": "https://www.tripadvisor.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Tripadvisor"
},
"name": "Tripadvisor",
"text": "",
"type": "follow"
},
{
"image": {
"alt": "Custom",
"height": "",
"href": "",
"prefix": "",
"src": "https://app-rsrc.getbee.io/public/resources/placeholders/custom-icon-placeholder.png",
"target": "_blank",
"title": "italian Custom",
"width": ""
},
"name": "9b6dbe22-59a9-4c8d-b2e3-601cfdee8f12",
"text": "",
"type": "custom"
},
{
"id": "snapchat",
"image": {
"alt": "",
"href": "https://www.snapchat.com",
"prefix": "https://www.snapchat.com",
"src": "https://app-rsrc.getbee.io/public/resources/social-networks-icon-sets/t-only-logo-dark-gray/[email protected]",
"target": "_blank",
"title": "italian Snapchat"
},
"name": "Snapchat",
"text": "",
"type": "follow"
}
]
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "40px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "40px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-social",
"uuid": "ec01e2b4-5716-455c-a8ef-732a8e0ff561"
},
{
"descriptor": {
"computedStyle": {
"class": "center autowidth",
"hideContentOnMobile": false,
"width": "700px"
},
"image": {
"alt": "english image",
"height": "853px",
"href": "",
"src": "https://d15k2d11r6t6rl.cloudfront.net/pub/bfra/rqqybms6/jcx/izz/k5l/baseball-usa-lol-lol-lol-lol-lol-6557888.jpg",
"target": "_blank",
"translations": {
"it-IT": {
"alt": "italian image"
}
},
"width": "1280px"
},
"mobileStyle": {},
"style": {
"border-radius": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-image",
"uuid": "1f4850b4-4146-4649-95ef-17c40214ce69"
},
{
"descriptor": {
"button": {
"href": "example.com/english",
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button english</p></div>",
"style": {
"background-color": "#3b498f",
"border-bottom": "1px solid #8a3b8f",
"border-left": "1px solid #8a3b8f",
"border-radius": "4px",
"border-right": "1px solid #8a3b8f",
"border-top": "1px solid #8a3b8f",
"color": "#ffffff",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "200%",
"max-width": "100%",
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px",
"width": "auto"
},
"target": "_blank",
"translations": {
"it-IT": {
"label": "<div class=\"txtTinyMce-wrapper\" style=\"font-family: inherit;\" data-mce-style=\"font-family: inherit;\"><p style=\"word-break: break-word;\" data-mce-style=\"word-break: break-word;\">Button italian</p></div>"
}
}
},
"computedStyle": {
"height": 44,
"hideContentOnMobile": false,
"width": 102
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-button",
"uuid": "df1b6f51-d8a7-43ae-a5b9-7699918eccdd"
},
{
"descriptor": {
"computedStyle": {
"hamburger": {
"backgroundColor": "#000000",
"foregroundColor": "#ffffff",
"iconSize": "36px",
"iconType": "normal",
"mobile": false
},
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"layout": "horizontal",
"linkColor": "#8a3c90",
"menuItemsSpacing": {
"padding-bottom": "5px",
"padding-left": "5px",
"padding-right": "5px",
"padding-top": "5px"
}
},
"menuItemsList": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "english menu"
}
],
"translations": {
"it-IT": {
"items": [
{
"id": "a785a714-3191-434f-bea0-657f983f7a59",
"link": {
"href": "example.com",
"target": "_self",
"title": ""
},
"text": "italian menu"
}
]
}
}
},
"mobileStyle": {},
"style": {
"color": "#101112",
"font-family": "inherit",
"font-size": "16px",
"font-weight": "400",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"text-align": "center"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-menu",
"uuid": "598ecce1-4b00-4484-bb47-bb6c3b5c6b07"
},
{
"descriptor": {
"heading": {
"style": {
"color": "#274daa",
"direction": "ltr",
"font-family": "Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "50px",
"font-weight": "700",
"letter-spacing": "1px",
"line-height": "150%",
"link-color": "#09eca4",
"text-align": "left"
},
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block english</span>",
"title": "h1",
"translations": {
"it-IT": {
"text": "<span class=\"tinyMce-placeholder\">I'm a new title block italian</span>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "10px",
"padding-left": "10px",
"padding-right": "10px",
"padding-top": "10px",
"text-align": "center",
"width": "100%"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-heading",
"uuid": "e18f9584-1396-4ff0-a6a5-0fb56ac92555"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"mobileStyle": {},
"paragraph": {
"computedStyle": {
"linkColor": "#3c09ec",
"paragraphSpacing": "16px"
},
"html": "<p>I'm a new paragraph block. english</p>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"translations": {
"it-IT": {
"html": "<p>I'm a new paragraph block. italian</p>"
}
}
},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-paragraph",
"uuid": "dbeb062e-f713-422b-a7d7-10df637c0c28"
},
{
"descriptor": {
"computedStyle": {
"hideContentOnAmp": false,
"hideContentOnDesktop": false,
"hideContentOnHtml": false,
"hideContentOnMobile": false
},
"list": {
"computedStyle": {
"liIndent": "30px",
"liSpacing": "0px",
"linkColor": "#8a3b8f",
"listStylePosition": "inside",
"listStyleType": "revert",
"startList": "1"
},
"html": "<ul><li>This is an unordered list english</li></ul>",
"style": {
"color": "#393d47",
"direction": "ltr",
"font-family": "'Cabin', Arial, 'Helvetica Neue', Helvetica, sans-serif",
"font-size": "16px",
"font-weight": "400",
"letter-spacing": "0px",
"line-height": "180%",
"text-align": "left"
},
"tag": "ul",
"translations": {
"it-IT": {
"html": "<ul><li>This is an unordered list italian</li></ul>"
}
}
},
"mobileStyle": {},
"style": {
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px"
}
},
"locked": false,
"type": "mailup-bee-newsletter-modules-list",
"uuid": "12801c59-2a03-489e-b155-02c7ac843e74"
}
],
"style": {
"background-color": "transparent",
"border-bottom": "0px solid transparent",
"border-left": "0px solid transparent",
"border-right": "0px solid transparent",
"border-top": "0px solid transparent",
"padding-bottom": "5px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "5px"
},
"uuid": "56119ad2-574d-4122-8dd1-c1152b5f4879"
}
],
"container": {
"style": {
"background-color": "transparent",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat"
}
},
"content": {
"computedStyle": {
"hideContentOnDesktop": false,
"hideContentOnMobile": false,
"rowColStackOnMobile": true,
"rowReverseColStackOnMobile": false,
"verticalAlign": "top"
},
"style": {
"background-color": "#f5f5ef",
"background-image": "none",
"background-position": "top left",
"background-repeat": "no-repeat",
"color": "#000000",
"width": "700px"
}
},
"empty": false,
"locked": false,
"synced": false,
"type": "one-column-empty",
"uuid": "0922fb70-f97e-4ae8-bcfe-0be9fd09a0d5"
}
],
"template": {
"name": "template-base",
"type": "basic",
"version": "2.0.0"
},
"title": ""
}
}
}
{
"message": "Success"
}