Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • Contact Us
  • Home
  • Installing Appcues Web

Identity Verification

Learn how to use Identity Verification to ensure only users you verify can access their Appcues experiences.

Written by Sean Edwards

Updated at December 12th, 2024

Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • FAQs
  • Support
  • Installation & Developers
    Installing Appcues Web API & Data Extras Troubleshooting Installing Appcues Mobile
  • Web Experiences
    Studio Building Web Experiences Customization & Styling FAQ Targeting Troubleshooting Use Cases
  • Mobile Experiences
    Building Mobile Experiences Installation & Overview Troubleshooting Mobile Analytics & Integrations
  • Account Management
    Subscription Users & Data
  • Analytics
    Experience and Event Analytics Data
  • Best Practices
    Product-led Growth Pro Tips Best Practices Use Cases
  • Integrations
    Integration Documents Extras Use Cases
  • System Status
    System Status & Incidents
  • Workflows
    Use Cases Building & Configuration Workflow Analytics and Integrations
+ More

Introduction

Identity Verification lets you digitally sign the UserID sent to Appcues when identifying users to ensure only users you verify can access their Appcues experiences. Implementing Identity verification ensures 3rd parties cannot pretend to be other users and see Appcues experiences not intended for them.  

Implementing Identity verification requires three steps to be performed by one of your developers:

  1. Add code to your product's backend to generate a signature for any UserID and provide that signature to the Appcues JavaScript SDK and/or Mobile SDKs. 
  2. Test and verify that valid signatures are provided when making calls to the Appcues SDK, across all your websites or mobile apps that use Appcues.
  3. Once verified, you can enforce identity verification by enabling Enforcement Mode to reject any Appcues SDK calls that do not contain valid signatures. 

That is it!    

To set up Identify Verification (Developers)

As a software developer for your product, you will need to:

  1. Generate a UserID signature on your backend server. The Appcues SDK will use this signature to verify that users can only see content intended for their UserID.
  2. Deliver that UserID signature to your website or mobile app.
  3. Provide the UserID signature before making any calls to the Appcues SDK using the instructions below.

Generating the UserID signature

Add the appropriate code to your product's backend server using one of the backend code samples at the bottom of this page for a guide.  

Once the signature is generated, you must securely provide it to the Appcues SDK in your web or mobile application or when using the Appcues HTTP API or Appcues Launchpad as described below. If your product uses server-side page rendering, you should embed the signature into the page delivered to the browser. Otherwise, make an authenticated API call to your backend server to retrieve the signature.  

By default, signatures are valid for 15 minutes after generating them. If you have a long-running single-page web app or mobile app, this could result in calls to the SDK failing after 15 minutes. If your app must call the Appcues SDK calls more than 15 minutes after obtaining a valid signature, you can either

  • change the time to longer than 15 minutes in the appropriate code sample provided below 
  • request an updated signature from your backend server  

Set the signature before making calls to the Appcues SDK 

It is important to provide the signature before making any calls to the Appcues SDK. If Enforcement Mode is enabled while calls are made to Appcues.track(), Appcues.page(), or any other Appcues SDK methods before providing a signature, data will not be sent to Appcues' servers, and experiences will not be shown.  As soon as a valid signature has been set, data will be sent to Appcues' servers to qualify and show Appcues experiences. If the signature is never set and Enforcement Mode is on, the user will not see Appcues experiences across any mobile or web apps using the Appcues SDK for that account.  

Note: Different behavior will occur when Enforcement Mode is off (the default), as described in the Testing Identity Verification section below. 

Note: If using Segment.io, the signature must be specified before calling Segment too.

 

 

Provide the Signature to the Appcues Javascript SDK

The process is the same if Appcues is installed directly or through Segment, Rudderstack, or any other third-party tool.

Assign the UserID Signature to window.AppcuesSettings.userIdSignature as follows.


// retain any Appcues SDK settings that may have been set prior
if (window.AppcuesSettings) {
  window.AppcuesSettings.userIdSignature = signature;
} else {
  window.AppcuesSettings = { userIdSignature: signature };
}
// Your Appcues.identify() call, or equivalent call for Segment, Rudderstack, etc. goes below

Provide the Signature to the Appcues Mobile SDK

Pass a user property called appcues:user_id_signature on the identify(userId, props) call. Note this requires Appcues mobile SDK version >= 1.4.0.

# Android / Kotlin
appcues.identify(userId, mapOf("appcues:user_id_signature" to signature))
# iOS / Swift
appcues.identify(userID: userID, properties: ["appcues:user_id_signature": signature])

This signature will be used in an Authorization header on network requests from the SDK. The Appcues API will use this signature to verify that the requests from the client are authorized using an SDK key configured in Appcues Studio.


Provide the Signature to Appcues Launchpad

If you are using the Appcues Launchpad Custom Install, you need to provide the signature as described in the Request Headers section Appcues Launchpad Custom Install documentation.   Note: If using the standard (not custom) Launchpad installation, you do not need to provide the signature. 
 

Testing Identity Verification

While Enforcement Mode is disabled (the default), the following behavior will occur:  

