Skip to content

Redactor 4 Configuration Guide

Last Updated: January 2026
Related Files:

  • client/js/crm/editors/redactor4.js - Base configurations and plugins
  • app/javascript/controllers/redactor4_init_controller.js - Stimulus initialization
  • app/inputs/redactor_input.rb - SimpleForm custom input

Redactor 4 is the WYSIWYG editor used throughout the CRM for rich text editing. It supports multiple modes depending on the use case, from full-featured blog editing to minimal note-taking.


FeatureBlogEmailDefaultAir (Notes)Readonly
Base OptionsdefaultRedactor4Options + aiRedactor4OptionsemailRedactor4OptionsdefaultRedactor4OptionssimpleNotesRedactor4OptionsAny + disabled
Min Height2000px500px300px100pxInherited
PathbarHiddenHiddenHiddenHiddenHidden
Source CodeVia data attrVia data attrVia data attrNoNo
ToolbarExternal (#redactor-blog-toolbar)Sticky (72px offset)Sticky (72px offset)Air (floating)Hidden
CSS InjectionWWW stylesCodeMirror custom CSSNoneNoneNone
AI Tools
Context Menu

PluginBlogEmailDefaultAirDescription
alignmentText alignment
counterWord/character count
fullscreenFullscreen editing
imageresizeVisual image resizing
fontcolorText color
fontfamilyFont family
fontsizeFont size
blockcolorBlock text color
blockbackgroundBlock background
blockborderBlock borders
blockfontsizeBlock font size
wyimageWY Image Library picker
wyembedoEmbed (YouTube, etc.)
wyvideoWY Video Library picker
wyfaqWY FAQ Library picker
aiOpenAI text/image tools
mergetagLiquid merge tags
clipsEmail snippets
variableVariable insertion
emailEmail formatting
wyemailblocksWY Header/Footer blocks

The Stimulus controller (redactor4_init_controller.js) detects which mode to use:

// In initializeRedactor4()
const isEmailEditor = editor.id === 'redactor-email-template-body-v4' ||
(this.hasEmailValue && this.emailValue);
const isBlogEditor = (this.hasBlogValue && this.blogValue) ||
editor.id === 'redactor-blog';
const isAirMode = this.hasAirValue && this.airValue;
  1. Air Mode - data-redactor4-init-air-value="true"
  2. Email Mode - editor.id === 'redactor-email-template-body-v4' OR data-redactor4-init-email-value="true"
  3. Blog Mode - editor.id === 'redactor-blog' OR data-redactor4-init-blog-value="true"
  4. Default Mode - Fallback

Used in: app/views/crm/posts/_content.html.erb

<div data-controller="redactor4-init"
data-redactor4-init-blog-value="true"
data-redactor4-init-source-value="<%= current_user&.admin? %>">
<%= f.input_field :solution,
id: 'redactor-blog',
class: 'form-control',
data: {
redactor4_init_target: 'editor',
www_css: webpack_css_url('www').to_json
} %>
</div>

Blog-specific features:

  • External toolbar in sticky header (#redactor-blog-toolbar)
  • WWW CSS injected for WYSIWYG preview
  • 2000px minimum height
  • AI tools, FAQ picker, Video picker enabled
  • blog-post-body class applied for styling

Used in: app/views/email_templates/_form.html.erb

<div data-controller="redactor4-init"
data-redactor4-init-email-value="true">
<%= f.text_area :body,
id: 'redactor-email-template-body-v4',
class: 'form-control',
data: { redactor4_init_target: 'editor' } %>
</div>

Email-specific features:

  • Liquid merge tags (recipient, sender, etc.)
  • Email clips (header, footer snippets)
  • WY Email Blocks plugin
  • Custom CSS injection from CodeMirror
  • Paste converts to plain text

Used in: Most forms via SimpleForm input

<%= f.input :description, as: :redactor %>

Or manually:

<div data-controller="redactor4-init">
<%= f.text_area :body,
class: 'form-control',
data: { redactor4_init_target: 'editor' } %>
</div>

Used in: Activity notes, comments

<div data-controller="redactor4-init"
data-redactor4-init-air-value="true">
<%= f.text_area :notes,
class: 'form-control',
data: { redactor4_init_target: 'editor' } %>
</div>

Air mode features:

  • Floating toolbar (appears on selection)
  • Minimal buttons: bold, italic, deleted, list
  • No plugins loaded
  • Plain text paste

Any mode can be made readonly:

<div data-controller="redactor4-init"
data-redactor4-init-readonly-value="true">
<%= f.text_area :preview,
class: 'form-control',
data: { redactor4_init_target: 'editor' } %>
</div>

ValueTypeDescription
blogBooleanEnable blog mode with AI, FAQ, Video plugins
emailBooleanEnable email mode with merge tags
airBooleanEnable minimal air mode (floating toolbar)
minHeightStringOverride minimum height (e.g., “500px”)
pluginsArrayOverride plugin list
sourceBooleanEnable HTML source editing (admin only)
readonlyBooleanDisable editing, hide toolbar
legacyBodyStringLegacy v3 content for migration

Image picker that integrates with the Image Library. Uses oEmbed API for rich HTML insertion.

Features:

  • Image search and selection
  • Visual cropping with Cropper.js
  • All ImageKit transformations (resize, rotate, blur, etc.)
  • Responsive srcset generation
  • Caption support
  • Re-editing existing images

Inserted HTML structure:

<figure class="wy-image-embed" data-wy-image-id="123" data-wy-image-options="{...}">
<img src="..." srcset="..." alt="..." loading="lazy" class="img-fluid">
<figcaption class="figure-caption">Caption here</figcaption>
</figure>

Video picker that integrates with the Video Library. Uses oEmbed API.

Blog only - Not available in email or default modes.

FAQ picker that embeds FAQ accordion blocks. Uses oEmbed API.

Blog only - Not available in email or default modes.

Enhanced oEmbed for external content (YouTube, Vimeo, etc.).

Not available in email mode - Email clients don’t support iframes.

Quick insertion of branded email header/footer.

Email only - Not available in other modes.


// Exported configurations:
window.defaultRedactor4Options // Standard editor
window.emailRedactor4Options // Email templates
window.aiRedactor4Options // AI + wyfaq + wyvideo (merged for blog)
window.simpleNotesRedactor4Options // Air mode

Default/Blog Mode:

  • clean: true - Sanitize for XSS protection
  • plaintext: false - Keep HTML formatting
  • stripAttr.allowedClasses - Whitelist of Bootstrap 5.3 + blog classes
  • stripAttr.allowedAttributes - Safe attributes only (no style)

Email Mode:

  • plaintext: true - Convert to plain text

Air Mode:

  • plaintext: true - Convert to plain text

The paste settings include a whitelist of allowed CSS classes for security:

  • Blog classes: blogLeft, blogRight, blog-cta, blog-post-body, etc.
  • Bootstrap 5.3: Spacing, display, flexbox, text, colors, tables, etc.
  • Redactor alignment: wrap-center, wrap-left, wrap-right, etc.

See defaultRedactor4Options.paste.stripAttr.allowedClasses for full list.


  1. Check browser console for errors
  2. Verify Stimulus controller is connected: 📝 Redactor4 Stimulus controller connected
  3. Check if element has correct data attributes
  4. Verify lazy loading: 📝 Redactor 4 module loaded
  1. For blog: Check #redactor-blog-toolbar exists in DOM
  2. For email/default: Check toolbar.stickyTopOffset is correct (72px for CRM navbar)
  3. For readonly: Toolbar is intentionally hidden
  1. Check plugin is in the correct options set
  2. Check browser console for plugin errors
  3. Verify plugin JS is imported in redactor4.js
  1. Verify Oembed::ImageProvider is handling crop params
  2. Check that crop dimensions aren’t being upscaled beyond their size
  3. Verify ImageKit transformation string is correct