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:

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

  1. Create a project. In Coretrace, choose New Project → Cancellation Interviews or Customer Discovery.
  2. Turn on the interview link. On the project page, switch on the interview link card. Copy the link or the snippet.
  3. 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

ParameterWhat it does
uidYour id for this person. The same uid resumes their existing interview instead of starting a new one. Recommended.
emailShown on the interview record. Optional.
nameFull name; Core-y greets them by first name. Or use first_name and last_name.
companyCompany name. Optional.
anything elseUp 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.

ParameterTypical source
uidThe logged-in user's id from your auth or session: session.user.id, current_user.id, request.user.id
email, nameThe same user object
planYour billing record, such as the account's plan or Stripe subscription
reasonThe 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

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.

Questions? hello@coretrace.ai