Skip to content
Zurück zur Startseite

Kreativsimulator per <iframe> einbinden

Betten Sie den Kreativsimulator in Sekunden in Ihre eigene Website ein – und steuern Sie ihn optional komplett von außen: eigene Produktauswahl, eigene Motive, eigene UI. Dieser Leitfaden zeigt jeden Schritt mit kopierbarem Code und einer Live-Demo zum Ausprobieren.

Schritt 1

Domains freischalten lassen

Aus Sicherheitsgründen erlaubt der Browser das Einbetten nur von Domains, die wir vorab freigeschaltet haben (Content-Security-Policy: frame-ancestors).

Teilen Sie uns vor der Einbettung alle Domains mit, auf denen der iframe erscheinen soll. Wir tragen sie in die Konfiguration Ihres Mandanten ein. Wildcards sind möglich.

Zum Beispiel:

  • https://www.ihre-agentur.de
  • https://kampagne.ihre-agentur.de
  • https://*.ihre-agentur.de (Wildcard)

Ohne Freischaltung bleibt der iframe leer (weiße Fläche). Auch die Live-Demo weiter unten lädt nur, wenn die einbettende Domain freigeschaltet ist – sonst nutzen Sie den „In neuem Tab öffnen“-Link.

Schritt 2

Einbettungs-Code

Ein einziges <iframe>-Tag genügt. Kein API-Key, keine zusätzliche Konfiguration auf Ihrer Seite – die Authentifizierung läuft vollständig serverseitig.

Code ansehen HTML
HTML
<iframe
  src="https://demo.kreativsimulator.com/"
  title="Kreativsimulator"
  style="width: 100%; height: 720px; border: 0;"
  allow="fullscreen"
  loading="lazy"
></iframe>

Embed-URL: https://<dein-mandant>.kreativsimulator.com/

Der Mandant wird aus der Subdomain abgeleitet. Für die öffentliche Sandbox verwenden Sie demo.kreativsimulator.com.

Sprache und Start-Produkt lassen sich optional per Query-Parameter vorgeben – siehe nächster Abschnitt.

Schritt 3

URL-Parameter

Optional lassen sich folgende Query-Parameter an die Embed-URL anhängen (mit ? beginnen, mit & verketten):

