feedback.js puts our finished board inside any element on your page. It takes your accent color, sits on your page’s background and grows with its content, so there’s never a scrollbar inside it.
Add the snippet#
Put an empty element where the board should appear, then load the script:
<div id="relay-feedback"></div>
<script>
window.RelayFeedbackSettings = {
// all optional
userId: "usr_123", // votes follow this user across devices
name: "Jane Cooper", // pre-fills the name on posts and comments
target: "#relay-feedback", // where to mount (selector or element)
minHeight: 640 // px, before the board has measured itself
};
</script>
<script src="https://support.notaislop.xyz/feedback.js" data-key="wk_XXXXXXXXXXXXXXXXXXXXXXXX" async></script>The same snippet, with your host filled in, is under Inbox → Settings → Install the feedback board.
Options#
userIdstring | numberoptionalnamestringoptionaltargetstring | Elementoptional#relay-feedback. You can also set it with a data-target attribute on the script tag.minHeightnumberoptionalFramework examples#
import { useEffect } from "react";
export function FeedbackPage({ user }) {
useEffect(() => {
const identity = { userId: user?.id, name: user?.name };
if (window.RelayFeedback) {
// Loaded on an earlier visit to this page: re-attach to the new element.
window.RelayFeedback("identify", identity);
return;
}
window.RelayFeedbackSettings = identity;
const s = document.createElement("script");
s.src = "https://support.notaislop.xyz/feedback.js";
s.dataset.key = "wk_XXXXXXXXXXXXXXXXXXXXXXXX";
s.async = true;
document.body.appendChild(s);
}, [user]);
return <div id="relay-feedback" />;
}import Script from "next/script";
export default function Feedback() {
return (
<>
<h1>Feature requests</h1>
<div id="relay-feedback" />
<Script id="relay-feedback-settings">
{`window.RelayFeedbackSettings = { /* userId, name */ };`}
</Script>
<Script src="https://support.notaislop.xyz/feedback.js" data-key="wk_XXXXXXXXXXXXXXXXXXXXXXXX" strategy="afterInteractive" />
</>
);
}<div id="relay-feedback"></div>
<script src="https://support.notaislop.xyz/feedback.js" data-key="wk_XXXXXXXXXXXXXXXXXXXXXXXX" async></script>Single-page apps
RelayFeedback("identify", …) (or RelayFeedback("mount") if the user hasn’t changed) and the board re-attaches to the element, as in the React example.JavaScript API#
Identify users after sign-in#
When the signed-in user changes, tell the board. The frame reloads with the new identity.
window.RelayFeedback("identify", { userId: user.id, name: user.name }); // after login
window.RelayFeedback("identify", {}); // after logoutuserId and name travel to the board in the URL hash, which browsers never send to the server, so they don’t appear in access logs.
Good for votes, not for authentication
How the embed behaves#
- It fills the width of its container. From 1024px wide it shows two columns (form and list); narrower, they stack.
- Its height follows the content, including after filtering or opening an idea.
- The background is transparent, so the board sits on your page’s background.
- Opening an idea happens inside the frame, and your page scrolls back to the top of the board.
- Upvotes update instantly and roll back if the request fails.
Branding#
The board uses your accent color from Settings → Brand for the upvote state, focus rings, hovered titles and team replies. Changing it there updates every embed on the next page load. For anything beyond color, build your own UI.
Content Security Policy#
script-src https://support.notaislop.xyz;
frame-src https://support.notaislop.xyz;Troubleshooting#
Next#
Manage what comes in from Inbox → Feedback board.