See the next section “Enforcing Identity Verification” for what happens when Enforcement Mode is enabled.

 
  • If no signature is provided to the SDK OR a valid signature is provided to the SDK:
    • Calls to the SDK will work, and Experiences will be shown to users according to the targeting settings of your Appcues Flows and other experiences.
  • If an invalid signature is provided to the SDK: 
    • Calls to the SDK will fail, and Experiences will not be shown to users.  Ensure the signature you provided to the SDK is valid according to the instructions in ‘Generating the UserID signature.’

To locally test web apps if the signature is missing while Enforcement Mode is disabled: 

If Enforcement Mode is disabled (the default) and you do not provide a signature, the user will still see Appcues experiences.  To locally test for this scenario with web apps, add the following line of code before your first call to the Appcues JavaScript SDK.  

// Allow testing Identity Verification locally with console messages
window.APPCUES_TEST_IDENTITY_VERIFICATION = true;

When window.APPCUES_TEST_IDENTITY_VERIFICATION = true you will see one the following messages in the JavaScript console, after every call to the Appcues SDK.  

  • Appcues Identity Verification Testing: Successfully sent update to API using User ID Signature
    • This console message means that a valid signature was provided before a call to the SDK 
  • Appcues Identity Verification Testing: Failed to send update to API - verification failure: No User ID Signature present
    • This console message means a signature was not provided before a call was made to the Appcues SDK and an Experience was not shown.  
  • Appcues Identity Verification Testing: Failed to send update to API - verification failure: Invalid User ID Signature NNNN 
    • This console message means an invalid signature was provided.  Check to ensure the signature is valid according to the instructions in ‘Generating the UserID signature.’

Important: After testing is done, be sure to remove the window.APPCUES_TEST_IDENTITY_VERIFICATION = true statement before deploying your app to production to not display these log messages to your user's JavaScript console.

 

 

Enforcing Identity Verification

Once your testing is complete across all your web and mobile apps that use the Appcues SDK with your Appcues account, you can enable Enforcement Mode to only show Appcues experiences to users with a valid signature. 

Important: Enabling Enforcement Mode for your account affects all of your mobile or web apps in that account. Do not enable Enforcement Mode until you have tested both your mobile and web apps, and ensure that all of your end users are using a version of your mobile or web app that is correctly performing identity verification, as described above.  For mobile apps, after you release a version of your app to the store with identity verification, you'll need to target your Appcues flows to app versions at or above this new version, or require your users update their apps to the latest version to continue usage. You should plan to enable Enforcement Mode in your account only after users in your apps have had a chance to update to this required version.

 

After Enforcement Mode is enabled, the following behavior will occur for all mobile and web apps using the Appcues SDK in your account.  See the previous section for what happens when Enforcement Mode is disabled:

  • If a valid signature is provided to the SDK:
    • Calls to the SDK will work, and Experiences will be shown to users according to the targeting settings of your Appcues Flows and other experiences.
  • If no signature is provided to the SDK OR an invalid signature is provided to the SDK: 
    • Calls to the SDK will fail, and Experiences will not be shown to users.  Ensure the signature you provided to the SDK is valid according to the instructions in ‘Generating the UserID signature.’

To enable Enforcement Mode:

  1. Get an API Key and API_Secret for your Appcues account. If you are an Appcues admin, you can issue an API key and secret yourself from the  API Keys settings page. For more details on using our API to control Identity Verification, see the Public API's SDK Authentication Keys page.
  2. Enable Enforcement Mode with the following curl command.  Replace ACCOUNT_ID with your account ID and your API_KEY and API_SECRET with the values from step 1.
curl <https://api.appcues.com/v2/accounts/ACCOUNT_ID/enforcement_mode/enable> \\
  -u API_KEY:API_SECRET \\
  -d ''
  1. Perform a final check of all your web and mobile apps that use the Appcues SDK with your account to verify Appcues experiences are being shown as expected, according to your experience's targeting settings.   Appcues experiences should show if the steps in Testing Identity Verification were followed.  You are done!

If your Appcues experiences do not appear as expected, no worries, just disable Enforcement Mode.

To disable Enforcement Mode:

Change enable to disable in the command, as shown below.  Replace ACCOUNT_ID with your account ID and your API_KEY and API_SECRET with the values you used when you enabled it as described above.

curl <https://api.appcues.com/v2/accounts/ACCOUNT_ID/enforcement_mode/disable> \\
  -u API_KEY:API_SECRET \\
  -d ''

Important: The API key and API secret generated in your account's dashboard are separate from the SDK authentication key used for generating the user ID signature. The key/secret pair is used for interfacing with our public API, which allows you to enable or disable enforcement mode. The public API also provides endpoints for generating a separate SDK authentication key specific to identity verification. This SDK key is then used in the following code for generating the actual user ID signatures for your users. 

 

 

Code samples to generate a UserID Signature

