Embed Surveys on Your Website

Overview

  1. Enable embedding in channel settings
  2. Create an iframe on your page and load the channel URL
  3. Listen for the ‘survey-ready’ message to show the iframe
  4. Listen for the ‘survey-completed’ message to hide the iframe

Information you can include in the URL (optional)

Below settings can be added to the channel url as search parameters

ParameterValuesDescription
languageen, et, de, frLanguage code. Defaults to international English
themelight, darkTheme preference. Defaults to browser preference
transparenttrue, falseTransparent background. Defaults to false
payloadstringSee 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"
}

React Implementation Example

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>
    );
}