Orshot Logo
OrshotDocs
Orshot Embed

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

EventDescription
orshot:template:createFired when a new template is created
orshot:template:updateFired when an existing template is saved
orshot:download:pngFired when downloaded as PNG
orshot:download:pdfFired when downloaded as PDF
orshot:download:htmlFired when downloaded as HTML
orshot:template:contentResponse with requested template content
orshot:errorError 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:

FormatMIME Type
pngimage/png
pdfapplication/pdf
htmltext/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>
  );
}

On this page