Guide
Interview links
Put a Coretrace interview where your customers already are: in your cancellation flow, or inside your product. One link, no inbox required.
Why links instead of email
Interview invitations sent by email compete with everything else in an inbox, and they arrive after the moment has passed. An interview link meets people at the moment of highest intent:
- Cancellation: right after someone clicks cancel, they know exactly why they're leaving. Ask them then.
- In-product discovery: users who just used a feature, or hit a limit, can tell you what they were trying to do while it's fresh.
Respondents can type, or tap the voice button and just talk (live voice is included on the Growth plan).
Set it up in 3 steps
- Create a project. In Coretrace, choose New Project → Cancellation Interviews or Customer Discovery.
- Turn on the interview link. On the project page, switch on the interview link card. Copy the link or the snippet.
- Add it to your product. Paste the snippet where you want the prompt to appear, and replace the
nulls with your user's id, email, and name if you have them. Pasted as-is, it still works (anonymously).
That's it. Each completed interview shows up in the project with its transcript, classified reasons, and the context you passed.
Implement it with an AI coding assistant
If you use Claude Code, Cursor, Copilot, or a similar tool, you don't need to wire this up by hand. On your project page, click Copy AI prompt on the interview link card. It copies a prompt with your link and interview type already filled in. Open your app's codebase in the assistant, paste it, and review the change it makes.
The assistant handles the part people usually get stuck on: finding where your app keeps the logged-in user and passing their id, email, and name. Here's the cancellation version, for reference:
Add a Coretrace interview button to this app.
Goal: after a user confirms they are cancelling (or on the cancellation page), show an optional button labeled "Before you go, tell us why" that opens a short exit interview in a popup. It must never block or delay the cancellation itself.
Interview link: https://app.coretrace.ai/r/YOUR_LINK_ID
Setup guide: https://coretrace.ai/docs/interview-links
Requirements:
1. Find how this app gets the currently logged-in user (auth/session hook, current_user, request.user, etc.) and pass these query parameters:
- uid: the user's stable internal ID. This lets a returning user resume their interview. Never use a secret or token.
- email and name: from the same user object, if available.
2. If the cancel flow collects a reason, pass it as `reason`. If the app knows the user's plan or how long they've been a customer, pass `plan` and `tenure_months`.
3. Build the URL as https://app.coretrace.ai/r/YOUR_LINK_ID?<params> using URLSearchParams, skipping any null, undefined, or empty values.
4. Open it from the button's click handler (so popup blockers allow it): window.open(url, "coretrace-interview", "width=440,height=760"). If that returns null, open the URL in a new tab instead.
5. Use the app's existing button component and styles. Don't add dependencies.
6. Parameters are visible in the URL and treated as unverified: no passwords, tokens, or sensitive personal data. At most 10 extra parameters; names use letters, numbers, and underscores; values up to 200 characters.
When you're done, tell me which files you changed and where the button appears.
Before you ship it, check two things: the button only opens from a click (so popup blockers allow it), and a test user's interview shows up in your project with the right name and context.
Recipe: cancellation flow
Show a short, optional prompt after the customer confirms cancellation (or on your cancellation page). Keep it clearly optional: they're leaving, and that's fine.
<p>Sorry to see you go. Would you tell us why? It takes about 3 minutes, and you can just talk.</p>
<button onclick="coretraceInterview({
uid: currentUser.id,
email: currentUser.email,
name: currentUser.name,
plan: currentUser.plan,
reason: selectedCancelReason
})">Tell us why</button>
<script>
function coretraceInterview(params) {
var query = new URLSearchParams();
for (var key in params || {}) {
var value = params[key];
if (value !== null && value !== undefined && value !== "") query.append(key, value); // skip missing values
}
var url = "https://app.coretrace.ai/r/YOUR_LINK_ID?" + query;
var popup = window.open(url, "coretrace-interview", "width=440,height=760");
if (!popup) window.open(url, "_blank"); // popup blocked: open a tab instead
}
</script>
If your cancel form asks for a reason, pass it as reason. Core-y starts from it ("I saw you mentioned pricing. What happened there?") instead of asking cold.
React
function TellUsWhy({ user, cancelReason }) {
const open = () => {
const fields = { uid: user.id, email: user.email, name: user.name, reason: cancelReason };
const params = new URLSearchParams(
Object.entries(fields).filter(([, v]) => v != null && v !== "") // skip missing values
);
const url = `https://app.coretrace.ai/r/YOUR_LINK_ID?${params}`;
window.open(url, "coretrace-interview", "width=440,height=760") ?? window.open(url, "_blank");
};
return <button onClick={open}>Tell us why you're leaving</button>;
}
Recipe: in-product discovery
Use a Customer Discovery project and show a prompt to the right users at the right moment, for example after they use a feature a few times or hit a plan limit:
<button onclick="coretraceInterview({ uid: currentUser.id, email: currentUser.email, segment: 'power_user', trigger: 'used_reports_3x' })">
Help shape what we build
</button>
Extra parameters like segment and trigger are saved with each interview, so you can see who said what.
Parameters
| Parameter | What it does |
|---|---|
uid | Your id for this person. The same uid resumes their existing interview instead of starting a new one. Recommended. |
email | Shown on the interview record. Optional. |
name | Full name; Core-y greets them by first name. Or use first_name and last_name. |
company | Company name. Optional. |
| anything else | Up to 10 extra parameters (letters, numbers, and underscores; values up to 200 characters) are saved with the interview and given to Core-y as background context. Examples: plan, reason, tenure_months, segment. |
Everything is optional. With no parameters at all, the interview is anonymous.
Where the values come from
From your own app. The snippet runs on a page where your user is already logged in, so your app already knows who they are: it's the same user object that shows their name in your header. Coretrace never sees your user database; you pass in what you choose.
| Parameter | Typical source |
|---|---|
uid | The logged-in user's id from your auth or session: session.user.id, current_user.id, request.user.id |
email, name | The same user object |
plan | Your billing record, such as the account's plan or Stripe subscription |
reason | The option the user just picked in your cancel form |
Use a stable id for uid. Your internal user id is ideal. Avoid values that change (like an email someone might update) or anything secret (like a session token).
Single-page apps (React, Vue, Svelte)
Read the user from your auth library's hook or store, then call the function from a click handler:
const { user } = useAuth(); // Auth0, Clerk, Supabase, NextAuth, Firebase...
<button onClick={() => coretraceInterview({ uid: user.id, email: user.email, name: user.name })}>
Tell us why
</button>
Server-rendered pages (Rails, Django, Laravel, Express)
Print the values into the page as JSON. JSON encoding keeps names like O'Brien from breaking the quotes:
<!-- Rails (ERB) -->
<script>
var coretraceUser = <%= raw({ uid: current_user.id, email: current_user.email, name: current_user.name }.to_json) %>;
</script>
<button onclick="coretraceInterview(coretraceUser)">Tell us why</button>
<!-- Django -->
{{ coretrace_user|json_script:"coretrace-user" }}
<button onclick="coretraceInterview(JSON.parse(document.getElementById('coretrace-user').textContent))">Tell us why</button>
In Django, build coretrace_user in your view as a dict with uid, email, and name.
No-code builders (Webflow, Bubble, Softr)
Use your builder's custom-code or HTML embed element and insert its "current user" fields where the snippet has null. If your builder can't expose user fields, paste the snippet as-is: interviews will be anonymous but still work.
Missing values are fine
Every parameter is optional. The snippet skips anything that's null, undefined, or empty, so a user without a name on file just gets a generic greeting.
How links behave
- Resume, don't duplicate: a returning
uidgoes back to their open interview, or to their thank-you page if they already finished. - Plan limits apply: completed interviews count toward your plan's monthly interview limit. To prevent abuse, each project also accepts up to 3× that many started interviews per 30 days, and each visitor's IP can start up to 20 per hour.
- Turning it off: switching off the link (or completing the project) shows visitors a polite "this link isn't active" page.
- Voice: live voice interviews are available on Growth when enabled for the project. Sessions are capped at 20 minutes.
Security and privacy
Links are public. Anyone with the link can start an interview, and parameters can be edited by the visitor. Treat uid, email, and extra parameters as unverified context, and never put secrets or sensitive personal data in them.
- If a link is shared somewhere it shouldn't be, use Regenerate link on the project page. The old link stops working immediately.
- Voice audio is never recorded or stored. Only the transcript is saved.
- Parameters you pass are stored with the interview and processed as described in our Privacy Policy.
Questions? hello@coretrace.ai