Search Docs
Loading...
Skip to content

Export to HTML5

Export CE.SDK designs as HTML5 bundles containing HTML, images and fonts — ready for distribution as display ads or interactive web content.

Export to HTML5

15 mins
estimated time
Download
StackBlitz
GitHub

The @imgly/html-exporter package converts a CE.SDK scene page into an HTML5 bundle using exportHtml(engine, options). The result is a FileMap — a standard Map extended with a toZip() method — that you can inspect, customize with additional files and scripts, then package as a ZIP for delivery.

This guide covers exporting scenes as HTML5, choosing between external and embedded formats, injecting GSAP for animated playback, and customizing the output with click tracking, metadata, and extra files.

Getting Started#

Install the @imgly/html-exporter package and import exportHtml and optionally injectGsapPlayer.

import { exportHtml, injectGsapPlayer } from '@imgly/html-exporter';

Exporting a Scene Page#

Call exportHtml() with the engine instance and an options object. The pageIndex option (0-based) selects which page to export. Each call exports one page.

// Export the first page as an external HTML5 bundle (HTML + separate assets)
const externalResult = await exportHtml(engine, {
format: 'external',
pageIndex: 0
});
// The result contains a FileMap with all generated files
console.log('External export files:');
for (const [path] of externalResult.files) {
console.log(` ${path}`);
}
// Check for warnings or errors during export
if (externalResult.messages && externalResult.messages.length > 0) {
for (const msg of externalResult.messages) {
console.log(`[${msg.type}] ${msg.message}`);
}
}

The returned ExportHtmlResult contains files (a FileMap of generated files) and messages (an array of LogMessage objects with any warnings or errors from the export process).

Export Options#

OptionTypeDefaultDescription
format'external' | 'embedded''external'Output format
pageIndexnumber(required)0-based page index
qualitynumber90WebP image quality 0–100
animatedboolean | 'auto''auto'Generate GSAP animation timeline
insertExplicitLineBreaksbooleantrueInsert <br> at CE.SDK line breaks
useSyntheticIdsbooleanfalseStable deterministic element IDs
abortSignalAbortSignalCancel the export

Choosing a Format: External vs Embedded#

The external format (default) writes index.html plus separate image and font files. Use this for production delivery — each file is individually cacheable and the total size is transparent for validation.

The embedded format inlines all assets as base64 data URLs into a single index.html. Use this for in-browser preview or sharing a single file.

// Export as a single self-contained HTML file (base64-embedded assets)
const embeddedResult = await exportHtml(engine, {
format: 'embedded',
pageIndex: 0
});

Animated Exports and GSAP Injection#

When animated is 'auto' (the default), the exporter checks the scene mode and generates a GSAP animation timeline for video scenes. The timeline is embedded as an inline script in the HTML output. To make it playable, inject the GSAP library from a CDN using injectGsapPlayer().

// Inject the GSAP library to make animations playable
const htmlFile = embeddedResult.files.get('index.html');
const htmlContent =
typeof htmlFile!.content === 'string'
? htmlFile!.content
: new TextDecoder().decode(htmlFile!.content);
const playableHtml = injectGsapPlayer(htmlContent);
// Open a preview in a new browser tab
const previewBlob = new Blob([playableHtml], { type: 'text/html' });
window.open(URL.createObjectURL(previewBlob), '_blank');

injectGsapPlayer() accepts optional overrides:

  • gsapUrl — Custom GSAP CDN URL (default: jsDelivr 3.x). Some platforms whitelist specific CDN URLs and exempt them from file-size limits.
  • splitTextUrl — Custom SplitText CDN URL, or false to disable auto-injection.
  • autoplay — Whether to inject the autoplay loop script (default: true).

Customizing the Output#

The FileMap returned by exportHtml() is a standard Map<string, ExportFile> extended with toZip(). Use files.get(), files.set(), and files.delete() to read, add, or remove files before packaging. Each ExportFile has a content property (string or Uint8Array) and an optional mimeType.

