Welcome to Encatch Docs
Shareable Feedback

User Identification

Identify respondents and attach contact traits through shareable feedback links

You can identify a respondent and provide contact traits by adding contact_ query parameters to a shareable feedback link. This is useful for email surveys, customer follow-ups, lifecycle campaigns, and other situations where you already know who will receive the link.

For example:

https://form.encatch.com/<shareable-link-id>?contact_id=customer_123&contact_email=alice%40example.com&contact_display_name=Alice&contact_plan=pro

The example identifies the respondent as customer_123 and supplies their email address, display name, and plan.

Contact parameters are not authentication by default

Anyone who can access or modify an unsigned link can change its query parameters. Use optional identity verification when the respondent's identity needs to be trusted.

Parameter format

ParameterPurpose
contact_idStable external identifier for the respondent
contact_emailRespondent's email address and email-only fallback identifier
contact_<trait-slug>Contact trait to associate with the respondent
contact_signatureOptional server-generated HMAC identity signature
contact_signature_timeOptional signature timestamp in Unix epoch milliseconds

Parameters are case-sensitive. Use the exact lowercase contact_ prefix.

Choose the contact identifier

For the most reliable cross-channel history, provide contact_id using the same stable identifier that your application uses with identifyUser:

?contact_id=customer_123

The identifier must contain 1–50 ASCII characters. Letters, numbers, ., _, @, and - are supported. Spaces, Unicode characters, and other symbols are not supported.

You can identify a respondent using only their email address:

?contact_email=alice%40example.com

When both parameters are present, contact_id is the identity and contact_email is stored as the email trait:

?contact_id=customer_123&contact_email=alice%40example.com

Prefer contact_id when the same person may receive email surveys and use an application where they are identified through the Web or Mobile SDK. Reusing the same identifier keeps their feedback activity associated with one contact.

Add contact traits

Add contact_ before a user-trait slug:

?contact_id=customer_123&contact_display_name=Alice&contact_plan=pro&contact_region=IN

This supplies the following traits:

{
  "display_name": "Alice",
  "plan": "pro",
  "region": "IN"
}

Trait slugs may contain lowercase letters, numbers, and underscores. URL traits use merge semantics: supplied values set or overwrite the corresponding trait, while traits omitted from the link remain unchanged.

The link cannot perform advanced trait operations such as incrementing, decrementing, removing traits, or replacing the complete contact record.

Projects can control whether previously unknown traits may be created from client data. If automatic trait creation is disabled, only existing enabled traits are accepted. See User Traits.

Values are strings

URL contact values are read as strings. Existing trait configuration may validate or convert an accepted value according to the trait's data type. Numeric-looking identifiers and values are not automatically converted by the URL parser.

Combine identification with response prefilling

contact_ and response_ parameters have separate purposes and can be used in the same link:

https://form.encatch.com/<shareable-link-id>?contact_id=customer_123&contact_plan=pro&response_nps=9
  • contact_id and contact_plan describe the respondent.
  • response_nps supplies the initial answer to the NPS question.

Opening the link does not submit the prefilled answer. The respondent can review or change it before submitting. See Advanced Configuration for supported response formats.

When the contact is created or updated

Opening a shareable link performs a read-only contact lookup. It does not create a new contact or update an existing contact merely because the page was loaded.

A contact is created or updated when one of these events occurs:

  • The respondent submits the form.
  • An eligible partial response is saved after the respondent's effective answers differ from the initialized prefilled answers.

If someone opens the link and leaves without interacting, no contact or response is created. This also prevents ordinary email-link previews and page scans from creating contacts.

Optional identity verification

Unsigned links are supported by default. For cases where the supplied identity must be verified, generate an HMAC signature on your server and add it to the link:

?contact_id=customer_123&contact_signature=<server-generated-signature>

Never generate the signature in browser code or expose your secret key in the link. Keep the secret on your server. See Publishable SDK Keys.

When no signature session timeout is configured, sign the identifier:

import crypto from 'node:crypto';

const signature = crypto
  .createHmac('sha256', process.env.ENCATCH_SECRET_KEY)
  .update('customer_123')
  .digest('hex');

When a session timeout is configured, include the current Unix epoch time in milliseconds in both the signed value and URL:

import crypto from 'node:crypto';

const contactId = 'customer_123';
const timestamp = String(Date.now());
const signature = crypto
  .createHmac('sha256', process.env.ENCATCH_SECRET_KEY)
  .update(contactId + timestamp)
  .digest('hex');
?contact_id=customer_123&contact_signature=<signature>&contact_signature_time=<timestamp>

contact_signature_time is optional in the URL format but required when the configured signature policy uses a session timeout. If email is the only identifier, use the email address as the value being signed.

Identity verification verifies the identifier. It does not make other URL parameters secret, and an identity-only signature does not protect arbitrary contact_ or response_ values from modification.

Use URL and URLSearchParams instead of manually joining query strings:

const link = new URL('https://form.encatch.com/<shareable-link-id>');

link.searchParams.set('contact_id', 'customer_123');
link.searchParams.set('contact_email', 'alice@example.com');
link.searchParams.set('contact_display_name', 'Alice & Bob');
link.searchParams.set('contact_plan', 'pro');

console.log(link.toString());

This correctly percent-encodes characters such as @, spaces, &, +, and Unicode characters in trait values.

Avoid unnecessary personal data in URLs

Query parameters can appear in browser history, email security systems, proxy and server logs, analytics tools, referrer information, and copied links. Prefer an opaque contact_id and include only the traits needed for the survey. Never include passwords, secret keys, access tokens, or sensitive personal data.

Invalid parameters

Invalid contact parameters are ignored independently. They do not prevent other valid contact or response parameters from being processed.

A contact parameter may be ignored when:

  • The same parameter appears more than once.
  • Its value is empty.
  • contact_id contains unsupported characters or exceeds 50 characters.
  • contact_email is not a valid email address.
  • A trait slug contains uppercase letters, hyphens, brackets, or other unsupported characters.
  • Bracketed or nested contact syntax is used.
  • The link supplies more than 25 custom contact traits.
  • A signature timestamp is malformed or is provided without a signature.
  • A signature is provided without contact_id or contact_email.

Unlike multi-value response questions, contact parameters do not support repeated values, comma-separated lists, or bracketed member keys.

Persistence and source tracking

Contact identity and accepted traits participate in the retained-draft scope. Opening links for two different contacts in the same browser does not restore one contact's draft into the other contact's form.

Signature and timestamp values do not participate in the draft identity, so regenerating a signature for the same contact and traits does not create another draft scope.

All contact_ and response_ parameters are excluded from Source Tracking. Other URL parameters continue to follow the form's source-tracking configuration.

Was this page helpful?