Skip to content

Generate your own survey links (embedded surveys)

This guide collects the different ways to generate an nps.today survey link yourself, so you can send or embed it from your own system (an ESP such as Agillic, a CRM, or a newsletter tool) instead of letting nps.today send the email. In every case the survey is still created and reported in nps.today, only the delivery happens in your system.

To keep responses tied to a person (not anonymous), you generate a personalized link that carries the respondent's data.

Which method should I use?

Method API key Hashing / secret Campaign member created Best for
1. Personalized link via script No Yes On reply Bulk sends from your own email/ESP, generated upstream in a script or middleware
2. API (GenerateLink) Yes No At generation Systems that can call the API and prefer not to hash

The "Campaign member created" column matters for volume: On reply means nothing is recorded in nps.today until the respondent actually answers, while At generation creates the member up front.

Prerequisites

  • An nps.today campaign. You'll need its campaignID (the numeric id, e.g. 19090). See How to find campaignID.
  • For the script method: the campaign Secret.
    1. Open the campaign
    2. Click Send Out Survey
    3. Go to the Unique Personalized Link tab
    4. Click the eye icon in the Secret field
    5. Copy the value Find Secrect
  • For the API method: an nps.today API key and the API module. See How to create an API key.
  • A system that can insert the link into an email.

Keep responses identifiable

Include at least one identifying field in the link (typically email and/or ext, your own contact id). Without any respondent data the response cannot be linked back to a person.

A personalized link is a campaign‑specific, single‑use link that you build and sign yourself, with no API call. It carries the respondent's details and a signature (sha) so nps.today can trust it.

Review script example

This section wil refer to this script.

See code examples to get you started if you wish to generate the link using a script: Generate link with script.

Campaign member creation

The campaign member is created only when the respondent answers. No campaign member or response is recorded in nps.today until then, which makes this a good fit for large sends where you expect a low response rate.

The link format is:

https://r.nps.today?cid=19090&firstName=John&lastName=Doe&[email protected]&phone=4512345678&ext=CRM-42&id=<GUID>&employee=&sha=7fab5a3b9d39321213ee6d7dc7a30990a820f2a3239623d078f2a42dd6051976

cid: your campaignID.
id: a unique GUID you generate for each recipient. This is what makes every link unique and single‑use.
firstName, lastName, email, phone, ext, employee: optional fields. Include at least one identifying field for non‑anonymous responses. Omit any field you don't use.
sha: the signature (see below).

You can also append your own custom fields after sha. Any field name that isn't reserved is stored as custom data on the respondent.

Calculating the sha

The sha is a SHA‑256 hash that proves the link was generated by you. You create one per recipient. In practice:

  1. Collect the field values for the recipient, for the fields you intend to include.
  2. Build the content string: concatenate the values into a single string, in this exact order, with no separators, and your secret added at the very end:
    cid + firstName + lastName + email + phone + ext + id + employee + secret
    
    If you don't use a field, leave it out of both the string and the URL, and keep the remaining fields in the same order.
  3. Hash it with SHA‑256 and take the lowercase hex output. That string is your sha.
  4. Assemble the URL from the raw field values plus &sha=, then URL‑encode the finished URL. The sha is hex, so encoding doesn't change it.

Only these fields are hashed

Only the fields listed above go into the hash. Custom fields, rating, and the sha itself are never part of the hashed string. It is a plain hash, not an HMAC — the secret is simply the last thing concatenated before hashing.

Worked example

With the following values (and a fixed id so it's reproducible):

Field Value
cid 19090
firstName John
lastName Doe
email [email protected]
phone 4512345678
ext 42
id b77063db-181c-4084-957f-590c04de255c
employee [email protected]
secret 12C48F78F6BQ141EDC9B71C48367251E (example only — use your own)

the content string is:

19090JohnDoejohn@example.com451234567842b77063db-181c-4084-957f-590c04de255cemployee@company.com12C48F78F6BQ141EDC9B71C48367251E

Notice the string has no field value like ?cid= or &firstName= prefixes and no separators. Those are added only when you build the URL.

and its SHA‑256 hex is:

861643e614da458e5d46c134293a5fe8e3ea49209bf6c9e91c9d9eeac2113d70

The hash depends on the exact values, the id, and your secret, so every recipient's link has a different sha.

Where to generate it in practice

Most email systems can't compute a SHA‑256 inside a template, so don't try to hash in the email editor. Generate the finished link upstream in a small script, your CRM, or middleware (for example a Power Automate flow or a function) using one of the snippets below and then pass the complete URL into your email as a personalization / merge field.

If you'd rather not compute a hash or hold the secret in your own system, you can let nps.today mint the link for you. Call the Generate link endpoint per respondent, map the respondent's data in the request, and embed the link it returns:

Campaign member creation

A campaign member is generated as soon as you call GenerateLink. While this increases overall survey volume (since it occurs before submission), it enables you to track and calculate response rates. The returned id references this pre-existing campaign member in nps.today.

See the endpoint in the API reference. The returned link can be used in its short form, where id refers to the campaign member the API already created and mapped, so no cid or sha is needed.

URL:

https://api.nps.today/campaigns/{campaignId}/GenerateLink

Here is an example of the body:

[
    {
        "respondent": {
            "emailAddress": "[email protected]",
            "firstName": "John",
            "lastName": "Doe",
            "company": {
                "name": "nps.today"
            }
        },
        "employee": {
            "email": "[email protected]",
            "firstName": "Janne",
            "lastName": "Hansen"
        },
        "custom": {
            "ticketid": "1209381dsf1"
        }
    }
]

The returned id (GUID) is used together with the base URL;

81ad980e-a6ca-4ae4-a38e-d627d8551926

Base URL:

https://r.nps.today

Unique survey link:

https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926
Rating links used in the rating boxes for your embedded survey will then look like this:
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=0
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=1
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=2
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=3
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=4
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=5
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=6
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=7
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=8
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=9
https://r.nps.today?id=81ad980e-a6ca-4ae4-a38e-d627d8551926&rating=10

Confirm the request/response against the API reference

Take the exact request body and response shape for GenerateLink from the API reference rather than assuming them.

Verify your setup

  1. Generate a single link with test values and open it in a browser.
  2. Submit a rating, then confirm the response and the mapped fields appear on the campaign in nps.today.
  3. For the script method, also generate one link in the app (Send Out Survey → Unique Personalized Link) with the same values and compare the sha. If they match, your secret and field order are correct, and you can move to production.

Tip

Test with one record before rolling out to a full list.


Need a hand? Reach out to nps.today support via the support page.