Amplitude is a decent product analytics tool, but there is no compromise when it comes to identification. User IDs are fixed forever and all data is immutable once it lands in the platform – names and email addresses are not an option.

Knowing the name of a user can unlock insight by giving context to usage patterns, especially in early-stage projects with a handful of users who are working at the same company.

I’m not aware of a way to make annotations directly in Amplitude; all data has to arrive over their API. Anyway, doing this would expose personally identifiable information (PII) to a third party.

To solve this, I worked with Gemini to develop a Tampermonkey userscript that finds and replaces the user ID with text of your choosing. For the uninitiated, Tampermonkey is a browser extension that lets you change how websites function.

To do the same simply:

  1. Install Tampermonkey
  2. Copy the code below:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// ==UserScript==
// @name         Amplitude named user profiles
// @namespace    https://jamesgreenblue.com/
// @version      0.1
// @description  Finds and replaces user profile names in Amplitude
// @author       James Greenhalgh, with significant contributions from an AI Assistant (Gemini)
// @match        *://app.amplitude.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    var replaceArry = [
        [/user_cva3bbm9i077dn133b2h/gi, 'james.g'],
        [/user_cva4gge9i077spp33b3h/gi, 'joe.b'],
        [/user_cva64re9i078i0h33b41/gi, 'jane.d'],
        // Add more replacements here
    ];
    var numTerms = replaceArry.length;

    function replaceTextInNode(node) {
        if (node.nodeType === Node.TEXT_NODE) {
            let oldTxt = node.nodeValue;
            let newTxt = oldTxt;
            for (let i = 0; i < numTerms; i++) {
                newTxt = newTxt.replace(replaceArry[i][0], replaceArry[i][1]);
            }
            if (newTxt !== oldTxt) {
                node.nodeValue = newTxt;
            }
        } else if (node.nodeType === Node.ELEMENT_NODE && node.childNodes) {
            node.childNodes.forEach(replaceTextInNode);
        }
    }

    // Initial scan of the document
    replaceTextInNode(document.body);

    // Observe for future changes
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE) {
                    replaceTextInNode(node);
                }
            });
            // For text content changes within existing nodes
            if (mutation.type === 'characterData' && mutation.target.parentNode) {
                replaceTextInNode(mutation.target.parentNode);
            }
        });
    });

    observer.observe(document.body, { subtree: true, childList: true, characterData: true });
})();
  1. Edit the rows in replaceArry to match the ID you see in Amplitude with the name you would like to see instead. Add more replacements if necessary. I suggest avoiding full names to minimise PII on your local machine.
  2. Save and enable the script in Tampermonkey
  3. Gain insight

This userscript is also published on GitHub if you would like to fork your own version or report issues.