Skip to main content

Iframe Controls - Quick Start Guide

5-Minute Quick Start to embed Speak Recorder / Survey

Speak Ai avatar
Written by Speak Ai
Updated this week

5-Minute Quick Start β€” Speak AI Recorder Embed


Step 1: Basic Iframe Embedding

<!-- Minimal Embedding -->
<iframe
src="https://recorder.speakai.co/iframe/YOUR_TOKEN_HERE"
allow="microphone; camera"
width="100%"
height="700px">
</iframe>

Step 2: Add Query Parameters

<!-- With Query Parameters -->
<iframe
src="https://recorder.speakai.co/iframe/YOUR_TOKEN_HERE?hideWaveform=true&hideTitle=true&submitLabel=Send"
allow="microphone; camera"
width="100%"
height="700px">
</iframe>


Step 3: Add PostMessage Control

// Get iframe reference
const iframe = document.querySelector('iframe');

// Start recording
iframe.contentWindow.postMessage({ action: 'start' }, 'https://recorder.speakai.co');

// Stop recording
iframe.contentWindow.postMessage({ action: 'stop' }, 'https://recorder.speakai.co');

// Listen for responses
window.addEventListener('message', (event) => {
if (event.origin !== 'https://recorder.speakai.co') return;
const response = JSON.parse(event.data);
console.log('Response:', response);
});


βš™οΈ Query Parameters Reference

Parameter

Type

Default

Description

hideWaveform

boolean

false

Hide audio waveform visualization

hideTitle

boolean

false

Hide title/header text

submitLabel

string

"Upload"

Custom submit button text

hideSubmit

boolean

false

Hide submit button

preselect

string

"audio" | "video" | "upload" | "screenshare"

Pre-select recording type

name

string

""

Pre-fill name field

email

string

""

Pre-fill email field

folderId

string

""

Pre-fill folder ID

field1 - field10

string

""

Pre-fill custom question answers (up to 10)

Examples

Hide waveform:
?hideWaveform=true

Hide title:
?hideTitle=true

Custom button:
?submitLabel=Send%20Recording

All combined:
?hideWaveform=true&hideTitle=true&submitLabel=Complete

Pre-select recording type:
?preselect=video

Pre-fill name:
?name=John%20Doe

Pre-fill email:
[email protected]

Pre-fill folder ID:
?folderId=123456

Pre-fill custom question answers:
?field1=Answer%201&field2=Answer%202&field3=Answer%203


πŸ”„ PostMessage API Reference

Commands (Parent β†’ Iframe)

// Start recording
{
action: 'start',
timestamp: Date.now() // optional
}

// Stop recording
{
action: 'stop',
timestamp: Date.now() // optional
}

Responses (Iframe β†’ Parent)

// Success
{
source: 'speak-embed-recorder',
status: 'success',
message: 'Recording started',
timestamp: '2025-10-09T10:30:00.000Z',
data: { action: 'start' }
}

// Error
{
source: 'speak-embed-recorder',
status: 'error',
message: 'Recording already in progress',
timestamp: '2025-10-09T10:30:00.000Z'
}


πŸ’‘ Common Patterns

Pattern 1: Minimal UI

<iframe
src="https://recorder.speakai.co/iframe/TOKEN?hideWaveform=true&hideTitle=true"
allow="microphone; camera"
style="width: 100%; height: 500px; border: none;">
</iframe>

Pattern 2: Custom Branding

<iframe
src="https://recorder.speakai.co/iframe/TOKEN?submitLabel=Submit%20to%20Support"
allow="microphone; camera">
</iframe>

Pattern 3: External Controls

<div class="recording-controls">
<button onclick="startRecording()">πŸ”΄ Start</button>
<button onclick="stopRecording()">⏹ Stop</button>
<div id="status">Ready</div>
</div>

<iframe id="recorder" src="https://recorder.speakai.co/iframe/TOKEN"></iframe>

<script>
const iframe = document.getElementById('recorder');
const status = document.getElementById('status');

function startRecording() {
iframe.contentWindow.postMessage({action: 'start'}, '*');
status.textContent = 'Recording...';
}

function stopRecording() {
iframe.contentWindow.postMessage({action: 'stop'}, '*');
status.textContent = 'Stopped';
}

window.addEventListener('message', (e) => {
const response = JSON.parse(e.data);
if (response.status === 'error') {
status.textContent = 'Error: ' + response.message;
}
});
</script>


βš™οΈ Troubleshooting

Iframe Not Loading

const iframe = document.querySelector('iframe');
console.log('Iframe loaded:', iframe.contentWindow !== null);

