Embed survey to your own site
High level process
- Enable embedding is channel settings
- Create an iframe on your page and load the channel url
- Wait for a Post Message with survey load status and decide if you want to show the iframe or not
- When user has completed the form you will get another Post Message so you can hide the iframe
Information you can include in the URL (optional)
Below settings can be added to the channel url as search parameters
Parameter | Values | Description |
---|---|---|
language | en, et, de, fr | If not provided will default to internaltional english |
theme | light, dark | If not provided we will respect users browser preference |
transparent | true, false | If true will turn page background transparent |
payload | string | See safe links documentation for more info |
Messages we are ready to receive
{
"message": "theme-change",
"theme": "light" // "light", "dark"
}
Messages we are sending
{
"message": "survey-ready"
}
{
"message": "survey-completed"
}
Simplified example for React
import { cn } from "@workspace/ui/lib/utils";
import { useCallback, useEffect, useRef, useState } from "react";
import * as v from "valibot";
const PostMessages = v.variant("message", [
v.object({
message: v.literal("survey-ready"),
}),
v.object({
message: v.literal("survey-completed"),
}),
]);
export function EmbeddedWidget() {
const [visible, setVisible] = useState(false);
const surveyRef = useRef<HTMLIFrameElement>(null);
const theme = useTheme();
// Handle messages from the iframe
const handlePostMessage = useCallback((event: MessageEvent) => {
if (event.origin !== "https://youropinion.is") {
return null;
}
const message = v.parse(PostMessages, event.data);
if (message.message === "survey-ready") {
setVisible(true);
} else if (message.message === "survey-completed") {
setVisible(false);
}
}, []);
// Listen for messages from iframe
useEffect(() => {
window.addEventListener("message", handlePostMessage);
return () => {
window.removeEventListener("message", handlePostMessage);
};
}, []);
// Example of how to send a message to iframe
useEffect(() => {
if (surveyRef.current) {
surveyRef.current.contentWindow?.postMessage({ message: "change-theme", theme }, "*");
}
}, [theme]);
return (
<div
className={cn(
"h-[400px] w-[400px] fixed right-24 bottom-24 opacity-0 transition-opacity duration-1000",
{
"opacity-100": visible,
}
)}
>
<iframe
src={`https://youropinion.is/snap/xxx/c/yyy?theme=${theme}&transparent=true`}
className="w-full h-full"
ref={surveyRef}
/>
</div>
);
}