How to get there: Go to Settings in the sidebar → Authentication tab → scroll to Single Sign-On (SSO).
When you receive feedback, you should know who gave it (free user, paid user, or enterprise customer). But more importantly, you want to inform them what you do with their feedback.
For this, we need to gather their email address to contact them, and it would be logical if users could log in again when they have additional feedback or questions.
For this reason, ProductLift has user accounts, and people can sign up for a new account and leave feedback.
When you want users to avoid creating a new account (people may forget passwords), you have several options:
In this article, we are going to set up #3 and #4. For Microsoft 365 SSO, see its dedicated guide.
ProductLift supports two integration methods:
| Method | Identity verification | When to use it |
|---|---|---|
JavaScript SDK (ProductLiftIdentify) |
Accepts the email, UID and name supplied by the browser. No server signature is required. | A simple integration where you accept that visitors can submit another user's identity. |
| Server-signed JWT | Your backend authenticates the user and signs a JWT using your portal's SSO secret. | Private portals, restricted content, or any integration that must prevent user impersonation. |
By default, both methods remain available for compatibility with existing integrations. Merely switching your application to server-signed JWTs does not disable SDK identification. SDK identification can let someone act as another member, including viewing content available to that member and posting or voting as them.
Use Allow members to sign in through your app in the Single Sign-On (SSO) section, then save. Turning it off blocks SDK identification, JWT sign-in and SSO access to embedded widgets. It also hides your app's button from the ProductLift login page. Existing login sessions stay active; email/password, social login and Microsoft 365 remain separate settings.
SSO is on by default to preserve existing integrations. Turning it off hides the configuration fields but keeps your verification choice, login URL, button text and secret so you can enable it again later. Still-valid tokens can work again after re-enabling SSO. Rotate the secret if you also want to invalidate previously issued tokens permanently.
The SSO secret is masked by default. Use Show to reveal it or Copy to copy it without revealing it. Regenerate Secret creates a new key and invalidates tokens signed with the previous key; update your server or WordPress plugin afterwards.
?sso=TOKEN on portal links, iframe URLs, or the SDK script URL shown below. Plain ProductLiftIdentify({ email, uid, name }) calls will no longer authenticate users.When enabled, POST /api/generate-sso-token returns 403 with code: "signed_sso_required". New SDK tokens carry a signed productlift_sso_source: "sdk" marker and are rejected by both portal login and widget token validation, including tokens cached before the setting was enabled. Do not set that reserved marker in your own server-signed tokens.
Older tokens and immediate invalidation: SDK tokens issued before this feature do not carry the marker. They were signed with the same secret as server-generated tokens, so their origin cannot be distinguished. They can remain valid for up to one hour after issuance. For immediate invalidation, first enable and save the setting, then use Regenerate Secret and update your backend with the new secret. This invalidates all tokens signed with the old secret, including your own server-generated tokens. Generate fresh tokens after updating your backend. Saving the verification setting itself does not rotate the secret or end existing login sessions.
This setting controls SSO verification independently of Show “Log in with your app” on the ProductLift login page, which configures the optional login redirect. It does not disable email/password, social login, or Microsoft 365 login. If members should only use JWT SSO, configure those other login methods separately. Portal admins cannot sign in through either SDK identification or JWT SSO; keep their normal administrator login available.
Turning the setting off restores SDK identification and permits still-valid SDK tokens again.
In Settings → Authentication → Single Sign-On (SSO), find Login page button. Turn on Show “Log in with your app” on the ProductLift login page, enter Your app's login URL and Button text, then save.
When visitors click the button, they go to your app to authenticate. Your integration then returns them to ProductLift with a signed token. This button is optional: leave it off if users already arrive signed in through links or embedded widgets. It does not enable or disable token-based sign-in, and it does not change your identity verification choice.
We use a secure protocol called JSON Web Token (JWT) to enable SSO to transfer user authentication data from your system to ProductLift. JWT is open, simple, and with solid community support. You can read more about it on the IETF website, and you'll be able to find a large number of open-source implementations for most languages.
The simplest sign-on is using our JavaScript SDK. This method requires Standard (JavaScript SDK) to be selected and does not verify who owns the supplied identity.
You should load the SDK in your app.
Then add the identify script, like below.
<script>
window.PQ=window.PQ||[];window.ProductLiftIdentify=window.ProductLiftIdentify||function(u){PQ.push(u)};
ProductLiftIdentify({
email: 'john@example.com',
uid: '123',
name: 'John Doe',
// Optional
avatar_url: 'https://example.com/avatar.jpg',
// sync_profile: true, // Optional: overwrite an existing member's name and supplied avatar
company: 'ACME Corp',
mrr: '99.99',
// Optional segment fields:
segment_1: 'developer',
segment_2: 'premium',
segment_3: 'early_adopter',
// ... up to segment_10
arr: '1199.88',
ltv: '3599.64',
group: ['beta-testers', 'enterprise'],
language: 'fr' // Optional, sets the user's preferred portal language
});
</script>
The ProductLiftIdentify function accepts an object with user data. You should include the required fields (email, uid, name) and any optional fields that are relevant to your use case. See below the list.
With SSO arranged, you can add data-productlift-link to enable auto login for an URL.
<a href="https://feedback.yourdomain.com" data-productlift-link>See our roadmap</a>
You can also use this in iFrames, for example.
<iframe src="https://app.productlift.dev/t/wish-list?widget_id=a4351156-d05a-4989-8c72-bf6cf88a99ae" data-productlift-link width="100%" height="600px" frameborder="0"></iframe>
In case you cannot add elements to these HTML codes (some website builders block it), you can add "data-productlift-link" as a class.
You should create a JWT token on your end using the SSO secret that we provide.
You can find your SSO secret at Settings → Authentication → Single Sign-On (SSO).
Generate a JWT SSO token on your end and sign it with your SSO secret. You can find several examples of creating a token on the IETF website.
The contents should look something like this:
$payload = [
'email' => 'john@me.com',
'uid' => '123',
'name' => 'John James',
'iat' => time(),
'exp' => time() + 300, // Expires after five minutes
// 'avatar_url' => 'https://i.pravatar.cc/150?img=61',
// 'sync_profile' => true, // Optional: overwrite the existing forum profile
// 'segment_1' => 'developer',
// 'company' => 'ABC',
// 'mrr' => '10.99',
// 'language' => 'fr',
];
$token = JWT::encode($payload, $private_key, 'HS256');Explaining the fields in the payload:
sync_profile is true.false. Set to true to update an existing member's display name and, when supplied, avatar from this sign-in. Use a JSON boolean (true or false); SDK requests with strings, numbers or null are rejected. Applies to both the JavaScript SDK and server-signed JWTs.{ id, name, domain, monthlySpend, ltv, plan, status, created, customFields }. id is your own identifier for the account and is remembered, so a later rename lands on the same company. domain lets ProductLift link new colleagues automatically by their email domain. monthlySpend sets the company's MRR. Only the first entry is used.en, nl, fr, de, es, pt, it, pl, zh, zh-tw, ja, ko, tr, ru). The value must match a locale enabled on your portal under Settings > General > Languages, otherwise it is ignored. This skips your user's "pick a language" step on the portal entirely.SSO sets the display name and optional avatar when it creates an account. On later sign-ins, ProductLift preserves those values so members can choose a forum name for privacy. Linking SSO to an existing account by email also preserves its profile. You can keep sending name and avatar_url; no API lookup is needed. name remains required in every sign-in payload.
If your application should control the forum profile, send sync_profile: true on each SDK identification or 'sync_profile' => true in each server-signed JWT. The name is then updated, and the avatar is updated only when a non-null avatar_url is supplied. An omitted or null avatar does not clear the current avatar. SDK identification with sync_profile: true requests a fresh token instead of reusing the cached identity token. That token is not saved to the identity cache, so later identifications without the flag cannot inherit the synchronization request.
Other SSO fields, including email, company, revenue, segments, groups and language, keep their existing synchronization behavior. sync_profile only controls the display name and avatar.
Change for existing integrations: Previously, each SSO sign-in overwrote the name and any supplied avatar. Integrations that need that behavior must now explicitly send sync_profile: true.
uid. If no match exists, an existing account with the supplied email is reused only when it has no SSO UID yet. An email already linked to a different UID is rejected. Keep UIDs stable and unique. Your backend must verify the user identity before issuing a server-signed token.
When you have the token, you can apply it easily by adding ?sso=TOKEN to any url of your portal.
For example:
It is possible to add the token to the ProductLift SDK. This way users can interact with the widgets without logging in.
<a href="#" data-productlift-sidebar="3b31866b-b281-437f-b3f5-928f9a8fab35">Open Widget</a>
<!-- ProductLift SDK - Include it only once -->
<script defer src="https://app.productlift.dev/widgets_sdk?sso=TOKEN"></script>
This data is currently visible to administrators on the user's profile page. Click on the user to view their profile.

In upcoming updates, you'll gain the ability to filter posts and categorize 'likes' based on this data, enhancing user engagement insights and content targeting.
If you embed ProductLift inside another application via an iframe, browsers now block third-party cookies by default. That breaks the normal session-cookie flow: the user appears logged out inside the iframe even though they are logged in on your host page.
ProductLift supports a cookieless SSO flow for exactly this case:
?sso={TOKEN} on the src of the iframe.Soft-deleted users: if a user was previously soft-deleted (e.g. removed and re-added on your side), the cookieless flow recreates the ProductLift user record automatically on the next signed request instead of erroring. You do not need to hard-delete or purge anything before re-onboarding a user.
Keep tokens short-lived (a few minutes is fine) and generate a new one for each iframe load rather than sharing one broadly.