Modifying the HTML#

We read the index.html content as a string, use String.replace() to inject an ad.size meta tag before </head> and a click-tracking script before </body>, then write it back with files.set().

// Read the index.html from the external export and inject metadata
let html = externalResult.files.get('index.html')!.content as string;
// Inject an ad.size meta tag into the <head>
const pageWidth = Math.round(engine.block.getWidth(page));
const pageHeight = Math.round(engine.block.getHeight(page));
html = html.replace(
'</head>',
` <meta name="ad.size" content="width=${pageWidth},height=${pageHeight}">\n</head>`
);
// Inject a click-tracking script before </body>
const clickScript = `
<script>
var clickTag = "https://example.com";
document.addEventListener("click", function() {
window.open(clickTag, "_blank");
});
</script>`;
html = html.replace('</body>', clickScript + '\n</body>');
// Write the modified HTML back to the FileMap
externalResult.files.set('index.html', {
content: html,
mimeType: 'text/html'
});

The same pattern works for injecting any content — tracking pixels, analytics beacons, platform SDK scripts, or additional stylesheets.

Adding Extra Files#

We add a manifest.json describing the bundle dimensions and entry point, then generate a static JPEG backup image using engine.block.export() and include it in the bundle.

// Add a manifest.json describing the bundle
externalResult.files.set('manifest.json', {
content: JSON.stringify(
{
version: '1.0',
title: 'My Creative',
width: pageWidth,
height: pageHeight,
source: 'index.html'
},
null,
2
),
mimeType: 'application/json'
});
// Generate a static backup image and add it to the bundle
const backupBlob = await engine.block.export(page, {
mimeType: 'image/jpeg',
jpegQuality: 0.8,
targetWidth: pageWidth,
targetHeight: pageHeight
});
const backupBytes = new Uint8Array(await backupBlob.arrayBuffer());
externalResult.files.set('backup.jpg', {
content: backupBytes,
mimeType: 'image/jpeg'
});

You can add any file to the bundle this way — data feed templates, custom fonts, or platform-specific configuration files.

Packaging and Downloading#

After all customizations, call files.toZip() to produce a Uint8Array containing the ZIP archive. We wrap it in a Blob and trigger a browser download.

// Package all files as a ZIP and trigger a browser download
const zip = await externalResult.files.toZip();
const downloadBlob = new Blob([zip.buffer as ArrayBuffer], {
type: 'application/zip'
});
const a = document.createElement('a');
a.href = URL.createObjectURL(downloadBlob);
a.download = 'html5-export.zip';
a.click();

Troubleshooting#

Exported HTML is blank — Verify pageIndex is within bounds by checking engine.block.findByType('page').length. Review result.messages for warnings about unsupported blocks.

Animations do not play — Ensure the scene mode is 'Video' or set animated: true explicitly. Call injectGsapPlayer() on the HTML string before opening it in a browser. Verify the GSAP CDN URL is reachable.

Bundle rejected for file size — Use the external format instead of embedded, which inflates size through base64 encoding. Reduce the quality option for smaller image assets. Remove unused files from the FileMap before calling toZip().

Missing click tracking or metadata — Inject the click-tracking script required by your target platform before </body>. Add required meta tags to <head> and include a manifest.json if the platform requires one.

API Reference#

Method / TypeDescription
exportHtml(engine, options)Export a scene page as HTML5
injectGsapPlayer(html, options?)Inject GSAP CDN and autoplay script
FileMapMap of export files extending Map<string, ExportFile>
FileMap.prototype.toZip()Package all files as a ZIP (Uint8Array)
ExportHtmlOptionsOptions interface for exportHtml()
ExportHtmlResultResult with files and messages
ExportFileFile entry with content and optional mimeType
LogMessageExport message with message and type
engine.block.export(block, options)Export a block as an image
engine.block.findByType('page')Find all pages in the scene

Next Steps#