Documentation

User authentication

Sign identity JWTs and control who can submit feedback or chat.

What it does

User Authentication lets your product prove who is logged in with a signed identity JWT. Your backend signs the token with your project secret key; Gatherly verifies it before treating someone as authenticated, storing their identity on feedback, or opening Chats.

Plain HTML attributes like data-auth-email are not proof of identity— anyone can change them in DevTools. Only a JWT signed with your secret key counts.

Configure it under Project → User Authentication. The Embed page updates the pasteable snippet to match your settings.

Secret key

Each project has a secret key starting with sk_live_. Copy it from User Authentication settings. Keep it on your server only — never put it in the embed script, front-end bundles, or public repos.

  • Use the secret to sign identity JWTs on your backend after login.
  • Regenerating the key immediately invalidates existing tokens until you mint new ones.

Identity JWT claims

Sign an HS256 JWT with your project secret. Claims:

ClaimRequiredNotes
user_idYesStable id in your product. Stored as external_user_id.
emailYesUser email address.
usernameWhen data mode is email + usernameDisplay name or handle. Omit when data mode is email only.
image_urlNoAvatar URL (http/https). Updates the user's latest-known profile.
planNoFree-form plan/tier label from your product (e.g. free, pro).
stripe_customer_idNoYour Stripe customer id so you can open the customer in the Stripe dashboard from Gatherly.
expYesExpiry. Prefer ≤ 1 hour; Gatherly rejects tokens older than 24 hours from issue.

Optional profile claims (image_url, plan, stripe_customer_id) are stored as the user's latest-known profile on each authenticated feedback, review, or chat request. Omitting a claim leaves the previous value unchanged.

Setup for your stack

Mint an identity JWT on a server you control, then pass it to the embed. Choose your platform for copy-paste examples. Each snippet is labeled Server (backend / template) or Client (browser). The secret key always stays as an environment variable — never in client code.

  • Your server must mint the JWT and render it into the page — never sign with the secret in browser JavaScript.
  • For static hosting only, skip verified auth or call a small backend that returns a token.

Mint on your server (Node)

javascript
Server
import { SignJWT } from "jose";

const secret = new TextEncoder().encode(process.env.GATHERLY_SECRET_KEY);

const token = await new SignJWT({
  user_id: user.id,
  email: user.email,
  username: user.username, // omit if email-only mode
  image_url: user.avatarUrl, // optional
  plan: user.plan, // optional
  stripe_customer_id: user.stripeCustomerId, // optional
})
  .setProtectedHeader({ alg: "HS256" })
  .setIssuedAt()
  .setExpirationTime("1h")
  .sign(secret);

Render the token (from your server template)

html
Server
<script
  src="https://YOUR_DOMAIN/embed.js"
  data-key="pk_live_…"
  data-auth-token="{{ identity_jwt }}"
  data-auth-email="USER_EMAIL"
  data-auth-username="USER_USERNAME"
  async
></script>

Copy your secret from Project → User Authentication into GATHERLY_SECRET_KEY on your server. After SPA login or logout without a full page reload, call Gatherly.invalidate() — see JavaScript API.

Who can give feedback

Audience controls who may submit. The API enforces this on every POST /api/feedback; the widget also hides the launcher when the visitor is not allowed. Authenticated means a valid identity JWT.

AudienceWho can submit
All usersAnyone — with or without data-auth-token
Only authenticatedVisitors with a valid data-auth-token
Only unauthenticatedVisitors without data-auth-token

Bug report screenshots also require authentication: only visitors with a valid identity JWT can attach images. Anonymous users can still submit text-only bugs when your audience allows it. See Feedback API for the upload flow.

Chats

The embed Chat tab is only shown when a token is present. Users can open multiple chats; your team replies from Dashboard → Chats. You can also start a chat from the dashboard (or via Users → Message) to reach early users without email. Chat APIs always require a verified JWT on the widget side — spoofing email in DevTools cannot list or send messages as another user.

How the widget decides

  1. On load, the embed fetches /api/embed/config?key=… for your project’s enabled flag, audience, and data mode.
  2. A visitor is treated as authenticated when auth is enabled and data-auth-token is present. The API verifies the JWT with your secret on every request.
  3. After config loads, if the audience does not allow that visitor, the launcher stays hidden.
  4. Allowed authenticated submissions include the token (body or Authorization: Bearer). Identity fields are taken from verified claims, not from editable script attributes.
  5. Auth attributes are read once at load. In an SPA, after login or logout update (or clear) the script attributes and call Gatherly.invalidate() so the launcher shows or hides without a full refresh. See JavaScript API.