ParameterWerteWirkungDefault
langde · en · fr · itUI-SpracheMandant → Browser → de
productProdukt-Code (ec5472c2)Lädt direkt dieses Produkt (Deep-Link). Unbekannter Code → erstes Produkt.Erstes Produkt
header0 · 1Kopfzeile (Logo + Produkt-Auswahl) aus-/einblenden1 (sichtbar)
sidebar0 · 1Seitenleiste (inkl. Mobil-Drawer + Hamburger) aus-/einblenden1 (sichtbar)
playback0 · 1Abspiel-/Transport-Knöpfe in der Leiste aus-/einblenden1 (sichtbar)
timeline0 · 1Zeitleiste (Scrubbing-Balken) aus-/einblenden1 (sichtbar)
export0 · 1„Kreation exportieren“-Button aus-/einblenden1 (sichtbar)
effects0 · 1Effekt-Dropdown (nur Foto-Produkte) aus-/einblenden – z. B. für einen eigenen Picker1 (sichtbar)
fullscreen0 · 1Vollbild-Icon: 0=nie, 1=immer (auch Desktop); ohne Param = nur mobil/im Vollbildadaptiv
embedminimal · kioskKurzform: blendet Header, Sidebar und Export aus (Abspielleiste bleibt)
themeURL zu einer CSS-DateiLädt ein eigenes Theme (CSS-Variablen), das das Mandanten-Theme überschreibt
bgbeliebige CSS-Farbe, transparent oder Bild-URLHintergrund der Fläche um den Canvas (Letterbox/Rahmen), nicht das VideoTheme-Hintergrund
stage<Breite>x<Höhe> (1280x720)Feste Anzeige-Pixelgröße des Canvas statt fluider Breitefluid (100 %)
placeholderBgbeliebige CSS-FarbeHintergrund der Platzhalter-Box (Loader ohne Motiv) – Direkt-Shortcut ohne ?theme=-DateiTheme/Default (#ffffff)
placeholderTextbeliebige CSS-FarbeFarbe des Buchstabens in der Platzhalter-BoxTheme/Default (#000000)
placeholderBorderbeliebige CSS-FarbeRahmenfarbe der Platzhalter-BoxTheme/Default (#000000)
  • Boolean-Parameter akzeptieren 0/1 (auch true/false, yes/no). embed=kiosk wird zuerst ausgewertet – einzelne Parameter überschreiben es danach (z. B. zeigt ?embed=kiosk&header=1 trotzdem die Kopfzeile).
  • Die Sichtbarkeits-Schalter (header/sidebar/playback/timeline/export/effects) lassen sich auch zur Laufzeit per setChrome umschalten (siehe API). Wiedergabe, Export und Effekt-Auswahl funktionieren immer per postMessage – unabhängig davon, ob die zugehörigen Bedienelemente sichtbar sind. So bauen Sie eine komplett eigene Bedienung (eigener Effekt-Picker via setEffect, eingebauten Dropdown mit effects=0 ausblenden).
  • theme-CSS: wird als zusätzliches <link> nach dem Mandanten-Theme geladen und überschreibt dessen CSS-Variablen (z. B. --vc-accent, --vc-bg). CSS kann kein JavaScript ausführen; die Datei darf cross-origin liegen (kein CORS nötig). Werte für ?theme=/?bg= müssen URL-kodiert sein (z. B. %23 für #).
  • bg=transparent: die Elternseite scheint durch die Fläche um den Canvas (am sinnvollsten mit ?embed=kiosk). Der Video-Canvas selbst bleibt immer deckend – transparent wirkt nur auf den Rahmen/die Letterbox-Ränder.
  • Platzhalterfarben direkt in der URL (placeholderBg/placeholderText/placeholderBorder): brandet nur die Platzhalter-Box (das generierte Buchstaben-Motiv, solange kein eigenes Motiv gesetzt ist) – ein Shortcut ohne eigene ?theme=-Datei. Akzeptiert jede CSS-Farbe (Hex %23ff5a10, rgb(...), hsl(...), Namen wie white) und überschreibt Mandanten-Theme und ?theme=; nur gesetzte Parameter überschreiben. Tipp: placeholderBg und placeholderText nicht gleich setzen (sonst unsichtbarer Buchstabe). Wer mehr branden will (Akzent, Buttons, Spinner …), nutzt weiterhin ?theme=.

Beispiele

Code ansehen URL
URL
https://demo.kreativsimulator.com/                          # default
https://demo.kreativsimulator.com/?lang=en                  # English UI
https://demo.kreativsimulator.com/?product=ec5472c2         # open a product
https://demo.kreativsimulator.com/?product=ec5472c2&lang=fr # language + product
https://demo.kreativsimulator.com/?embed=kiosk              # canvas + playback bar only
https://demo.kreativsimulator.com/?header=0&sidebar=0       # header + sidebar off
https://demo.kreativsimulator.com/?timeline=0&playback=0    # timeline + transport off
https://demo.kreativsimulator.com/?effects=0                # effect dropdown off (own picker)
https://demo.kreativsimulator.com/?fullscreen=1             # fullscreen icon also on desktop
https://demo.kreativsimulator.com/?stage=1280x720           # fixed 1280×720 canvas
https://demo.kreativsimulator.com/?bg=%23000000             # black letterbox area
https://demo.kreativsimulator.com/?embed=kiosk&bg=transparent  # parent page shows through
https://demo.kreativsimulator.com/?theme=https%3A%2F%2Fcdn.kunde.de%2Fks-theme.css

# Placeholder colors directly (no theme file) — encode # as %23:
https://demo.kreativsimulator.com/?placeholderBg=%23ff5a10&placeholderText=%23ffffff&placeholderBorder=%23ffffff
# … or with rgb()/color names (no %23 needed):
https://demo.kreativsimulator.com/?placeholderBg=rgb(255,90,16)&placeholderText=white&placeholderBorder=white
Schritt 4

Responsive einbetten

Im Embed-Modus (Chrome aus, z. B. ?embed=kiosk oder ?sidebar=0) füllt der Canvas das iframe vollflächig und bleibt dabei mittig zentriert – kein Links-Offset, kein 1280px-Deckel mehr. Legen Sie das iframe also einfach mit width:100%; height:100% in einen beliebig dimensionierten Eltern-Container (auch Flexbox/Grid). Weicht dessen Seitenverhältnis von 16:9 ab, entsteht eine symmetrische Letterbox (Farbe per ?bg=).

Empfohlenes Rezept – das iframe füllt seinen Flex-/Grid-Container:

Code ansehen HTML
HTML
<!-- Any parent container; the iframe fills it completely. -->
<div style="display:flex; width:100%; height:480px;">
  <iframe
    src="https://demo.kreativsimulator.com/?embed=kiosk"
    title="Kreativsimulator"
    style="flex:1; border:0;"
    allow="fullscreen"
    loading="lazy"
  ></iframe>
</div>

Wer ein exakt passendes Seitenverhältnis ohne Letterbox will, gibt dem Wrapper aspect-ratio: 16 / 9:

Code ansehen HTML
HTML
<!-- Exact 16:9, no letterbox: constrain the wrapper. -->
<div style="aspect-ratio: 16 / 9; width: 100%;">
  <iframe
    src="https://demo.kreativsimulator.com/?embed=kiosk"
    title="Kreativsimulator"
    style="width: 100%; height: 100%; border: 0;"
    allow="fullscreen"
    loading="lazy"
  ></iframe>
</div>

Mit sichtbarer Sidebar (Standalone-Ansicht ohne ?embed/?sidebar=0) bleibt der Canvas links-bündig (max. 1280px) – die Voll-/Zentrier-Logik greift bewusst nur im Embed-Modus.

Schritt 5 · Kern-Use-Case

Nur der Canvas – alles selbst steuern

Der häufigste Fall: Sie zeigen nur den WebGL-Canvas und bauen die komplette Bedienung selbst. Blenden Sie Header, Sidebar und Buttons aus – per URL mit ?embed=kiosk (Header + Sidebar + Export aus, Abspielleiste bleibt) oder gezielt mit ?header=0&sidebar=0&playback=0&export=0. Zur Laufzeit geht dasselbe per setChrome.

Das Entscheidende: Wiedergabe und Export funktionieren immer per postMessage – unabhängig davon, ob die eingebauten Buttons sichtbar sind. So treiben Ihre eigenen Buttons das iframe; für einen eigenen Fortschrittsbalken lauschen Sie auf das playbackState-Event.

Praktisch ohne Sidebar: Ist die Seitenleiste ausgeblendet, öffnet ein Klick direkt auf eine Plakatfläche im Canvas den Datei-Dialog für genau diesen Platzhalter – so können Endnutzer auch ohne eigene Upload-UI ein Motiv hochladen.

embed=kiosk versteckt das eingebaute Chrome – Ihre Buttons senden play/pause/seek/export. Probieren Sie es unten in der Live-Demo mit den „Chrome“-Schaltern und der eigenen Wiedergabeleiste aus.

Canvas im Kiosk-Modus + eigene Abspielsteuerung, synchron gehalten über das playbackState-Event:

Code ansehen HTML + JS
HTML + JS
<!-- Canvas only — your own playback UI drives it from the outside -->
<iframe id="ks" src="https://demo.kreativsimulator.com/?embed=kiosk"
        style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>

<button id="play">▶︎</button>
<button id="pause">⏸</button>
<button id="stop">⏹</button>
<button id="back">⏮</button>
<button id="fwd">⏭</button>
<input id="scrub" type="range" min="0" value="0" />
<button id="export">Export</button>
<button id="fs">⛶ Fullscreen</button>

<script>
  const iframe = document.getElementById("ks");
  const send = (msg) => iframe.contentWindow.postMessage(msg, "*");
  const P = "kreativsimulator:";

  play.onclick  = () => send({ type: P + "play" });
  pause.onclick = () => send({ type: P + "pause" });
  stop.onclick  = () => send({ type: P + "stop" });
  back.onclick  = () => send({ type: P + "stepBackward" });
  fwd.onclick   = () => send({ type: P + "stepForward" });
  scrub.oninput = (e) => send({ type: P + "seek", frame: Number(e.target.value) });
  // Direct export at 1280×720 (no dialog):
  export.onclick = () =>
    send({ type: P + "export", filename: "creation", width: 1280, height: 720 });
  // Fullscreen ON reliably via requestFullscreen on the iframe (the user gesture
  // is here, on the click). OFF/toggle could also go via the postMessage event.
  fs.onclick = () => {
    if (document.fullscreenElement) document.exitFullscreen();
    else iframe.requestFullscreen();   // iframe needs allow="fullscreen"
  };

  window.addEventListener("message", (e) => {
    const m = e.data;
    if (!m || m.source !== "kreativsimulator") return;
    if (m.type === "playbackState") {
      scrub.max = m.frameCount - 1;
      if (document.activeElement !== scrub) scrub.value = m.frame; // don't fight the drag
      play.disabled = m.playing;
      pause.disabled = !m.playing;
    }
    if (m.type === "fullscreenChanged") {
      fs.textContent = m.fullscreen ? "⛶ Exit fullscreen" : "⛶ Fullscreen";
    }
  });

  // Ask for the current state once (e.g. after load):
  // send({ type: P + "getState" });
</script>
Schritt 6 · Eigenes Design

Eigenes Design per CSS (theme & bg)

Das iframe übernimmt Ihr Branding über CSS-Variablen. ?theme= lädt eine eigene CSS-Datei nach dem Mandanten-Theme und überschreibt dessen Variablen (z. B. --vc-accent, --vc-bg). ?bg= setzt die Letterbox-Fläche um den Canvas (Farbe oder Bild-URL), ?stage= eine feste Canvas-Pixelgröße.

Einbettung mit Theme + Hintergrund

Code ansehen HTML
HTML
<!-- Your own theme + a black letterbox around the canvas -->
<iframe
  src="https://demo.kreativsimulator.com/?embed=kiosk&theme=https%3A%2F%2Fcdn.kunde.de%2Fks-theme.css&bg=%23000000"
  title="Kreativsimulator"
  style="width: 100%; height: 720px; border: 0;"
  allow="fullscreen"
  loading="lazy"
></iframe>

Theme-Vorlage

Vorlage herunterladen ks-theme.css
Vorlage ansehen kreativsimulator-theme-template.css
kreativsimulator-theme-template.css
/* =============================================================================
   Kreativsimulator – Theme-Vorlage (CSS Custom Properties)
   =============================================================================

   So passt du das Aussehen des eingebetteten Kreativsimulators an deine Marke an.

   VERWENDUNG
   ----------
   1. Diese Datei kopieren, Werte unten anpassen, auf einem öffentlich
      erreichbaren HTTPS-URL ablegen (z. B. https://cdn.deine-agentur.de/ks-theme.css).
   2. Den URL per `?theme=` an die iframe-Einbettung hängen – URL-kodiert:

      <iframe src="https://demo.kreativsimulator.com/?theme=https%3A%2F%2Fcdn.deine-agentur.de%2Fks-theme.css"
              style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>

   HINWEISE
   --------
   • Die Datei wird als zusätzliches <link> NACH dem Mandanten-Theme geladen und
     überschreibt dessen Werte (CSS-Kaskade). Cross-Origin ist erlaubt (kein CORS
     nötig) – CSS kann kein JavaScript ausführen.
   • Du musst NICHT alle Variablen setzen. Lösche einfach die Zeilen, die du nicht
     ändern willst – dann gilt der jeweilige Standard des Simulators/Mandanten.
   • Farben: jede gültige CSS-Farbe (#hex, rgb(), hsl(), benannt).
   • Den Hintergrund UM den Canvas (Letterbox) steuerst du besser per
     `?bg=<farbe|transparent|url>` – nicht über `--vc-bg` (das ist auch der
     Canvas-Hintergrund während des Ladens).
   ========================================================================== */

:root {
  /* ── Meta ──────────────────────────────────────────────────────────────
     Hell-/Dunkel-Schema. Beeinflusst u. a. native Formular-Elemente.
     Werte: dark | light */
  --vc-color-scheme: dark;

  /* Schriftfamilie der gesamten Oberfläche.
     Eigene Webfont? Oben in der Datei per @import laden, z. B.:
       @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap');
     und hier referenzieren: 'Inter', system-ui, sans-serif */
  --vc-font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* ── Flächen ───────────────────────────────────────────────────────────
     Grundfarben der UI-Container (Sidebar, Dialoge, Karten). */
  --vc-bg: #0a0a0a;             /* App-Hintergrund / Canvas-Hintergrund beim Laden */
  --vc-surface: #181818;       /* Sidebar, Dialog-Flächen */
  --vc-surface-raised: #2a2a2a;/* erhöhte Elemente (Tracks, Chips, Inputs) */
  --vc-surface-hover: #3a3a3a; /* Hover-Fläche */
  --vc-border: #2a2a2a;        /* Standard-Rahmenfarbe */
  --vc-border-strong: #444444; /* betonte Rahmen */

  /* ── Text ──────────────────────────────────────────────────────────────*/
  --vc-text: #eeeeee;          /* Standard-Textfarbe */
  --vc-text-muted: #888888;    /* sekundärer Text */
  --vc-text-subtle: #666666;   /* dezente Hinweise */
  --vc-text-on-accent: #ffffff;/* Text auf Akzent-/Primärflächen */

  /* ── Akzent (Marke) ────────────────────────────────────────────────────
     Wird u. a. für aktive Zustände, Timeline/Abspielkopf und Slider-Punkte
     verwendet. `--vc-accent-rgb` MUSS dieselbe Farbe als "R, G, B" enthalten
     (ohne rgb()-Klammern) – wird für halbtransparente Hervorhebungen genutzt. */
  --vc-accent: #df3b00;
  --vc-accent-strong: #ff5722; /* kräftigere Akzentvariante (Hover) */
  --vc-accent-rgb: 223, 59, 0; /* = --vc-accent als R, G, B */
  --vc-accent-muted: #3a3a3a;  /* gedämpfter Akzent-Hintergrund */

  /* ── Header (Kopfzeile mit Logo + Produktauswahl) ──────────────────────
     Nur relevant, wenn der Header sichtbar ist (sonst per ?header=0 ausblenden). */
  --vc-header-bg: transparent;     /* Hintergrund der Kopfzeile */
  --vc-header-text: #eeeeee;       /* Titel-/Header-Text */
  --vc-header-text-muted: #888888; /* sekundärer Header-Text */
  --vc-header-border: #1a1a1a;     /* untere Trennlinie */
  --vc-header-border-width: 1px;   /* Stärke der Trennlinie (0px = keine) */
  --vc-header-padding: 12px 20px;  /* Innenabstand der Kopfzeile */
  --vc-logo-height: 26px;          /* Höhe des Mandanten-Logos */

  /* ── Buttons ───────────────────────────────────────────────────────────*/
  --vc-button-bg: #2a2a2a;       /* Button-Fläche */
  --vc-button-bg-hover: #3a3a3a; /* Button-Fläche bei Hover */
  --vc-button-text: inherit;     /* Button-Textfarbe */
  --vc-button-border: #444444;   /* Button-Rahmen */
  --vc-button-radius: 4px;       /* Eckenradius der Buttons */

  /* ── Dialoge (Export-Dialog „Export als MP4") ──────────────────────────
     Ohne Override folgen sie den Surface-/Border-Variablen. */
  --vc-dialog-bg: var(--vc-surface);        /* Dialog-Fläche */
  --vc-dialog-border: var(--vc-border);     /* Dialog-Rahmen */
  --vc-dialog-radius: 8px;                  /* Eckenradius des Dialogs */
  --vc-dialog-backdrop: rgba(0, 0, 0, 0.6); /* Abdunklung hinter dem Dialog */

  /* ── Eingabefelder & Selects ───────────────────────────────────────────
     Gilt für alle Input-/Select-Felder – auch das Effekt-Dropdown bei
     Foto-Produkten. Ohne Override folgen sie den Surface-/Text-Variablen. */
  --vc-input-bg: var(--vc-surface-raised);    /* Feld-Hintergrund */
  --vc-input-border: var(--vc-border-strong); /* Feld-Rahmen */
  --vc-input-text: var(--vc-text);            /* Eingabetext */
  --vc-input-radius: 4px;                     /* Eckenradius der Felder */
  --vc-label-text: var(--vc-text-muted);      /* Feld-Beschriftungen */

  /* ── Slider / Zeitleiste ───────────────────────────────────────────────
     Der Abspielkopf und die In/Out-Marken nutzen --vc-accent (s. o.). */
  --vc-slider-track: #3a3a3a;    /* Track-Farbe der Regler */

  /* ── Lade-Spinner (Ladeanzeige beim Initialisieren / Footage-Laden) ────
     Ohne Override folgt der Spinner automatisch --vc-accent (Bogen) bzw.
     --vc-border (Ring) – diese Zeilen also nur setzen, wenn du ihn abweichend
     gestalten willst. */
  --vc-spinner-color: var(--vc-accent); /* rotierender Bogen */
  --vc-spinner-track: var(--vc-border); /* ruhender Ring */
  --vc-spinner-size: 48px;              /* Durchmesser */

  /* ── Vorschau-Canvas (Rahmen um das Video) ─────────────────────────────*/
  --vc-canvas-outline-color: #2a2a2a; /* Outline-Farbe des Canvas */
  --vc-canvas-outline-width: 1px;     /* Outline-Stärke (0px = kein Rahmen) */
  --vc-canvas-radius: 0px;            /* Eckenradius des Canvas – z. B. 16px für
                                         runde Ecken (rundet Video, Lade-Fläche
                                         und Rahmen einheitlich). 0px = eckig. */

  /* ── Viewport-Rahmen (optionaler Rahmen um die ganze Fläche) ───────────*/
  --vc-frame-color: transparent; /* Farbe des Außenrahmens */
  --vc-frame-width: 0px;          /* Stärke (0px = aus) */

  /* ── Platzhalter (Plakatflächen ohne hochgeladenes Motiv) ──────────────
     Die generierte „A/B"-Platzhaltertextur. */
  --vc-placeholder-bg: #ffffff;     /* Hintergrund der Platzhalterfläche */
  --vc-placeholder-text: #000000;   /* Buchstabe/Beschriftung */
  --vc-placeholder-border: #000000; /* Rahmen der Platzhalterfläche */
}

/* =============================================================================
   BEISPIEL: helles Marken-Theme (zum Vergleich auskommentiert).
   Zum Ausprobieren das obige :root entfernen und dieses aktivieren.
   ============================================================================*/
/*
:root {
  --vc-color-scheme: light;
  --vc-bg: #ffffff;
  --vc-surface: #ffffff;
  --vc-surface-raised: #f2f2f2;
  --vc-surface-hover: #e8e8e8;
  --vc-border: #e2e2e2;
  --vc-border-strong: #c2c2c2;
  --vc-text: #1a1a22;
  --vc-text-muted: #5e5e68;
  --vc-text-subtle: #8c8c94;
  --vc-text-on-accent: #ffffff;
  --vc-accent: #0066ff;
  --vc-accent-strong: #0047b3;
  --vc-accent-rgb: 0, 102, 255;
  --vc-accent-muted: #d6e4ff;
  --vc-header-bg: #ffffff;
  --vc-header-text: #1a1a22;
  --vc-header-text-muted: #6a6a74;
  --vc-header-border: #e2e2e2;
  --vc-header-border-width: 1px;
  --vc-button-bg: #0066ff;
  --vc-button-bg-hover: #0047b3;
  --vc-button-text: #ffffff;
  --vc-button-border: #0066ff;
  --vc-button-radius: 6px;
  --vc-slider-track: #e0e0e0;
  --vc-canvas-outline-color: #0066ff;
  --vc-canvas-outline-width: 2px;
}
*/
  • Kein CORS nötig: Die CSS-Datei wird als <link> geladen (nicht per fetch wie Motive) und darf cross-origin liegen. CSS kann kein JavaScript ausführen.
  • URL-kodieren: Werte für ?theme=/?bg= müssen URL-kodiert sein (z. B. %23 für #, %2F für /).
  • Auch der Lade-Spinner ist themebar: --vc-spinner-color (rotierender Bogen), --vc-spinner-track (Ring) und --vc-spinner-size (Durchmesser) – ohne Override folgt er automatisch --vc-accent bzw. --vc-border.
  • Abgerundete Canvas-Ecken: --vc-canvas-radius (Default 0px) rundet den Vorschau-Canvas – Video, Lade-Fläche und Rahmen einheitlich – z. B. --vc-canvas-radius: 16px; in der ?theme=-CSS.
  • Dialoge & Eingabefelder themebar: Der Export-Dialog (--vc-dialog-bg, --vc-dialog-border, --vc-dialog-radius, --vc-dialog-backdrop) und alle Input-/Select-Felder inkl. des Effekt-Dropdowns bei Foto-Produkten (--vc-input-bg, --vc-input-border, --vc-input-text, --vc-input-radius, --vc-label-text) lassen sich gezielt stylen – ohne Override folgen sie den Surface-/Text-Variablen.
  • Nur Platzhalterfarben? Dafür brauchen Sie keine Theme-Datei: ?placeholderBg=/?placeholderText=/?placeholderBorder= setzen die Platzhalter-Box direkt per URL (siehe URL-Parameter oben) und überschreiben Theme + ?theme=.
  • Die vollständige Liste der überschreibbaren CSS-Variablen finden Sie in der Theme-Vorlage unten.
Schritt 7 · Interaktiv

Fernsteuerung live ausprobieren

Hier sehen Sie das echte iframe (links) und daneben eine komplett eigene Bedien-UI (rechts) – eigene Produktbilder, eigene Motive, eigene Buttons. Jeder Klick schickt eine postMessage an das iframe. Genau so bauen Sie es auf Ihrer Seite nach; den passenden Code finden Sie direkt darunter.

Echtes iframe von demo.kreativsimulator.com In neuem Tab öffnen

Chrome ein-/ausblenden

Header/Sidebar/Buttons live verstecken → setChrome. „Nur Canvas“ blendet alles aus.

Eigene Wiedergabe

Funktioniert auch ohne sichtbare Buttons. Scrubber via seek, synchron über playbackState.

Eigene Produktauswahl

Diese Karten baut Ihre Seite aus dem ready-Event. Klick → setProduct. Foto-Produkte zeigen per getEffects (vorab, ohne Produktwechsel) ihre Effektzahl.

Eigene Motive

Ihre eigenen Platzhalter-Motive. Klick → setCreative (lädt das Bild per CORS).

Eigene Datei je Platzhalter

Bild auf A oder B ziehen → setCreative mit loader. In Produktion laden Sie die Datei auf Ihren CORS-Host und übergeben die URL; hier zur Demo als Data-URL.

Export

Auflösung aus ready.render.presets. Klick → export (MP4).

Lade-Varianten (URL-Parameter)

Lädt das iframe mit Parametern neu – so wirken embed/bg/stage.

Platzhalterfarben (URL)

Brandet nur die Platzhalter-Box direkt per URL – ohne eigene ?theme=-Datei. „Anwenden“ lädt das iframe mit ?placeholderBg/Text/Border neu.

Sprache

Event-Log (iframe → Ihre Seite)

  • Noch keine Events empfangen …

Der folgende Code steuert exakt diese Live-Demo. Übernehmen Sie ihn als Ausgangspunkt:

Code ansehen HTML + JS
HTML + JS
<iframe id="ks" src="https://demo.kreativsimulator.com/"
        style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>

<script>
  const iframe = document.getElementById("ks");
  const send = (msg) => iframe.contentWindow.postMessage(msg, "*");

  window.addEventListener("message", (e) => {
    const m = e.data;
    if (!m || m.source !== "kreativsimulator") return;

    if (m.type === "ready") {
      // Build your own buttons from the product list
      for (const p of m.products) {
        const btn = document.createElement("button");
        btn.textContent = p.name;
        btn.onclick = () =>
          send({ type: "kreativsimulator:setProduct", code: p.code });
        document.body.appendChild(btn);
      }
      // Build your own resolution picker + export button from m.render.presets
      const sel = document.createElement("select");
      for (const r of m.render.presets) {
        const o = document.createElement("option");
        o.value = r.width + "x" + r.height;
        o.textContent = r.label;
        sel.appendChild(o);
      }
      const exportBtn = document.createElement("button");
      exportBtn.textContent = "Export";
      exportBtn.onclick = () => {
        const [width, height] = sel.value.split("x").map(Number);
        send({ type: "kreativsimulator:export", filename: "creation", width, height });
      };
      document.body.append(sel, exportBtn);
    }

    // The product is active now → only here may you target a placeholder.
    if (m.type === "productChanged") {
      const first = m.loaders[0];                // take the name from the event
      if (first) {
        send({
          type: "kreativsimulator:setCreative",
          url: "https://cdn.your-agency.com/creative.png",
          loader: first.name,                    // this placeholder only
        });
      }
    }

    if (m.type === "error") console.warn("KS error:", m.message);
  });

  // Creative on ALL placeholders (no loader) — fine right after `ready`:
  // send({ type: "kreativsimulator:setCreative", url: "https://cdn.your-agency.com/creative.png" });
</script>
Schritt 8 · Referenz

postMessage-API

Bauen Sie eine eigene UI und steuern Sie das iframe per window.postMessage. Das iframe sendet außerdem Events zurück (u. a. die Liste der verfügbaren Produkt-Codes).

Eingehende Befehle (Ihre Seite → iframe)

NachrichtWirkung
{ type: "kreativsimulator:setProduct", code: "ec5472c2" }Lädt das Produkt mit diesem Code.
{ type: "kreativsimulator:setCreative", url: "https://…/motiv.png" }Legt das Bild/Video als Motiv auf alle Platzhalter.
{ type: "kreativsimulator:setCreative", url: "…", loader: "Loader A" }Belegt nur den genannten Platzhalter.
{ type: "kreativsimulator:clearCreative", loader?: "Loader A" }Setzt einen (oder ohne loader alle) Platzhalter auf den Default zurück.
{ type: "kreativsimulator:setLanguage", lang: "fr" }Schaltet die UI-Sprache (de/en/fr/it).
{ type: "kreativsimulator:setEffect", id: "static-5s" }Foto-Produkte: wählt einen Eintrag aus ready.effects – ein Statisch-Preset (static-5s/static-10s, immer vorhanden) oder einen benannten Ken-Burns-Effekt. id: null = reines Standbild (1 Frame). Ändert die Timeline-Länge → es folgt ein playbackState.
{ type: "kreativsimulator:getEffects", code: "ec5472c2" }Fragt die Effektliste eines beliebigen Produkts ab, ohne es zu aktivieren (Live-Ansicht bleibt unverändert) → Antwort als effects-Event. Für einen eigenen Effekt-Picker je Produkt – noch vor setProduct.
{ type: "kreativsimulator:play" } · pause · stopStartet / pausiert / stoppt (zurück an den Anfang) die Wiedergabe.
{ type: "kreativsimulator:stepForward", frames?: 1 } · stepBackwardSpringt frames Bilder vor/zurück (Default 1) und pausiert.
{ type: "kreativsimulator:seek", frame: 120 }Springt zu einem absoluten Bild-Index (0…frameCount-1).
{ type: "kreativsimulator:export", filename?, width?, height? }Startet den MP4-Export. Mit width+height direkt in beliebiger Auflösung; ohne öffnet sich der Export-Dialog.
{ type: "kreativsimulator:setChrome", header?, sidebar?, playback?, timeline?, export?, effects? }Blendet einzelne UI-Bereiche zur Laufzeit ein/aus (jeweils true/false). effects = Effekt-Dropdown (Foto-Produkte).
{ type: "kreativsimulator:fullscreen", enabled? }Vollbild: true=ein, false=aus, ohne enabled=umschalten (siehe Hinweis).
{ type: "kreativsimulator:getState" }Fordert den aktuellen Wiedergabe-Zustand an → Antwort als playbackState.

Ausgehende Events (iframe → Ihre Seite)

Code ansehen JS
JS
{ source: "kreativsimulator", v: 1, type: "ready",
  product: "ec5472c2", locale: "de",
  products: [{ code: "ec5472c2", name: "City-Light …" }, …],
  loaders: [{ name: "Loader A", aspectRatio: 2.96 }, …],
  // native render resolution (16:9) + suggested export presets
  render: { width: 1280, height: 720, aspectRatio: 1.7778,
            presets: [{ label: "E-Mail / WhatsApp (640×360)", width: 640, height: 360 },
                      { label: "Standard HD (1280×720)", width: 1280, height: 720 },
                      { label: "YouTube / Full HD (1920×1080)", width: 1920, height: 1080 }] },
  // photo products (productType "bild"): effects[] = two always-present static
  // presets (static-5s, static-10s) + named Ken-Burns effects; default = static-5s.
  // video products report isPhoto:false, effects:[], selectedEffect:null.
  isPhoto: true,
  effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
            { id: "static-10s", name: "Static (10s)", durationFrames: 250 },
            { id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
  selectedEffect: "static-5s" }

{ source: "kreativsimulator", v: 1, type: "productChanged", code: "ec5472c2",
  loaders: [{ name: "Loader A", aspectRatio: 2.96 }, …],
  isPhoto: true,
  effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
            { id: "static-10s", name: "Static (10s)", durationFrames: 250 },
            { id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
  selectedEffect: "static-5s" }

// reply to getEffects {code}: a product's effect list WITHOUT activating it.
// same fields as productChanged (incl. the static presets), plus code.
// video products report isPhoto:false, effects:[], selectedEffect:null.
{ source: "kreativsimulator", v: 1, type: "effects", code: "ec5472c2",
  isPhoto: true,
  effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
            { id: "static-10s", name: "Static (10s)", durationFrames: 250 },
            { id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
  selectedEffect: "static-5s" }

// playback state: on play/pause, ~4×/s while playing, after seek/stop/step, and on getState
// for photo products, frameCount equals the active effect's duration
{ source: "kreativsimulator", v: 1, type: "playbackState",
  frame: 120, playing: true, frameCount: 250, fps: 25 }

// confirmation after setChrome, with the new visibility state
{ source: "kreativsimulator", v: 1, type: "chromeChanged",
  header: false, sidebar: false, playback: true, timeline: true, export: false, effects: false }

// fullscreen state — on every change (e.g. ESC); for syncing your own button
{ source: "kreativsimulator", v: 1, type: "fullscreenChanged", fullscreen: true }

{ source: "kreativsimulator", v: 1, type: "error", message: "…", code, loader }

Filtern Sie eingehende Nachrichten immer auf source === "kreativsimulator". v ist die Protokoll-Version (aktuell 1).

Vollständiges Beispiel

Eigene Buttons aus der Produktliste, ein platzhalter-gezieltes Motiv (korrekte Reihenfolge) und ein eigener Auflösungs-Picker aus render.presets:

Code ansehen HTML + JS
HTML + JS
<iframe id="ks" src="https://demo.kreativsimulator.com/"
        style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>

<script>
  const iframe = document.getElementById("ks");
  const send = (msg) => iframe.contentWindow.postMessage(msg, "*");

  window.addEventListener("message", (e) => {
    const m = e.data;
    if (!m || m.source !== "kreativsimulator") return;

    if (m.type === "ready") {
      // Build your own buttons from the product list
      for (const p of m.products) {
        const btn = document.createElement("button");
        btn.textContent = p.name;
        btn.onclick = () =>
          send({ type: "kreativsimulator:setProduct", code: p.code });
        document.body.appendChild(btn);
      }
      // Build your own resolution picker + export button from m.render.presets
      const sel = document.createElement("select");
      for (const r of m.render.presets) {
        const o = document.createElement("option");
        o.value = r.width + "x" + r.height;
        o.textContent = r.label;
        sel.appendChild(o);
      }
      const exportBtn = document.createElement("button");
      exportBtn.textContent = "Export";
      exportBtn.onclick = () => {
        const [width, height] = sel.value.split("x").map(Number);
        send({ type: "kreativsimulator:export", filename: "creation", width, height });
      };
      document.body.append(sel, exportBtn);
    }

    // The product is active now → only here may you target a placeholder.
    if (m.type === "productChanged") {
      const first = m.loaders[0];                // take the name from the event
      if (first) {
        send({
          type: "kreativsimulator:setCreative",
          url: "https://cdn.your-agency.com/creative.png",
          loader: first.name,                    // this placeholder only
        });
      }
    }

    if (m.type === "error") console.warn("KS error:", m.message);
  });

  // Creative on ALL placeholders (no loader) — fine right after `ready`:
  // send({ type: "kreativsimulator:setCreative", url: "https://cdn.your-agency.com/creative.png" });
</script>

Wichtig

  • Reihenfolge bei Produktwechsel: Nach setProduct ist das neue Produkt erst aktiv, sobald das productChanged-Event eintrifft. Platzhalter-gezielte Befehle (setCreative/clearCreative mit loader) erst danach senden – vorher kennt das iframe nur die Platzhalter des alten Produkts. Ein Produktwechsel setzt zudem alle Motive zurück.
  • Eigene Bedienelemente: Wiedergabe (play/pause/stop/step…/seek) und export funktionieren immer – egal ob die eingebauten Buttons sichtbar sind. Blenden Sie sie mit ?embed=kiosk aus und steuern Sie alles selbst.
  • Export-Auflösung frei wählen: export mit width+height rendert in beliebiger Auflösung. Native Auflösung (1280×720, 16:9) und Presets liefert ready.render – Seitenverhältnis 16:9 halten, sonst verzerrt das Bild.
  • Foto-Produkte & Ken-Burns-Effekte: Manche Produkte sind Standbilder mit benannten Kamerafahrten. ready/productChanged melden dann isPhoto: true und eine Liste effects ({ id, name, durationFrames }). Diese beginnt immer mit zwei Statisch-Presets (static-5s = 5 s, static-10s = 10 s), gefolgt von den benannten Effekten; beim Laden ist automatisch static-5s aktiv (selectedEffect). Mit setEffect { id } wählen Sie einen anderen Eintrag (oder id: null für ein reines Standbild, 1 Frame). Wiedergabe und Export funktionieren wie bei Video; playbackState.frameCount entspricht der Dauer des aktiven Eintrags.
  • Effekte vorab abfragen (ohne Produktwechsel): ready/productChanged liefern Effekte nur für das aktive Produkt. Für einen Effekt-Picker zu anderen Produkten – ohne die Live-Ansicht umzuschalten – senden Sie getEffects { code } und lauschen auf das effects-Event (gleiche Felder wie productChanged, plus code). So holen Sie id/name jedes Effekts, die Sie später mit setEffect (nach setProduct auf diesen Code) ansteuern.
  • Vollbild zuverlässig einschalten: Browser erlauben das Einschalten nur als direkte Reaktion auf eine User-Geste – eine fullscreen-postMessage hat diese meist nicht und kann blockiert werden. Rufe daher auf deiner Seite beim Klick iframe.requestFullscreen() auf (iframe braucht allow="fullscreen"); die postMessage eignet sich für Aus/Toggle. Den Zustand liefert fullscreenChanged.
  • Platzhalter-Namen sind nicht frei wählbar – verwenden Sie exakt einen name aus dem loaders[]-Array von ready bzw. productChanged.
  • CORS: Bei setCreative lädt das iframe die Bild-/Video-URL per fetch. Der Host Ihrer Datei muss daher Access-Control-Allow-Origin senden, sonst kommt ein error-Event zurück.
  • Sicherheit: Welche Seiten das iframe einbetten dürfen, ist serverseitig per frame-ancestors festgelegt – nur diese können überhaupt Nachrichten senden.

Gut zu wissen

  • Kein API-Key nötig – die Authentifizierung läuft vollständig serverseitig.
  • Der Nutzer kann den Simulator direkt im iframe bedienen oder Sie steuern ihn per postMessage von Ihrer Seite.
  • Der iframe lädt Video-Footage – eine stabile Verbindung wird empfohlen.

Troubleshooting

Der iframe bleibt leer / weiße Fläche

Mit hoher Wahrscheinlichkeit ist die einbettende Domain nicht freigeschaltet. Die Browser-Konsole (F12) zeigt dann „Refused to frame … frame-ancestors …“. Schicken Sie uns die exakte Domain (inkl. https:// und ggf. Subdomain), wir schalten sie frei.

Der iframe zeigt „403“

Der Mandant ist serverseitig noch nicht vollständig konfiguriert (kein API-Key hinterlegt). Bitte bei uns melden.

Ein Motiv erscheint nicht (error-Event)

Die Motiv-URL sendet kein CORS, oder der loader-Name passt nicht zum aktiven Produkt. Prüfen Sie Access-Control-Allow-Origin der Bild-URL und senden Sie loader-gezielte Befehle erst nach dem productChanged-Event.

Bereit zum Einbetten?

Schicken Sie uns Ihre Domain(s) – wir schalten die Einbettung frei und Sie sind in Minuten live.