# @deldico/tracking-client

> Deldico Tracking uses fingerprinting technology to identify website visitors and track leads across multiple devices. It is a robust and configurable tracking system that is self-hosted and uses server-side GTM to ensure compliance with GDPR standards. It

Latest version **0.2.15** (published 2023-05-17) · 0 weekly downloads

## Install

```sh
npm install @deldico/tracking-client
pnpm add @deldico/tracking-client
yarn add @deldico/tracking-client
bun add @deldico/tracking-client
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.15 |
| Published | 2023-05-17 |
| First published | 2022-12-06 |
| Weekly downloads | 0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 23.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Alex Klos |
| Maintainers | ekomenu_henk, aklos, deldicobv |

## Links

- npm: https://www.npmjs.com/package/@deldico/tracking-client
- Repository: https://github.com/deldico-workspace/tracking-client
- Homepage: https://github.com/deldico-workspace/tracking-client#readme
- Issues: https://github.com/deldico-workspace/tracking-client/issues
- npm.io page: https://npm.io/package/@deldico/tracking-client

## Recent versions

- 0.2.15 (latest) — 2023-05-17
- 0.2.14 — 2023-05-17
- 0.2.13 — 2023-05-09
- 0.2.12 — 2023-04-28
- 0.2.11 — 2023-01-31
- 0.2.10 — 2023-01-20
- 0.2.9 — 2023-01-09
- 0.2.8 — 2023-01-03
- 0.2.7 — 2022-12-19
- 0.2.6 — 2022-12-12
- 0.2.5 — 2022-12-12
- 0.2.4 — 2022-12-09
- 0.2.3 — 2022-12-09
- 0.2.2 — 2022-12-06

## README

# Deldico Tracking

Deldico Tracking uses fingerprinting technology to identify website visitors and track leads across multiple devices. It is a robust and configurable tracking system that is self-hosted and uses server-side GTM to ensure compliance with GDPR standards. It integrates with Pipedrive and a mailer to keep contacts and leads up-to-date and allows users to register webhooks to pipe events straight to their apps for further processing.

---

## Setup

We have already deployed the necessary servers for the tracking system: a Server-side GTM and a Tracking API. In order to begin using it, you will have to add a JavaScript module to your website that will connect with the GTM dataLayer events, and then deploy the "Server-side tracking" workspace changes to your web GTM container.

### Update your GTM containers

You now have two Google Tag Manager (GTM) containers: a web container, which is the script that is injected into the document's `<head>` section, and a server-side container, which is a replacement for Google's GTM servers. This means that all GTM tracking activities will be taken off of Google servers and put onto your own infrastructure. 

1. Look over and merge all the changes in the "Server-side tracking" workspace. These tags add the Deldico Tracking client and associated events, and they also update existing tags to point to the server-side GTM container. 
2. Update the injected script in your frontend's `<head>` section to point to your GTM server URL (the container ID stays the same). Use the following code: 
```html
  <!-- Google Tag Manager -->
  <script>(function (w, d, s, l, i) {
      w[l] = w[l] || []; w[l].push({
        'gtm.start':
          new Date().getTime(), event: 'gtm.js'
      }); var f = d.getElementsByTagName(s)[0],
        j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
              'https://<Your GTM server>/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
    })(window, document, 'script', 'dataLayer', '<GTM web container ID>');</script>
  <!-- End Google Tag Manager -->
  <!-- Google tag (gtag.js) -->
  <script async src="https://<Your GTM server>/gtag/js?id=<Google Analytics measurement ID>"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag() { dataLayer.push(arguments); }
    gtag('js', new Date());

    gtag('config', '<Google Analytics measurement ID>', {
      transport_url: 'https://<Your GTM server>',
      first_party_collection: true
    });
  </script>
  <!-- End Google tag (gtag.js) -->
```

<!-- [//]: # (Currently, the Universal Analytics and Facebook clients point to our testing environment. You’ll need to modify some tags to point to the correct Universal Analytics account and Facebook Pixel:)

[//]: # ()
[//]: # (1. Set the “Measurement ID” field in the *UA Base* tag in the web container.)

[//]: # (2. Set the "Measurement ID" field in the *UA Proxy* tag in the server container.) -->

After that you may connect analytics to your Facebook Pixel. **Be aware that enabling this and leaving the Pixel on your frontend will create duplicated events.**

3. Set “API Access Token”, “Facebook Pixel ID”, and clear "Test ID" in the *Facebook Proxy* tag in the server container.

Once you set the Facebook Pixel up in GTM, you'll be able to remove it entirely from your frontend (and any related tags in GTM). This is because now your GA4 tag events will be piped directly to your Facebook Pixel through the GTM server.

### Install the JavaScript client

You can install the client directly from NPM:

```bash
npm install @deldico/tracking-client
```

Use the following pattern to import and initialize the client in Angular:

```tsx
import { Component, OnInit } from '@angular/core';
import DeldicoTrackingClient from '@deldico/tracking-client';