Each code sample requires the following information to generate a signature valid for 15 minutes.  

  • Your account ID -  can be found in Appcues Studio in the Settings > Account tab
  • The current user's UserID - the same UserID provided to the Appcues Identity call
  • A Secret from the Appcues Public API SDK Authentication Keys.  IMPORTANT: It is essential to keep the secret confidential and not in client-side JavaScript code.  Disclosure of the secret would allow a hacker to impersonate another UserID and see their Appcues Experiences. Note that the SDK authentication key is separate from the API key and secret generated via your Appcues's account's dashboard.

If your product's backend uses a language other than the ones listed below, please contact Appcues support for assistance.

C# 

Using the Jose-jwt library

using System;
using System.Collections.Generic;
using Jose;
using System.Text;

static class AppcuesSignature
{
    public static string CreateToken(string userId, string accountId, byte[] secretKey)
    {
        var payload = new Dictionary<string, object> {
            { "iss", accountId },
            { "sub", userId },
            { "exp", DateTimeOffset.UtcNow.AddMinutes(15).ToUnixTimeSeconds() }
        };
        return Jose.JWT.Encode(payload, secretKey, Jose.JwsAlgorithm.HS256);
    }
}

Elixir 

Using the Joken library

@spec create_token(binary(), binary(), binary()) :: nil | binary()
def create_token(account_id, user_id, sdk_secret)
	expiry = (Timex.now() |> Timex.to_unix()) + (1 * 60 * 60)
	claims = %{
	  "iss" => account_id,
	  "sub" => user_id,
	  "exp" => expiry # The timestamp when this JWT should expire
	}
	signer = Joken.Signer.create("HS256", sdk_secret)
	case Joken.encode_and_sign(claims, signer) do
		{:ok, token, _} -> token
		{:error, _} -> nil
	end
end

Go 

Using the github.com/dgrijalva/jwt-go library

import (
	"github.com/dgrijalva/jwt-go"
	"time"
)

func CreateToken(accountID string, userID string, secretKey []byte) (string, error) {
	// Create the Claims
	claims := jwt.StandardClaims{
		Issuer: accountID,
		Subject: userID,
		ExpiresAt: time.Now().Add(time.Minute * 15).Unix(),
	}

	// Create the token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// Sign and get the complete encoded token as a string
	return token.SignedString(secretKey)
}

Javascript 

Using the Jose library

const jose = require("jose");

function createToken(account_id, user_id, secretKey) {
  const secret = new TextEncoder().encode(secretKey);
  const signature = new jose.SignJWT({})
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuer(account_id)
    .setSubject(user_id)
    .setExpirationTime('1h')
    .sign(secret);
  return signature; // returns a promise
}

Java 

Using the auth0-jwt library

import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.JWT;
import java.util.Date;

class AppcuesSignature {
  public static String CreateToken(String accountId, String userId, byte[] secret) {
    Algorithm algorithm = Algorithm.HMAC256(secret);
    String token = JWT.create()
        .withIssuer(accountId)
        .withSubject(userId)
        .withExpiresAt(new Date(System.currentTimeMillis() + 15 * 60 * 1000))
        .sign(algorithm);
    return token;
  }
}

PHP 

Using the php-jwt library

use \\Firebase\\JWT\\JWT;

function create_token($user_id, $account_id, $secret_key) {
    $payload = array(
        "iss" => $account_id,
        "sub" => $user_id,
        "exp" => time() + 15 * 60
    );

    $jwt = JWT::encode($payload, $secret_key, 'HS256');
    return $jwt;
}

Python 

Using the PyJWT library

import jwt
import datetime

def create_token(account_id, user_id, secret_key):

	# Create the Claims
	claims = {
		'iss': account_id,
		'sub': user_id,
		'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
	}

	# Create the token
	token = jwt.encode(claims, secret_key, algorithm='HS256')

	# Sign and get the complete encoded token as a string
	return token

Ruby 

Using the ruby-jwt library

require 'jwt'

def create_token(user_id, account_id, secret_key)
    claims = {
        iss: account_id,
        sub: user_id,
        exp: Time.now.to_i + 15 * 60
    }

    JWT.encode(claims, secret_key, 'HS256')
end

 

Was this article helpful?

Yes
No
Give feedback about this article

Related Articles

  • Installation Guide for Developers
  • Host Appcues SDK Under Your Own Domain
  • Shared Responsibility Model for Security and Privacy
DON'T TAKE OUR WORD FOR IT

Start building with Appcues for free

Try before you buy
No credit card required
Support included
Start building for freeBook a demo
or take an interactive tour
Appcues logo

Product

In-app messaging
Email
Push notifications
Workflows
Data
How it works
Pricing
What's new

Use cases

Onboarding
Free-trial conversion
Feature adoption
Feedback
Support

Integrations

Why connect
All integrations
All workflows

Company

About
Careers
HIRING
Why Appcues
Teams
Customers

Support

Request a demo
Start free trial
Developer Docs
Help Center
Customer Success
Contact

Resources

Product Adoption Academy
Courses
Workshops
Templates
Examples
Made with Appcues
The Appcues Blog
PLG Collective
Product-led Experience Report
The Product Experience Playbook
The Product-Led Growth Flywheel
© 2025 Appcues. All rights reserved.
SecurityTerms of ServiceWebsite Terms of UsePrivacy PolicyCookie Preferences
Expand