Skip to main content
Ask your AI

Fingerprint to BigQuery

This server flow turns raw request signals into a privacy-friendly identifier before events reach BigQuery. The Express source extracts the client IP and user agent, the fingerprint transformer hashes them into user.hash, and the GCP destination writes the events to a table. The ingest keys must be ip and userAgent, the fingerprint's default inputs (ingest.ip, ingest.userAgent); the transformer anonymizes the IP, reduces the user agent and keys the hash with a secret salt.

{
  "version": 4,
  "flows": {
    "default": {
      "config": {
        "platform": "server",
        "bundle": {
          "packages": {
            "@walkeros/collector": { "version": "^4" },
            "@walkeros/server-source-express": { "version": "^4" },
            "@walkeros/server-transformer-fingerprint": { "version": "^4" },
            "@walkeros/server-destination-gcp": { "version": "^4" }
          }
        }
      },
      "sources": {
        "express": {
          "package": "@walkeros/server-source-express",
          "next": "fingerprint",
          "config": {
            "ingest": {
              "map": {
                "ip": { "key": "ip" },
                "userAgent": { "key": "headers.user-agent" }
              }
            }
          }
        }
      },
      "transformers": {
        "fingerprint": {
          "package": "@walkeros/server-transformer-fingerprint",
          "config": {
            "settings": { "salt": "$env.FINGERPRINT_SALT", "length": 16 }
          }
        }
      },
      "destinations": {
        "bigquery": {
          "package": "@walkeros/server-destination-gcp",
          "import": "destinationBigQuery",
          "config": {
            "settings": {
              "projectId": "my-analytics-project",
              "datasetId": "events",
              "tableId": "raw_events"
            }
          }
        }
      },
      "collector": { "run": true }
    }
  }
}

Run it​

Save the config as flow.json and run the fingerprint transformer of the built flow on an event. --ingest passes the request context the Express source extracts, the client IP and user agent, and the salt comes from the environment. Nothing is written to BigQuery:

FINGERPRINT_SALT=change-me npx walkeros push flow.json -e '{"name":"page view"}' --simulate transformer.fingerprint \
  --ingest '{"ip":"203.0.113.7","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}'

You should see, besides an Output: line naming the built bundle before each Simulating line (your hash differs, as it depends on the salt and the day):

Simulating transformer: fingerprint
success: true
  transformer.fingerprint
    event {"name":"page view","user":{"hash":"8015a6ca3b754e5e"}}
  Duration: 58621ms

What you get​

In production every event lands as one row in your table, using the standard walkerOS schema (name, entity, action, timestamp, user, and more). The destination receives an appendRows call, and the user column carries the hash in place of a raw IP or user agent (from the package's examples):

['appendRows', [{
  "name": "page view",
  "entity": "page",
  "action": "view",
  "user": "{\"hash\":\"158f99cc06e33fd6\"}",
  ...
}]]

The hash rotates daily by default, so a visitor is not tracked across days. Use a long random salt per deployment in production.

Next steps​

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)