const trackingClient = new DeldicoTrackingClient({
  token: '<Your tracking client token>',
  gtmURL: '<Your GTM server URL>',
});

@Component({
  selector: 'app-xyz',
  templateUrl: './xyz.component.html',
  styleUrls: ['./xyz.component.scss'],
})
export class XyzComponent implements OnInit {
  constructor() {}

  ngOnInit(): void {
    // Assuming consent approval. Normally you should set this in a consent banner or form field.
    trackingClient.updateConsent(true, true);

    trackingClient.init().then(() => {
      console.log(trackingClient.fingerprint);
    });
  }
}
```

The client will fetch the user's device fingerprint and tracking ID on `init()` and set the appropriate *dataLayer* variables. **This should be done once on page load.** Now you’ll be able to use the special tracking *dataLayer* events, which are described in detail in the [Usage](#usage) section of this document.

### Setup webhooks in the API (optional)

The tracking API can push raw event data to your own apps, and all you need to do is register an endpoint through a POST request like below:

```bash
curl --location --request POST 'https://<API URL>/webhook' \
--header 'X-Api-Key: <API key>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "url": "<Your webhook endpoint>"
}'
```

The API will retry sending events to each webhook until it gets a 200 status response.

---

## Usage

### Consent
Before sending any events you'll need to configure consent for page visitors. It doesn't matter how you implement this, whether it's a banner or a form field, but tracking will be blocked unless a user gives approval.

You can set the consents for a user with the following method:

```tsx
  trackingClient.updateConsent(true, true); // Enable both analytics and ads
  trackingClient.updateConsent(false, false); // Disable tracking
  trackingClient.updateConsent(true, false); // Only enable analytics
  
  // Now init the client to get fingerprint and tracking ID
  await trackingClient.init();
  
  // You can also update consent afterwards to block tracking on request