iframe.addEventListener('load', () => {
console.log('Iframe loaded successfully');
});

PostMessage Not Working

const iframe = document.querySelector('iframe');

console.log('Iframe found:', iframe !== null);
console.log('ContentWindow:', iframe.contentWindow);

function sendDebugMessage(action) {
console.log('Sending:', action);
iframe.contentWindow.postMessage({ action: action }, '*');
console.log('Message sent');
}

sendDebugMessage('start');

Parameters Not Applied

const iframe = document.querySelector('iframe');
console.log('Iframe src:', iframe.src);

const url = new URL(iframe.src);
console.log('hideWaveform:', url.searchParams.get('hideWaveform'));
console.log('hideTitle:', url.searchParams.get('hideTitle'));
console.log('submitLabel:', url.searchParams.get('submitLabel'));


βš›οΈ Framework Examples

React

import { useEffect, useRef } from 'react';

function RecorderEmbed({ token }) {
const iframeRef = useRef(null);

useEffect(() => {
const handleMessage = (event) => {
if (event.origin !== 'https://recorder.speakai.co') return;
const response = JSON.parse(event.data);
console.log('Recorder:', response);
};

window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);

const startRecording = () => {
iframeRef.current?.contentWindow.postMessage({ action: 'start' }, 'https://recorder.speakai.co');
};

const stopRecording = () => {
iframeRef.current?.contentWindow.postMessage({ action: 'stop' }, 'https://recorder.speakai.co');
};

return (
<div>
<div>
<button onClick={startRecording}>Start</button>
<button onClick={stopRecording}>Stop</button>
</div>
<iframe
ref={iframeRef}
src={`https://recorder.speakai.co/iframe/${token}?hideWaveform=true`}
allow="microphone; camera"
style={{ width: '100%', height: '700px', border: 'none' }}
/>
</div>
);
}


Vue

<template>
<div>
<div>
<button @click="startRecording">Start</button>
<button @click="stopRecording">Stop</button>
</div>
<iframe
ref="recorder"
:src="iframeUrl"
allow="microphone; camera"
style="width: 100%; height: 700px; border: none"
/>
</div>
</template>

<script>
export default {
props: ['token'],
computed: {
iframeUrl() {
return `https://recorder.speakai.co/iframe/${this.token}?hideWaveform=true`;
}
},
mounted() {
window.addEventListener('message', this.handleMessage);
},
beforeUnmount() {
window.removeEventListener('message', this.handleMessage);
},
methods: {
handleMessage(event) {
if (event.origin !== 'https://recorder.speakai.co') return;
const response = JSON.parse(event.data);
console.log('Recorder:', response);
},
startRecording() {
this.$refs.recorder.contentWindow.postMessage(
{ action: 'start' },
'https://recorder.speakai.co'
);
},
stopRecording() {
this.$refs.recorder.contentWindow.postMessage(
{ action: 'stop' },
'https://recorder.speakai.co'
);
}
}
}
</script>


Angular

import { Component, ElementRef, ViewChild, OnInit, OnDestroy } from '@angular/core';

@Component({
selector: 'app-recorder',
template: `
<div>
<button (click)="startRecording()">Start</button>
<button (click)="stopRecording()">Stop</button>
</div>
<iframe
#recorder
[src]="iframeUrl"
allow="microphone; camera"
style="width: 100%; height: 700px; border: none">
</iframe>
`
})
export class RecorderComponent implements OnInit, OnDestroy {
@ViewChild('recorder') iframeElement: ElementRef;
iframeUrl = 'https://recorder.speakai.co/iframe/TOKEN?hideWaveform=true';

ngOnInit() {
window.addEventListener('message', this.handleMessage);
}

ngOnDestroy() {
window.removeEventListener('message', this.handleMessage);
}

handleMessage = (event: MessageEvent) => {
if (event.origin !== 'https://recorder.speakai.co') return;
const response = JSON.parse(event.data);
console.log('Recorder:', response);
};

startRecording() {
const iframe = this.iframeElement.nativeElement as HTMLIFrameElement;
iframe.contentWindow.postMessage({ action: 'start' }, 'https://recorder.speakai.co');
}

stopRecording() {
const iframe = this.iframeElement.nativeElement as HTMLIFrameElement;
iframe.contentWindow.postMessage({ action: 'stop' }, 'https://recorder.speakai.co');
}
}


Support

For issues or questions:

  1. Check the troubleshooting section above

  2. Review the full test plan document

  3. Use the test embedder page to debug

  4. Check the browser console for error messages

  5. Contact us at [email protected]

Did this answer your question?