Conditional Display: Show Feedback at the Right Time
Control when the feedback embed appears based on user state, page URL, or custom application logic.
A feedback button on your checkout page competes with the checkout. One on a signup form competes with the signup. The fix is to construct the embed yourself, when you want it, instead of letting the script tag do it on every page.
When this is worth doing
New users have nothing to say yet. Logged-out visitors mostly report that they cannot log in. A checkout has one job. And if you want to know whether the embed itself is worth having, showing it to half your traffic is the only way to find out.
Constructing it yourself
Drop the auto-init script tag and call the constructor when the condition holds:
<!-- Load the library without auto-init -->
<script src="https://cdn.qaid.dev/embed.js"></script>
<script>
// Initialize only when your conditions are met
if (shouldShowFeedback()) {
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key",
position: "bottom-right"
});
}
</script>
Nothing renders until that line runs.
Only for signed-in users
The most common gate, and the one that improves quality most:
// Check your auth state
const user = await getCurrentUser();
if (user) {
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
Only on certain pages
Match on the path:
// Show only on dashboard pages
const allowedPaths = ["/dashboard", "/settings", "/projects"];
if (allowedPaths.some(path => window.location.pathname.startsWith(path))) {
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
Or against a list, when the routes are not a prefix:
// Show on all pages except auth flows
const blockedPaths = ["/login", "/signup", "/reset-password", "/verify"];
const isBlockedPath = blockedPaths.some(path =>
window.location.pathname.startsWith(path)
);
if (!isBlockedPath) {
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
Staying out of onboarding
Somebody four steps into a setup wizard does not want a third opinion:
// Check if user has completed onboarding
const user = await getCurrentUser();
if (user && user.onboardingComplete) {
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
If the embed is already up when they enter the flow, take it down:
function startOnboarding() {
// Remove feedback embed during onboarding
if (window.qaid) {
window.qaid.destroy();
window.qaid = null;
}
// Begin onboarding...
showOnboardingModal();
}
function completeOnboarding() {
// Re-initialize after onboarding
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
What destroy() does
Calling destroy() removes the DOM the embed created and unbinds every listener it added:
const embed = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
// Later, when you need to remove it
embed.destroy();
Call it on sign-out, on the way into checkout or account deletion, and on any single-page navigation that leaves a section where feedback made sense. Construct a fresh one when you want it back.
// Example: Remove on logout
async function logout() {
if (window.qaid) {
window.qaid.destroy();
window.qaid = null;
}
await signOut();
redirect("/login");
}
Combining the gates
Real apps stack these:
async function initializeFeedback() {
const user = await getCurrentUser();
const path = window.location.pathname;
// Must be logged in
if (!user) return;
// Must have completed onboarding
if (!user.onboardingComplete) return;
// Must not be on blocked pages
const blockedPaths = ["/checkout", "/delete-account"];
if (blockedPaths.some(p => path.startsWith(p))) return;
// Optional: Only show to a percentage of users
if (user.id % 100 >= 50) return; // 50% rollout
window.qaid = new Qaid.QaidFeedback({
apiKey: "your-api-key"
});
}
initializeFeedback();
Where this leaves you
You will collect less feedback this way. It will be from people who have used the product, on pages where they had a choice about answering, and you will read all of it.