Embedded Redactor UI¶
This guide shows how to embed the Redactor editor into your web application. The embedded editor lets users perform video redaction directly within your application's interface, providing a seamless experience without redirecting to a separate Redactor instance.
Overview¶
Embedding Redactor requires three components:
- Redactor server configured with API mode enabled
- A reverse proxy that routes requests from users' browsers to the Redactor server
- JavaScript code that renders the Redactor editor into your web page
Everything is included in our example project
Don't worry! We provide a Docker Compose example that has all of this set up and ready to run. You can follow along with the tutorial below without configuring anything yourself.
There are two deployment approaches based on where your proxy lives:
| Approach | When to Use |
|---|---|
| Same-Domain | Your web application is served from https://yourdomain.com/, and you can create a reverse proxy for Redactor like https://yourdomain.com/proxy/redactor/. This keeps cookies first-party and requires minimal configuration. |
| Cross-Domain | Redactor has a different domain or subdomain than your web application. This requires explicit CORS headers and cookie configuration but offers more deployment flexibility. |
This guide walks through the same-domain approach step by step. If you ultimately need a cross-domain deployment, we still recommend starting with the same-domain approach due to its simplicity. When ready to move on to a cross-domain deployment, you can skip to its section here.
Getting Started¶
Example Project Files¶
To help you get started quickly, Sighthound provides the Redactor API Toolkit: a package with Docker Compose example configurations for both deployment approaches, along with reference materials, and LLM-optimized documentation so you can ask your AI coding agent questions about Redactor as you work. Contact sales@sighthound.com to obtain the toolkit and an evaluation serial number.
The example project includes:
- Docker Compose file with profiles for each deployment approach
- NGINX configuration files for same-domain and cross-domain proxies
- Example HTML files demonstrating the embedded editor
- CSS override and translation files for customization
Apple Silicon Not Supported
The Redactor server currently requires an Intel/AMD (x86_64) processor. M-series Macs (Apple Silicon) are not supported at this time.
To run the same-domain example:
# Extract and enter the directory
cd sighthound-redactor-api-examples
# Start the same-domain demo environment
docker compose --profile with-same-domain-proxy up -d
If this is your first time running Redactor, set up your admin user and license at http://localhost:9000/admin.
Key Concepts¶
Before diving in, it's important to understand two concepts used throughout this guide:
Session
A redaction session represents a video along with all its associated redaction data (detected objects, manual redactions, settings, etc.). Sessions can be exported and saved, allowing users to restore and continue their work later. The same source video can be used to create multiple independent redaction sessions, each with its own sessionId.
We recommend always providing your own sessionId when making your initial MEDIA_PREPARE API requests, since it makes it easier to reference a specific session in subsequent API calls. This ID is also included in events like Operation webhooks and those emitted by the editor (such as when a user exports a video). The sessionId is immutable once set.
Project
A project is a logical container that groups one or more redaction sessions (videos) together. Projects are useful for organizing sessions by customer, case, user, or any other logical grouping that fits your application. The embedded editor displays one project at a time, showing all sessions that share the same projectId in the video list.
You must specify a projectId during the initial MEDIA_PREPARE API request. This same projectId is used when initializing the editor in JavaScript to display the correct sessions to the user.
Since the projectId controls which sessions are visible in the embedded editor, we recommend using a complex, unguessable string (such as a UUID) rather than predictable values like "customer-1". This helps prevent users from accessing sessions they shouldn't see. For stronger access control, your proxy can validate user authentication from your application and enforce project-level permissions before forwarding requests to Redactor.
Tutorial¶
This tutorial walks through loading videos, embedding the editor, and exporting redacted videos using the Docker Compose example environment.
Keep Redactor open while making API calls
We recommend opening the Redactor UI at http://localhost:9000 in your browser while working through this tutorial. It allows you to see in real-time what's happening on the server as you make API calls.
Step 1: Load Videos via API¶
Before the embedded editor can display videos, they must be loaded into Redactor using the MEDIA_PREPARE API.
You load a video by providing a path to the input video (inputUri) and an optional path where all of the redaction state data will be stored (outputUri). If an outputUri is not provided, files are stored in Redactor's internal storage and can be moved to a different location (e.g., AWS S3, Azure Blob Storage, local filesystem) in subsequent API calls.
See the videos:process API Reference for all available options and supported input/output paths (HTTP, file system, AWS S3, Azure Blob Storage, etc.).
In this example, we'll load two videos for a user to redact in the browser. We'll use the same projectId for both videos so they appear together in the editor, and each video gets a unique sessionId.
API Request
POST /api/v1/videos:process
Video 1:
curl --location --request POST 'http://localhost:9000/api/v1/videos:process' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YourRedactorApiToken' \
--data-raw '{
"inputUri": "https://sh-io-downloads.s3.amazonaws.com/videos/garage-top.mp4",
"features": ["MEDIA_PREPARE"],
"videoContext": {
"prepareConfig": {
"sessionId": "media-id-240403-1"
}
},
"projectId": "my-project-id"
}'
Video 2:
This example also includes HEAD_DETECTION in the features array, demonstrating how you can kick off auto-detection directly from the API call.
curl --location --request POST 'http://localhost:9000/api/v1/videos:process' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YourRedactorApiToken' \
--data-raw '{
"inputUri": "https://sh-io-downloads.s3.amazonaws.com/videos/Dancing.mp4",
"features": ["MEDIA_PREPARE", "HEAD_DETECTION"],
"videoContext": {
"prepareConfig": {
"sessionId": "media-id-240403-2"
}
},
"projectId": "my-project-id"
}'
API Response
Note
API calls to /api/v1/videos:process start operations that may take time to complete (e.g., loading large videos). Redactor uses an asynchronous API that returns an operation name you can use to check status. Monitor the operation by querying /api/v1/{operation-name} or by specifying a webhook endpoint for progress and completion events. Subscribing to COMPLETION events is recommended so you know when the video is ready or if errors occurred.
For more API examples, see Redactor API Basics.
Step 2: Embed the Editor¶
Once your MEDIA_PREPARE operation is complete (from Step 1), you can display the editor UI on your website.
The Docker Compose example includes a webpage that demonstrates the embedded editor running in a page your create. Open https://127.0.0.1:3443/ in your browser to see it in action. We use 127.0.0.1 instead of localhost to keep cookies separate in case you need to access Redactor directly at http://localhost:9000. You'll see a browser security warning due to the self-signed certificate—select the option to proceed. Once loaded, Redactor's Projects page will display, showing any videos you've loaded and giving you full access to the redaction tools.
The sample HTML is at config/same-domain/nginx/html/index.html in the example project. Here's a general overview:
<!-- Redactor mounts into the following container. It will size itself to fill this element. -->
<div id="redactor-editor"></div>
<script src="https://127.0.0.1:3443/proxy/redactor/public/sighthound-redactor.js"></script>
<script>
// Reference to the mount element for Redactor.
const redactorElement = document.getElementById("redactor-editor");
// The Redactor server/proxy base URL. Update this if your server
// is not running at https://127.0.0.1:3443/proxy/redactor/.
const redactorServer = "https://127.0.0.1:3443/proxy/redactor";
// Where to connect inside Redactor:
// - Use a stable projectId that matches your MEDIA_PREPARE calls.
// - Provide sessionId to open a specific video immediately, or leave
// it empty to show the project's video list first.
const redactorWhereTo = { projectId: "my-project-id", sessionId: "" };
// Create the embedded editor instance. Shadow DOM is recommended.
// When shadowed is true, include font and CSS dependencies in cssHref.
const redactorEditor = new redactor.default(
redactorElement,
redactorServer,
redactorWhereTo,
{
shadowed: true,
cssHref: {
fonts: [
"/proxy/redactor/public/sighthound-redactor-fonts.css",
],
main: [
"/proxy/redactor/public/sighthound-redactor.css",
// Optional CSS override file to customize the editor UI
"/public/sighthound-redactor-override.css",
],
},
// Customization options for the editor UI.
customize: {
export: {
download: "show", // The download button behavior: show, hide, or eventOnly
save: "show", // Displays a custom button next to the download button
},
session: {
remove: "show", // The context menu item for removing a video: show, hide, eventOnly
deleteRedactionData: "show", // The context menu item for deleting redaction data: show, hide
},
},
// Optional: overlay translation strings to change wording in the UI.
translationOverwritesUrl: "/public/translations.overlay.hjson",
}
);
// Render the editor after MEDIA_PREPARE has been completed for the target project/session.
redactorEditor.renderEditor((err) => {
if (err) { console.error("EDITOR RENDER FAILED:", err); }
});
// Observable event names for context menu, editor open/close, and export flow.
const sessionEventNames = ["redactor.session.remove", "redactor.session.delete_redaction_data"];
const editorEventNames = ["redactor.editor.enter", "redactor.editor.exit"];
const exportEventNames = ["redactor.export.cancel", "redactor.export.download", "redactor.export.save", "redactor.export.submit"];
[...editorEventNames, ...exportEventNames, ...sessionEventNames].forEach(evtName =>
redactorElement.addEventListener(evtName, evt => {
console.log("EVENT -", evt.type, "-", JSON.stringify(evt.detail, null, 4));
// Tip: For export, you can intercept and run rendering via your backend
// instead of Redactor handling it automatically by calling evt.preventDefault().
// evt.preventDefault();
})
);
// Close the currently open session. Required before making API calls that operate on the session.
function onClose() {
redactorEditor.cleanup()
.then(result => { if (result) console.log("cleanup completed"); })
.catch(err => { console.error("CLEANUP FAILED:", err); });
}
// Completely destroy the embedded editor instance and free resources.
function onDestroy() { redactorEditor.destroy(); }
// Open the export dialog for the active session.
function onExport() {
if (!redactorEditor.sendCommand("export")) {
console.warn("Export command ignored. The editor must be open/active.");
}
}
</script>
Configuration Locations
When changing your domain or proxy path, update these two locations:
- The
<script src="...">tag in the<head> - The
redactorServervariable in JavaScript
Open a Specific Video Directly
To open a specific video immediately instead of showing the project's video list, provide the sessionId:
const redactorWhereTo = {
projectId: "my-project-id",
sessionId: "video-001" // Opens this video directly
};
For the full JavaScript API documentation including constructor parameters, methods, and events, see the Embedded Editor Reference.
Step 3: Export Redacted Videos¶
To trigger a render and export, you need to tell Redactor which session to export and where to put the files. The inputUri uses the session:// scheme with the sessionId you defined when loading the video, and the outputUri points to the destination path.
Redactor determines whether to output only the redacted video or all of the redaction state based on whether the outputUri ends in a trailing slash:
- No trailing slash (e.g.,
.../redacted.mp4) — outputs only the redacted video with your specified filename - Trailing slash (e.g.,
.../output/) — outputs all redaction state, including the redacted video namedredacted.mp4
UI Export vs API Export
By default, Redactor's UI displays an Export Video button that users can click to render and download directly to their computer. If you prefer to control this process instead, you can hide the button by setting customize.export.download="hide" in the editor initialization, then trigger exports via the API using the MEDIA_RENDER feature.
API Request
POST /api/v1/videos:process
Video 1 (Export only the redacted video):
curl --location --request POST 'http://localhost:9000/api/v1/videos:process' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YourRedactorApiToken' \
--data-raw '{
"inputUri": "session://media-id-240403-1",
"features": ["MEDIA_RENDER"],
"outputUri": "file:///data/media-id-240403-1-output/redacted.mp4"
}'
Video 2 (Export all redaction state and redacted.mp4):
curl --location --request POST 'http://localhost:9000/api/v1/videos:process' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YourRedactorApiToken' \
--data-raw '{
"inputUri": "session://media-id-240403-2",
"features": ["MEDIA_RENDER"],
"outputUri": "file:///data/media-id-240403-2-output/"
}'
API Response
Operation Status¶
All requests sent to /api/v1/videos:process are asynchronous, returning an operation name that you can use to check status.
API Request
GET /api/v1/{operation-name}
Example: GET /api/v1/projects/{project-id}/locations/{location-id}/operations/{operation-id}
API Response
{
"name": "projects/{project-id}/locations/{location-id}/operations/{operation-id}",
"metadata": {
"@type": "sighthound.cloud.v1.Progress",
"progress": {
"inputUri": "http://example.com/path/to/video.mp4",
"progressPercent": 100,
"startTime": "2020-04-01T22:13:17.978847Z",
"updateTime": "2020-04-01T22:13:29.576004Z"
}
},
"done": true,
"response": {
"@type": "sighthound.cloud.v1.videos.ProcessResponse",
"processResults": {
"outputUri": "file:///data/media-id-240403-1-output/"
}
}
}
When the done value is true, the operation is complete, and either a response or error property will exist to indicate success or failure.
Webhook Notifications¶
Webhook notifications can be enabled using the notifications property in your API request. We recommend subscribing to COMPLETION events, though START and PROGRESS are also available. The Redactor server will POST messages containing the same content as the Operation Status response to the uri you provide.
Testing webhooks without a server
During evaluation, you can use webhook.site to receive and inspect webhook payloads without setting up your own server.
Example request body with webhooks:
{
"inputUri": "https://example.com/path/to/video.mp4",
"features": ["MEDIA_PREPARE"],
"videoContext": {
"prepareConfig": {
"sessionId": "my-media-id1"
}
},
"projectId": "my-project-id",
"notifications": [{
"method": "HTTP_POST",
"uri": "https://example.com/mywebhook/endpoint",
"events": ["START", "PROGRESS", "COMPLETION"]
}]
}
Customization¶
CSS Overrides¶
Create a CSS file to customize the editor's appearance:
/* Example: Hide the Redactor logo */
.sh-rui-logo {
display: none !important;
}
/* Example: Custom header background */
.sh-rui-header {
background-color: #1a365d !important;
}
Include your override file in the cssHref.main array:
cssHref: {
main: [
"/proxy/redactor/public/sighthound-redactor.css",
"/path/to/your-overrides.css"
]
}
Translation Overrides¶
Customize UI text by providing a translation overlay file in HJSON format:
{
status.exporting.complete.title: {
en-US: "Render complete"
}
button.export: {
en-US: "Process Video"
}
}
Reference the file in your options:
Production Considerations¶
When moving from the demo environment to production, you'll need to set up the following infrastructure:
Infrastructure Requirements¶
- Redactor server - Self-hosted via Docker or on Windows
- API access and Bearer Token - The API must be enabled and a bearer token specified for backend communication with Redactor's API
- HTTPS - Both your application and the Redactor proxy must use HTTPS (browsers require secure contexts for many features)
- Reverse proxy - NGINX, Apache, or another reverse proxy to route traffic to Redactor
Security¶
- Block direct Redactor access - In production, block Redactor's port 9000 from public access. All requests should go through the proxy.
- Use real TLS certificates - Replace self-signed certificates with certificates from a trusted CA.
- Enable API authentication - Configure the
REDACTOR_API_TOKENenvironment variable and require it for all API calls. - Restrict CORS origins - If using cross-domain deployment, only allow your trusted application domains in the CORS origin map.
Performance¶
- Upload timeouts - Large video uploads can take significant time. Ensure your proxy allows adequate timeouts (the examples use 3600s for uploads).
- WebSocket connections - WebSocket connections are long-lived. Configure appropriate timeouts to avoid premature disconnection.
- File size limits - Set
client_max_body_sizeappropriately for your expected video sizes (examples use 5000M).
GPU Acceleration¶
If your Redactor server supports GPU acceleration, configure the Docker deployment accordingly. See the Redactor Docker documentation for GPU setup instructions.
Same-Domain Proxy Configuration¶
When you're ready to set up your own reverse proxy instead of using the Docker Compose example, this section provides the configuration details.
The same-domain approach places the Redactor proxy under the same domain as your web application. Cookies remain first-party, so no special CORS or cookie configuration is needed.
Architecture
┌─────────────────────────────────────────────────────────┐
│ Your Domain (e.g., https://yourdomain.com) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Web Application │ │
│ │ / → Your app HTML/JS │ │
│ │ /proxy/redactor/ → Reverse proxy to Redactor │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Redactor │ │
│ │ Server │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
NGINX Configuration
The reverse proxy routes /proxy/redactor/ requests to the Redactor server. WebSocket support is required for real-time updates.
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
# Allow large video uploads
client_max_body_size 5000M;
# Your web application
location / {
root /var/www/html;
try_files $uri /index.html;
}
# Redactor reverse proxy
location /proxy/redactor/ {
proxy_pass http://redactor:9000/;
}
# WebSocket support (required)
location /proxy/redactor/socket.io {
proxy_pass http://redactor:9000/socket.io;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
If Redactor is running on a different host or port, update the proxy_pass values accordingly.
Cross-Domain Deployment¶
Use the cross-domain approach when the Redactor proxy must live on a different domain than your web application. This is common when:
- Your application infrastructure doesn't allow adding proxy paths
- You want to centralize Redactor access for multiple applications
- Network architecture requires separation of concerns
Architecture¶
┌────────────────────────────────┐ ┌────────────────────────────────┐
│ Your App Domain │ │ Redactor Domain │
│ e.g. https://app.example.com │ │ https://redactor.example.com │
│ │ │ │
│ ┌──────────────────────────┐ │ │ ┌──────────────────────────┐ │
│ │ Web Application │ │────▶│ │ NGINX Proxy │ │
│ │ (embeds Redactor) │ │ │ │ + CORS Headers │ │
│ └──────────────────────────┘ │ │ │ + Cookie Config │ │
│ │ │ └────────────┬─────────────┘ │
└────────────────────────────────┘ │ │ │
│ ▼ │
│ ┌──────────────────────────┐ │
│ │ Redactor Server │ │
│ └──────────────────────────┘ │
└────────────────────────────────┘
NGINX Configuration¶
Docker Compose Example Includes a Complete Demo Environment
If you're using the provided Docker Compose example with --profile with-cross-domain-proxy, everything is included to get a working demo up and running:
- Redactor server - The core redaction service
- NGINX reverse proxy - Pre-configured with CORS headers and cookie settings for cross-domain access
- Sample web page - A separate site (simulating your application) that embeds the Redactor editor
Simply run the Docker Compose command, then:
- Open
https://127.0.0.1:3443/first and accept the self-signed certificate warning - Open
https://127.0.0.1:4443/to see the embedded editor running on a separate domain
No configuration changes are required to try the demo. For production, you'll need to update the CORS origin map to include your application's domain(s).
Cross-domain embedding requires explicit CORS headers and cookie configuration. The proxy must:
- Allow your application's origin in CORS headers
- Set cookies with
SameSite=Noneso they work cross-origin - Handle preflight OPTIONS requests for CORS
# Map trusted origins for CORS (update for your domains)
map $http_origin $cors_origin {
default "";
"https://app.example.com" "https://app.example.com";
"https://staging.example.com" "https://staging.example.com";
}
server {
listen 443 ssl;
server_name redactor.example.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
# Reverse proxy headers
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts and limits
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 60s;
proxy_buffering off;
client_max_body_size 5000M;
# General API routes
location / {
# Replace backend CORS headers with our trusted ones
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Credentials;
# CORS preflight handling
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
return 204;
}
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
proxy_pass http://redactor:9000/;
# Required for cross-origin cookies
proxy_cookie_flags connect.sid Secure HttpOnly SameSite=None;
}
# File uploads (extended timeouts)
location /upload {
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Credentials;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
return 204;
}
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
proxy_pass http://redactor:9000/;
# Large file uploads may take a long time
proxy_connect_timeout 10s;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
client_max_body_size 5000M;
}
# WebSocket support
location /socket.io {
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Credentials;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
return 204;
}
add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
proxy_pass http://redactor:9000/socket.io;
# WebSocket upgrade headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cookie_flags connect.sid Secure HttpOnly SameSite=None;
# Long-lived WebSocket connections
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 3600s;
}
}
CORS Origin Configuration
Update the map $http_origin block to include only your trusted application domains. An empty default value ensures unknown origins are rejected.
HTML/JavaScript Integration¶
When embedding cross-domain, you must use absolute URLs for the Redactor script and CSS files:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Your Web App</title>
<!-- Load the Redactor script from the proxy domain -->
<script src="https://redactor.example.com/public/sighthound-redactor.js"></script>
</head>
<body>
<div id="redactor-editor" style="width: 100vw; height: 100vh;"></div>
<script>
const redactorElement = document.getElementById("redactor-editor");
const redactorServer = "https://redactor.example.com";
const redactorWhereTo = { projectId: "my-project-id" };
const redactorEditor = new redactor.default(
redactorElement,
redactorServer,
redactorWhereTo,
{
shadowed: true,
cssHref: {
// Must use absolute URLs for cross-domain
fonts: ["https://redactor.example.com/public/sighthound-redactor-fonts.css"],
main: ["https://redactor.example.com/public/sighthound-redactor.css"],
},
}
);
redactorEditor.renderEditor((err) => {
if (err) {
console.error("Editor render failed:", err);
} else {
console.log("Editor rendered successfully");
}
});
</script>
</body>
</html>
Configuration Locations
When changing your proxy domain, update these four locations:
- The
<script src="...">tag in the<head> - The
redactorServervariable in JavaScript - The
cssHref.fontsURL - The
cssHref.mainURL
Troubleshooting Cross-Domain Issues¶
If the embedded editor fails to load or authenticate:
- Open browser developer tools and check the Console and Network tabs for errors
- Verify CORS headers - Look for
Access-Control-Allow-Originin response headers; it should match your application's origin - Check cookie settings - The
connect.sidcookie must haveSameSite=NoneandSecureattributes - Accept self-signed certificates - During development with self-signed certs, open the proxy URL directly in your browser first and accept the security warning
Contact Support¶
If you encounter issues, you can find the Redactor logs at the following location in the example project. Note: you may need to sudo to access the logs:
Review the logs for error messages, or send them to support@redactor.com for assistance. You can also submit logs directly from within the Redactor app by following the instructions on our Support page.