Redactor 4 Configuration Guide
Last Updated: January 2026
Related Files:
client/js/crm/editors/redactor4.js- Base configurations and pluginsapp/javascript/controllers/redactor4_init_controller.js- Stimulus initializationapp/inputs/redactor_input.rb- SimpleForm custom input
Overview
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.
Editor Modes Comparison
| Feature | Blog | Default | Air (Notes) | Readonly | |
|---|---|---|---|---|---|
| Base Options | defaultRedactor4Options + aiRedactor4Options |
emailRedactor4Options |
defaultRedactor4Options |
simpleNotesRedactor4Options |
Any + disabled |
| Min Height | 2000px | 500px | 300px | 100px | Inherited |
| Pathbar | Hidden | Hidden | Hidden | Hidden | Hidden |
| Source Code | Via data attr | Via data attr | Via data attr | No | No |
| Toolbar | External (#redactor-blog-toolbar) | Sticky (72px offset) | Sticky (72px offset) | Air (floating) | Hidden |
| CSS Injection | WWW styles | CodeMirror custom CSS | None | None | None |
| AI Tools | ✅ | ❌ | ❌ | ❌ | ❌ |
| Context Menu | ✅ | ❌ | ✅ | ❌ | ❌ |
Plugin Availability by Mode
| Plugin | Blog | Default | Air | Description | |
|---|---|---|---|---|---|
| alignment | ✅ | ✅ | ✅ | ❌ | Text alignment |
| counter | ✅ | ✅ | ✅ | ❌ | Word/character count |
| fullscreen | ✅ | ✅ | ✅ | ❌ | Fullscreen editing |
| imageresize | ✅ | ❌ | ✅ | ❌ | Visual image resizing |
| fontcolor | ✅ | ✅ | ✅ | ❌ | Text color |
| fontfamily | ✅ | ✅ | ✅ | ❌ | Font family |
| fontsize | ✅ | ✅ | ✅ | ❌ | Font size |
| blockcolor | ✅ | ✅ | ✅ | ❌ | Block text color |
| blockbackground | ✅ | ✅ | ✅ | ❌ | Block background |
| blockborder | ✅ | ✅ | ✅ | ❌ | Block borders |
| blockfontsize | ✅ | ✅ | ✅ | ❌ | Block font size |
| wyimage | ✅ | ✅ | ✅ | ❌ | WY Image Library picker |
| wyembed | ✅ | ❌ | ✅ | ❌ | oEmbed (YouTube, etc.) |
| wyvideo | ✅ | ❌ | ❌ | ❌ | WY Video Library picker |
| wyfaq | ✅ | ❌ | ❌ | ❌ | WY FAQ Library picker |
| ai | ✅ | ❌ | ❌ | ❌ | OpenAI text/image tools |
| mergetag | ❌ | ✅ | ❌ | ❌ | Liquid merge tags |
| clips | ❌ | ✅ | ❌ | ❌ | Email snippets |
| variable | ❌ | ✅ | ❌ | ❌ | Variable insertion |
| ❌ | ✅ | ❌ | ❌ | Email formatting | |
| wyemailblocks | ❌ | ✅ | ❌ | ❌ | WY Header/Footer blocks |
Mode Detection Logic
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;
Priority Order:
- Air Mode -
data-redactor4-init-air-value="true" - Email Mode -
editor.id === 'redactor-email-template-body-v4'ORdata-redactor4-init-email-value="true" - Blog Mode -
editor.id === 'redactor-blog'ORdata-redactor4-init-blog-value="true" - Default Mode - Fallback
Usage Examples
1. Blog Editor (Full Featured)
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-bodyclass applied for styling
2. Email Template Editor
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
3. Default Editor (Standard)
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>
4. Air Mode (Minimal Notes)
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
5. Readonly Preview
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>
Stimulus Controller Values
| Value | Type | Description |
|---|---|---|
blog |
Boolean | Enable blog mode with AI, FAQ, Video plugins |
email |
Boolean | Enable email mode with merge tags |
air |
Boolean | Enable minimal air mode (floating toolbar) |
minHeight |
String | Override minimum height (e.g., "500px") |
plugins |
Array | Override plugin list |
source |
Boolean | Enable HTML source editing (admin only) |
readonly |
Boolean | Disable editing, hide toolbar |
legacyBody |
String | Legacy v3 content for migration |
Custom WY Plugins
WY Image (wyimage)
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>
WY Video (wyvideo)
Video picker that integrates with the Video Library. Uses oEmbed API.
Blog only - Not available in email or default modes.
WY FAQ (wyfaq)
FAQ picker that embeds FAQ accordion blocks. Uses oEmbed API.
Blog only - Not available in email or default modes.
WY Embed (wyembed)
Enhanced oEmbed for external content (YouTube, Vimeo, etc.).
Not available in email mode - Email clients don't support iframes.
WY Email Blocks (wyemailblocks)
Quick insertion of branded email header/footer.
Email only - Not available in other modes.
Configuration Files
Base Configurations (redactor4.js)
// Exported configurations:
window.defaultRedactor4Options // Standard editor
window.emailRedactor4Options // Email templates
window.aiRedactor4Options // AI + wyfaq + wyvideo (merged for blog)
window.simpleNotesRedactor4Options // Air mode
Paste Settings
Default/Blog Mode:
clean: true- Sanitize for XSS protectionplaintext: false- Keep HTML formattingstripAttr.allowedClasses- Whitelist of Bootstrap 5.3 + blog classesstripAttr.allowedAttributes- Safe attributes only (nostyle)
Email Mode:
plaintext: true- Convert to plain text
Air Mode:
plaintext: true- Convert to plain text
CSS Class Handling
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.
Troubleshooting
Editor not initializing
- Check browser console for errors
- Verify Stimulus controller is connected:
📝 Redactor4 Stimulus controller connected - Check if element has correct data attributes
- Verify lazy loading:
📝 Redactor 4 module loaded
Toolbar missing
- For blog: Check
#redactor-blog-toolbarexists in DOM - For email/default: Check
toolbar.stickyTopOffsetis correct (72px for CRM navbar) - For readonly: Toolbar is intentionally hidden
Plugins not working
- Check plugin is in the correct options set
- Check browser console for plugin errors
- Verify plugin JS is imported in
redactor4.js
Images not cropping correctly
- Verify
Oembed::ImageProvideris handling crop params - Check that crop dimensions aren't being upscaled beyond their size
- Verify ImageKit transformation string is correct