Events
Listen to embed events and request template content programmatically
The embed communicates with your parent page through postMessage events. You can listen for events when users save templates or download images, and request template content in any format.
Event Types
| Event | Description |
|---|---|
orshot:template:create | Fired when a new template is created |
orshot:template:update | Fired when an existing template is saved |
orshot:download:png | Fired when downloaded as PNG |
orshot:download:pdf | Fired when downloaded as PDF |
orshot:download:html | Fired when downloaded as HTML |
orshot:template:content | Response with requested template content |
orshot:error | Error response for failed requests |
Listening to Events
Set up a message listener to receive events from the embed:
window.addEventListener("message", (event) => {
// Verify the origin
if (!event.origin.includes("orshot.com")) return;
const { type, data, timestamp } = event.data;
switch (type) {
case "orshot:template:create":
console.log("Template created:", data);
break;
case "orshot:template:update":
console.log("Template updated:", data);
break;
case "orshot:download:png":
console.log("PNG downloaded:", data);
break;
case "orshot:download:pdf":
console.log("PDF downloaded:", data);
break;
case "orshot:download:html":
console.log("HTML downloaded:", data);
break;
case "orshot:template:content":
console.log("Template content received:", data);
break;
case "orshot:error":
console.error("Embed error:", event.data.error);
break;
}
});Event Payloads
Template Events
When a user creates or updates a template:
{
type: "orshot:template:create", // or "orshot:template:update"
timestamp: "2024-01-15T10:30:00.000Z",
data: {
id: 123,
name: "My Design",
workspaceId: 50
}
}Download Events
When a user downloads from the embed:
// Single page download
{
type: "orshot:download:png",
timestamp: "2024-01-15T10:30:00.000Z",
data: {
templateId: 123,
templateName: "My Design",
pageIndex: 0,
scale: 2,
content: "data:image/png;base64,..." // base64 data URL
}
}
// Multi-page download
{
type: "orshot:download:png",
timestamp: "2024-01-15T10:30:00.000Z",
data: {
action: "zip", // "zip" for PNG/HTML, "multipage" for PDF
templateId: 123,
templateName: "My Design",
pageCount: 3,
scale: 2
}
}
// Copy to clipboard
{
type: "orshot:download:png",
timestamp: "2024-01-15T10:30:00.000Z",
data: {
action: "clipboard",
templateId: 123,
templateName: "My Design",
pageIndex: 0,
scale: 2,
content: "data:image/png;base64,..."
}
}Formats and their MIME types:
| Format | MIME Type |
|---|---|
| png | image/png |
| application/pdf | |
| html | text/html |
Requesting Template Content
You can request the current template content from your parent page. Send a message to the embed iframe and receive the content in your preferred format.
Request Message Format
{
type: "orshot:request:template",
requestId: "unique-request-id",
format: "png" // png, pdf, or html
}Sending a Request
const iframe = document.querySelector("iframe");
const requestId = `req-${Date.now()}`;
// Send request to embed
iframe.contentWindow.postMessage(
{
type: "orshot:request:template",
requestId: requestId,
format: "png", // png, pdf, or html
},
"https://orshot.com" // Target origin - use your embed URL origin
);Handling the Response
window.addEventListener("message", (event) => {
if (!event.origin.includes("orshot.com")) return;
if (event.data.type === "orshot:template:content") {
const { requestId, data } = event.data;
// data contains:
// - content: base64 data URL or HTML string
// - format: requested format
// - mimeType: content MIME type
// - templateId: template ID
// - templateName: template name
console.log("Received content:", data.format);
// Example: Create download from content
if (data.format === "png") {
const link = document.createElement("a");
link.href = data.content;
link.download = `${data.templateName}.png`;
link.click();
}
}
if (event.data.type === "orshot:error") {
console.error("Request failed:", event.data.error);
}
});Complete Example
Here's a full example that requests template content and handles the response:
class OrshotEmbedManager {
constructor(iframeSelector) {
this.iframe = document.querySelector(iframeSelector);
this.pendingRequests = new Map();
this.setupListener();
}
setupListener() {
window.addEventListener("message", (event) => {
if (!event.origin.includes("orshot.com")) return;
const { type, requestId, data, error } = event.data;
// Handle content response
if (type === "orshot:template:content" && requestId) {
const resolver = this.pendingRequests.get(requestId);
if (resolver) {
resolver.resolve(data);
this.pendingRequests.delete(requestId);
}
}
// Handle error response
if (type === "orshot:error" && requestId) {
const resolver = this.pendingRequests.get(requestId);
if (resolver) {
resolver.reject(new Error(error));
this.pendingRequests.delete(requestId);
}
}
// Handle save events
if (type === "orshot:template:create") {
this.onTemplateCreate?.(data);
}
if (type === "orshot:template:update") {
this.onTemplateUpdate?.(data);
}
// Handle download events
if (type.startsWith("orshot:download:")) {
this.onDownload?.(data);
}
});
}
requestContent(format = "png") {
return new Promise((resolve, reject) => {
const requestId = `req-${Date.now()}`;
this.pendingRequests.set(requestId, { resolve, reject });
this.iframe.contentWindow.postMessage(
{
type: "orshot:request:template",
requestId,
format,
},
"https://orshot.com" // Target origin - use your embed URL origin
);
// Timeout after 30 seconds
setTimeout(() => {
if (this.pendingRequests.has(requestId)) {
this.pendingRequests.delete(requestId);
reject(new Error("Request timed out"));
}
}, 30000);
});
}
}
// Usage
const manager = new OrshotEmbedManager("iframe");
// Listen to events
manager.onTemplateCreate = (data) => console.log("Created:", data);
manager.onTemplateUpdate = (data) => console.log("Updated:", data);
manager.onDownload = (data) => console.log("Downloaded:", data);
// Request content
const pngContent = await manager.requestContent("png");
const htmlContent = await manager.requestContent("html");
const pdfContent = await manager.requestContent("pdf");React Example
import { useEffect, useRef, useCallback } from "react";
function useOrshotEmbed() {
const embedRef = useRef(null);
const pendingRequests = useRef(new Map());
useEffect(() => {
const handleMessage = (event) => {
if (!event.origin.includes("orshot.com")) return;
const { type, requestId, data, error } = event.data;
if (type === "orshot:template:content" && requestId) {
const resolver = pendingRequests.current.get(requestId);
if (resolver) {
resolver.resolve(data);
pendingRequests.current.delete(requestId);
}
}
if (type === "orshot:error" && requestId) {
const resolver = pendingRequests.current.get(requestId);
if (resolver) {
resolver.reject(new Error(error));
pendingRequests.current.delete(requestId);
}
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
const requestContent = useCallback((format = "png") => {
return new Promise((resolve, reject) => {
const requestId = `req-${Date.now()}`;
pendingRequests.current.set(requestId, { resolve, reject });
embedRef.current?.contentWindow?.postMessage(
{ type: "orshot:request:template", requestId, format },
"https://orshot.com" // Target origin - use your embed URL origin
);
setTimeout(() => {
if (pendingRequests.current.has(requestId)) {
pendingRequests.current.delete(requestId);
reject(new Error("Request timed out"));
}
}, 30000);
});
}, []);
return { embedRef, requestContent };
}
// Usage
function DesignEditor() {
const { embedRef, requestContent } = useOrshotEmbed();
const handleExport = async (format) => {
try {
const content = await requestContent(format);
console.log("Got content:", content);
} catch (error) {
console.error("Export failed:", error);
}
};
return (
<div>
<iframe ref={embedRef} src="https://orshot.com/embeds/abc123" />
<button onClick={() => handleExport("png")}>Export PNG</button>
<button onClick={() => handleExport("pdf")}>Export PDF</button>
<button onClick={() => handleExport("html")}>Export HTML</button>
</div>
);
}Enable Events
Events must be enabled in your embed settings. Go to your workspace embed configuration and toggle Enable Events to start receiving events.
When disabled, the embed won't send any postMessage events to your parent page.
Get Template HTML on Create/Update
A common use case is to automatically fetch the template HTML whenever a user creates or updates a template. This allows you to sync the design content with your backend or display it elsewhere.
const iframe = document.querySelector("iframe");
window.addEventListener("message", async (event) => {
if (!event.origin.includes("orshot.com")) return;
const { type, data } = event.data;
// Listen for template create or update events
if (type === "orshot:template:create" || type === "orshot:template:update") {
console.log(
`Template ${type === "orshot:template:create" ? "created" : "updated"}:`,
data
);
// Request the HTML content
const requestId = `html-${Date.now()}`;
iframe.contentWindow.postMessage(
{
type: "orshot:request:template",
requestId: requestId,
format: "html",
},
"https://orshot.com" // Target origin - use your embed URL origin
);
}
// Handle the HTML content response
if (type === "orshot:template:content") {
const { content, format, templateId, templateName } = event.data.data;
if (format === "html") {
console.log("Received HTML for template:", templateName);
// Example: Send to your backend
await fetch("/api/templates/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
templateId,
templateName,
html: content,
}),
});
// Or store locally
localStorage.setItem(`template-${templateId}-html`, content);
// Or render in a preview container
document.getElementById("preview").innerHTML = content;
}
}
});React Example
import { useEffect, useRef, useState } from "react";
function DesignEditorWithAutoSync() {
const embedRef = useRef(null);
const [lastSavedHtml, setLastSavedHtml] = useState(null);
const [templateInfo, setTemplateInfo] = useState(null);
useEffect(() => {
const handleMessage = (event) => {
if (!event.origin.includes("orshot.com")) return;
const { type, data, requestId } = event.data;
// Auto-request HTML on create/update
if (
type === "orshot:template:create" ||
type === "orshot:template:update"
) {
setTemplateInfo(data);
// Request HTML content
embedRef.current?.contentWindow?.postMessage(
{
type: "orshot:request:template",
requestId: `auto-html-${Date.now()}`,
format: "html",
},
"https://orshot.com" // Target origin - use your embed URL origin
);
}
// Handle HTML response
if (
type === "orshot:template:content" &&
event.data.data.format === "html"
) {
setLastSavedHtml(event.data.data.content);
// Sync with your backend
syncWithBackend(event.data.data);
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
const syncWithBackend = async (data) => {
try {
await fetch("/api/templates/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
templateId: data.templateId,
html: data.content,
}),
});
} catch (error) {
console.error("Sync failed:", error);
}
};
return (
<div>
<iframe ref={embedRef} src="https://orshot.com/embeds/abc123" />
{templateInfo && (
<p>
Last saved: {templateInfo.name} (ID: {templateInfo.id})
</p>
)}
</div>
);
}