```

### GTM dataLayer

The tracking system is connected to your website through GTM *dataLayer* events, and requires specific event data to properly track devices and associate them with leads.

Deldico Tracking specific *dataLayer* fields are: `fingerprint`, `trackingId`, `event`, `userData`, and `metaData`.

The JavaScript client will automatically set `fingerprint` and `trackingId` on initialization if they are available, but you can always set them yourself later.

#### Fields

- `fingerprint`: The unique fingerprint ID of the visitor's device. This is the first layer of lead tracking, because a visitor may have a fingerprint but no lead yet. Visitors without leads are still tracked with a generated `trackingId`.

- `trackingId`: The unique visitor tracking ID. A single `trackingId` may be associated with multiple fingerprints through the use of the `tid` UTM link parameter (see [UTM links](#utm-links) section).

- `event`: Basic *dataLayer* parameter. Deldico Tracking connected events are described in the [Events](#events) subsection.

- `userData`: User-submitted form field values. Deldico Tracking is only concerned with `name`, `email`, and `phone` for creating new leads in Pipedrive. All other form fields are passed through (ignored by the API but pushed to webhooks).

  Example value:
  ```javascript
  userData: { name: "John Doe", email: "john@doe.com", phone: "12345678" }
  ```
  
- `metaData`: Additional information about the event required by the API in order to correctly generate leads and activities. Currently has three possible parameters: `context`, `step` (for step completion tracking), and `createActivity` (to create an activity for the event - if applicable - in Pipedrive).

  Example value:
  ```javascript
  metaData: { context: "signup" }
  ```
  
#### Events
You'll need to trigger the following *dataLayer* events in order to create leads and track visitors. The most important event is `new_lead`, which generates a lead for a visitor in Pipedrive.

- `page_visit`: Tracks page navigations for visitors and leads. 
  ```javascript
  window.dataLayer.push({
    event: "page_visit",
    // no other data needed,
    // path and page title are automatically extracted
    // UTM parameters are also automatically extracted
    metaData: {
      // leave this out or set to false to avoid
      // spamming information-less lead activities
      // like homepage visits
      createActivity: true
    }
  });
  ```
- `new_lead`: Creates a lead in Pipedrive if there's no other lead associated with the current visitor. If the `metaData.context` value is "contact" the lead will be considered warm, and if it's set to "signup" then it will be hot.

  ```javascript
  window.dataLayer.push({
    event: "new_lead",
    userData: {
      // partial lead data is OK, email is required
      name: "John Doe",
      email: "john@doe.com",
      phone: "12345678"
    },
    metaData: {
      context: "contact", // may be "contact" or "signup"
    },
  });
  ```
- `step_completed`: Updates leads with partial lead data in the case of split forms (sign up), where email may be present in one step but name in another.
  
  ```javascript
  window.dataLayer.push({
    event: "step_completed",
    userData: {
      // partial lead data is OK
      name: "John Doe"
    },
    metaData: {
      context: "signup_form", // any identifier string
      step: stepNumber, // integer
    },
  });
  ```
- `conversion`: Used for keeping track of conversions in the API for reporting.
  
  ```javascript
  window.dataLayer.push({
    event: "conversion",
    metaData: {
      context: "partial", // may be "partial" or "full"
    },
  });
  ```
### Tracking links
In order to associate new fingerprints with existing tracking IDs and leads, visitors need to navigate to your website with tracked links.

Tracking IDs are associated with contacts in both Pipedrive and your mailer, so all you need to do is generate a link with the tracking ID added to the URL in the `tid` parameter.

Example:
```
https://yoursite.com?tid=123
```
Anyone who clicks the above link will have their device fingerprint permanently associated with tracking ID 123 and their lead, if any.

### Tracking API

The API exposes some HTTP endpoints to help you manage webhooks and manually send tracking events, if necessary.

Making requests requires authorization using the `X-Api-Key` header. If you fail to authenticate you will receive a `403 Forbidden` response.

- GET `/webhooks`: Returns a list of existing webhook configurations.

  ```bash
  curl --location --request GET 'http://localhost:3030/webhooks' \
  --header 'X-Api-Key: 1234abcd'

  EXAMPLE RESPONSE (json):
  {
    "webhooks": [
      {
        "id": 1,
        "url": "https://yoursite.com/yourwebhook",
        "created_at": "2022-11-03 15:57:50",
        "updated_at": "2022-11-03 15:57:50"
      }
    ],
    "ok": true
  } - 200
  ```
- POST `/webhooks`: Creates a webhook.

  ```bash
  curl --location --request POST 'http://localhost:3030/webhooks' \
  --header 'X-Api-Key: 1234abcd' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "url": "https://yoursite.com/yourwebhook"
  }'

  EXAMPLE RESPONSE:
  OK - 200
  ```
- DEL `/webhooks`: Deletes a webhook.

  ```bash
  curl --location --request DELETE 'http://localhost:3030/webhooks' \
  --header 'X-Api-Key: 1234abcd' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "url": "https://yoursite.com/yourwebhook"
  }'

  EXAMPLE RESPONSE:
  OK - 200
  ```
- POST `/event`: Handles an event. Normally called by GTM with appropriate tags, follows the exact same structure as dataLayer pushes.
  ```bash
  curl --location --request POST 'http://localhost:3030/event' \
  --header 'X-Api-Key: 1234abcd' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "fingerprint": "asd31dffgh0jz", 
      "trackingId": "123",
      "path": "/",
      "pageTitle": "",
      "utmCampaign": "",
      "utmSource": "",
      "utmMedium": "",
      "utmTerm": "",
      "utmContent": "",
      "event": "page_visit",
      "timestamp": "2022-11-03T00:00:00",
      "userData": null,
      "metaData": null
  }'
  
  EXAMPLE RESPONSE:
  OK - 200
  ```
---

## Pipedrive integration
The tracking API will create leads on `new_lead` for visitors without any existing leads, and will update contact info on `step_completed` events.

Leads are considered warm if the event's `metaData.context` value is "contact", and hot if the value is "signup". The API assigns labels for the lead according to type.

The API also creates activities for existing lead events to enable behavioural filtering.

---

## Mailer integration
Whenever an event comes in where `userData.email` is set, the API checks if such a contact/customer exists in your mailer and sets their "Tracking ID" field accordingly.

---

## Contact
If anything in this documentation is unclear, or you have any other questions, please contact us at: `joren@deldico.be`

---
_Source: https://npm.io/package/@deldico/tracking-client · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
