FingerprintJS Snowplow Integration

Why use Snowplow with FingerprintJS Pro

FingerprintJS Pro can augment the context surrounding Snowplow events by adding information to the event from FingerprintJS, both from the Javascript call and the optional webhook.

Augmenting Snowplow data with an additional unique identifier can be especially useful in fraud detection such as account sharing, paywall avoidance, and more (see identity graph with Snowplow+Neo4j).

Integration Options

Option 1: Using FingerprintJS visitorId in Snowplow user_id

The most straightforward integration is to pass the FingerprintJS Pro visitorId to Snowplow in the user_id field. Please note that using this method, we do not capture information like confidence score and requestId in Snowplow.

Snowplow JS Tracker V3

<head>
  <script>
    var initSnowplow = function (fpjsVisitorId) {
      // Loading tracker with the Snowplow tag
      (function (p, l, o, w, i, n, g) {
        if (!p[i]) {
          p.GlobalSnowplowNamespace = p.GlobalSnowplowNamespace || [];
          p.GlobalSnowplowNamespace.push(i);
          p[i] = function () {
            (p[i].q = p[i].q || []).push(arguments);
          };
          p[i].q = p[i].q || [];
          n = l.createElement(o);
          g = l.getElementsByTagName(o)[0];
          n.async = 1;
          n.src = w;
          g.parentNode.insertBefore(n, g);
        }
      })(
        window,
        document,
        "script",
        "//cdn.jsdelivr.net/npm/@snowplow/javascript-tracker@3.4.0/dist/sp.js",
        "snowplow"
      );

      // Tracker Initialization
      snowplow("newTracker", "sp", "sp.demos.snowcatcloud.com", {
        appId: "my-app-id",
        discoverRootDomain: true,
        cookieSameSite: "Lax",
      });

      // Set the user ID
      snowplow("setUserId", fpjsVisitorId);
      snowplow("trackPageView");
    };

    // Now, the FingerprintJS Pro configuration
    import("https://fpcdn.io/v3/NjcpQCRz3HGRrT43cQLv")
      .then((FingerprintJS) => FingerprintJS.load())
      .then((fp) => fp.get())
      .then((result) => initSnowplow(result.visitorId))
      .catch((error) => {
        // use your favorite error reporting tool
        reportError(err);
      })
      .finally(function () {
        // optional
        // do some guaranteed post-processing here
      });
  </script>
</head>

Option 2: Use FingerprintJS Snowplow Schema (Preferred)

Snowplow uses schemas to provide additional metadata to each event. SnowcatCloud created two Snowplow schemas, one for the visitor id and the other for webhooks. To use FingerprintJS Pro with Snowplow using this method (and webhooks), please download the FingerprintJS schemas and install them in your Snowplow Pipeline.

<head>
  <script>
    var initSnowplow = function (fpjs) {
      (function (p, l, o, w, i, n, g) {
        if (!p[i]) {
          p.GlobalSnowplowNamespace = p.GlobalSnowplowNamespace || [];
          p.GlobalSnowplowNamespace.push(i);
          p[i] = function () {
            (p[i].q = p[i].q || []).push(arguments);
          };
          p[i].q = p[i].q || [];
          n = l.createElement(o);
          g = l.getElementsByTagName(o)[0];
          n.async = 1;
          n.src = w;
          g.parentNode.insertBefore(n, g);
        }
      })(
        window,
        document,
        "script",
        "//cdn.jsdelivr.net/npm/@snowplow/javascript-tracker@3.4.0/dist/sp.js",
        "snowplow"
      );

      // Tracker Initialization
      snowplow("newTracker", "sp", "sp.demos.snowcatcloud.com", {
        appId: "my-app-id",
        discoverRootDomain: true,
        cookieSameSite: "Lax",
      });

      // Set the user ID
      snowplow("setUserId", fpjs.visitorId);
      snowplow("trackSelfDescribingEvent", {
        event: {
          schema: "iglu:com.fingerprintjs/fingerprint/jsonschema/1-0-0",
          data: {
            visitorId: fpjs.visitorId,
            visitorFound: fpjs.visitorFound,
            requestId: fpjs.requestId,
            confidence: {
              score: fpjs.confidence.score,
            },
          },
        },
      });

      console.log("====" + fpjs.visitorId + "====");
    };

    // Now, the FingerprintJS Pro configuration
    import("https://fpcdn.io/v3/NjcpQCRz3HGRrT43cQLv")
      .then((FingerprintJS) => FingerprintJS.load())
      .then((fp) => fp.get())
      .then((result) => initSnowplow(result))
      .catch((error) => {
        // use your favorite error reporting tool
        reportError(err);
      })
      .finally(function () {
        // optional
        // do some guaranteed post-processing here
      });
  </script>
</head>

Use the Snowplow Collector to receive FingerprintJS webhooks

Snowplow collectors can also receive and process FingerprintJS webhook events (requires instalation of FingerprintJS schemas in your Snowplow pipeline).

The FingerprintJS Pro webhook events will be processed and stored with your Snowplow event data, which you can easily query by looking for app_id=fp-webhook.

Add a webhook with the following URL (Copy paste exactly, only change the hostname to your Snowplow collector).

https://collector/com.snowplowanalytics.iglu/v1?aid=fp-webhook&p=app&schema=iglu%3Acom.fingerprintjs%2Fwebhook%2Fjsonschema%2F1-0-0