Custom Asset Picker
Let your users pick images, videos, fonts, and colors from your own library
Custom Asset Picker is available on the Agency plan and above.
The Custom Asset Picker lets you replace the default file upload dialogs with your own asset selection UI. When a user needs to insert an image, video, font, or color, the embed sends an event to your parent page — you show your own picker, and send the selected asset back.
This is useful when you already have an asset library (DAM, media gallery, brand kit) and want your users to pick from it instead of uploading files manually.
How It Works#
- User clicks "Insert Image" (or video, font, color) in the embed
- The embed sends an
orshot:asset:requestevent to your parent page - Your app opens its own picker UI
- User selects an asset in your UI
- Your app sends an
orshot:asset:responsemessage back to the embed - The embed downloads the asset from the URL you provide and saves it to the user's library
Enabling Custom Asset Picker#
- Go to your embed settings
- Under Custom Asset Picker, enable the asset types you want to handle (image, video, font, color)
- Save your settings
You can enable the picker for specific asset types independently — for example, handle only images and colors from your library while letting users upload fonts normally.
Handling Asset Requests#
Listen for orshot:asset:request events from the embed:
window.addEventListener("message", (event) => {
if (!event.origin.includes("orshot.com")) return;
if (event.data.type === "orshot:asset:request") {
const { type, requestId } = event.data.data;
// type: "image", "video", "font", or "color"
// requestId: unique ID to match your response
openYourAssetPicker(type, requestId);
}
});Sending Asset Responses#
Once the user picks an asset, send it back to the embed. The response format varies by asset type.
Image#
const iframe = document.querySelector("iframe");
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId: "the-request-id",
url: "https://your-cdn.com/images/photo.jpg",
fileName: "photo.jpg", // optional
},
"*"
);Video#
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId: "the-request-id",
url: "https://your-cdn.com/videos/clip.mp4",
fileName: "clip.mp4", // optional
},
"*"
);Font#
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId: "the-request-id",
url: "https://your-cdn.com/fonts/CustomFont.woff2",
fontFamily: "Custom Font", // required — the display name
},
"*"
);Color#
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId: "the-request-id",
value: "#FF6B00", // hex color value
},
"*"
);What Happens After You Respond#
The embed takes care of everything after you send the response:
- Images/Videos: Downloads the file from your URL, uploads it to the user's workspace storage, and adds it to their asset library
- Fonts: Downloads the font file, uploads it to storage, registers it so it's available in the font picker
- Colors: Saves the hex value to the user's saved colors
The asset is permanently available in the user's library for future use — they don't need to re-pick it.
Complete Example#
const iframe = document.querySelector("iframe");
window.addEventListener("message", (event) => {
if (!event.origin.includes("orshot.com")) return;
if (event.data.type === "orshot:asset:request") {
const { type, requestId } = event.data.data;
// Open your custom picker based on asset type
switch (type) {
case "image":
showImagePicker((selectedImage) => {
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId,
url: selectedImage.url,
fileName: selectedImage.name,
},
"*"
);
});
break;
case "font":
showFontPicker((selectedFont) => {
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId,
url: selectedFont.fileUrl,
fontFamily: selectedFont.name,
},
"*"
);
});
break;
case "color":
showColorPicker((hex) => {
iframe.contentWindow.postMessage(
{
type: "orshot:asset:response",
requestId,
value: hex,
},
"*"
);
});
break;
}
}
});React Example#
import { useEffect, useRef, useState } from "react";
function EmbedWithAssetPicker() {
const iframeRef = useRef(null);
const [pickerState, setPickerState] = useState(null);
useEffect(() => {
const handleMessage = (event) => {
if (!event.origin.includes("orshot.com")) return;
if (event.data.type === "orshot:asset:request") {
const { type: assetType, requestId } = event.data.data;
setPickerState({ assetType, requestId });
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
const handleAssetSelected = (asset) => {
if (!pickerState) return;
const response = {
type: "orshot:asset:response",
requestId: pickerState.requestId,
};
if (pickerState.assetType === "color") {
response.value = asset.hex;
} else if (pickerState.assetType === "font") {
response.url = asset.url;
response.fontFamily = asset.name;
} else {
response.url = asset.url;
response.fileName = asset.name;
}
iframeRef.current?.contentWindow?.postMessage(response, "*");
setPickerState(null);
};
return (
<div>
<iframe
ref={iframeRef}
src="https://orshot.com/embeds/YOUR_EMBED_ID"
style={{ width: "100%", height: "700px" }}
/>
{pickerState && (
<YourAssetPickerModal
type={pickerState.assetType}
onSelect={handleAssetSelected}
onClose={() => setPickerState(null)}
/>
)}
</div>
);
}Asset URL Requirements#
- URLs must be publicly accessible (the embed server downloads the file)
- HTTPS is required for production
- Private/internal URLs (localhost, 10.x.x.x, 192.168.x.x) are blocked
- Maximum file size: 10 MB
- Supported formats:
- Images: PNG, JPEG, GIF, WebP, SVG, AVIF
- Videos: MP4, WebM, MOV
- Fonts: WOFF, WOFF2, TTF, OTF
Event Reference#
| Event | Direction | Description |
|---|---|---|
orshot:asset:request | Embed → Parent | User wants to pick an asset |
orshot:asset:response | Parent → Embed | Your app sends the selected asset |
Request Payload#
{
type: "orshot:asset:request",
timestamp: "2024-01-15T10:30:00.000Z",
data: {
type: "image", // "image", "video", "font", or "color"
requestId: "req-abc123"
}
}Response Payload (Image/Video)#
{
type: "orshot:asset:response",
requestId: "req-abc123",
url: "https://...",
fileName: "optional-name.jpg"
}Response Payload (Font)#
{
type: "orshot:asset:response",
requestId: "req-abc123",
url: "https://...",
fontFamily: "Font Display Name" // required
}Response Payload (Color)#
{
type: "orshot:asset:response",
requestId: "req-abc123",
value: "#FF6B00"
}Ready to automate?
Start rendering images, PDFs and videos from your templates in under 2 minutes. Free plan, no credit card.
Get your API key- Image, PDF and video generation via API
- Visual editor with AI and smart layouts
- Zapier, Make, MCP and 50+ integrations
- White-label embed for your own app
- 60 free renders — no credit card required