> For the complete documentation index, see [llms.txt](https://stitchd.gitbook.io/solid-web-tracking/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stitchd.gitbook.io/solid-web-tracking/solid-and-digital-analytics/developer-guide.md).

# Developer guide

If you have a website of your own and would like to experiment with web tracking using Solid Pods, this guide might help to get you started!

In this guide, we'll walk you through the development process of a small news website, where news articles are suggested based on previous pageviews that are stored in the visitor's Solid Pod.

Upon visiting the website, you'll be prompted to authenticate with your own Solid Pod. For this demo, there are two providers to choose from: [solidcommunity](https://solidcommunity.net/) or [inrupt](https://signup.pod.inrupt.com/). Both providers offer you to create your own Solid Pod for free to experiment with. Once you've authenticated your Solid Pod and have authorized the demo website to store/retrieve data from your Pod, pageview data will be stored in your Pod for each page visit. The 'personalized news' page will read this data from your Pod, and will suggest a category of news articles based on your viewing history.

This demo is a static website hosted on Netlify, and we're not storing any data elsewhere.&#x20;

{% hint style="info" %}
**Visit** [**demo website**](https://solid-demo.netlify.app)
{% endhint %}

*Note: the demo website is a static mockup website based on the VRT NWS website. This is solely for demo purposes, we are not in any way affiliated to the brand and we are not responsible for the content of the website. The code samples we are sharing below are not from VRT NWS, but are 'plugins' that we've added to this demo website and are free for you to use in your own projects.*

## Prerequisites

The demo uses Inrupt’s [JavaScript Client Libraries](https://github.com/inrupt/solid-client-js) to connect and manage data stored in a Solid Pod, and uses GDDL framework for handling the [Event Driven Web Analytics Tracking](https://bitbucket.org/xploregroup/xploregroup-webanalytics-demo). &#x20;

#### Your own Pod and WebID <a href="#prerequisites" id="prerequisites"></a>

Before you start, make sure you have [your own Pod and WebID](https://solidproject.org/developers/tutorials/getting-started).

## Getting started

Note: we assume you have your own website and would like to learn how to implement web tracking with Solid Pods, so we're gonna skip over the part on how to build a website.

There are a few steps that need to be done:

1. [Add web tracking](#web-tracking). In this demo, we're using the GDDL framework for handling the event driven web tracking.
2. [Solid Pod authentication](#pod-authentication). Ask the visitor to authenticate with his Solid Pod.
3. [Write data to pod](#write-web-tracking-data-to-pod). Tracking events generated by the GDDL need to be stored in the Solid Pod.
4. [Read data from pod](#read-web-tracking-data-from-pod). And then use this data to personalize content.

### Web tracking

In this demo, we're using the GDDL framework for handling the event driven web tracking. However, you are free to use your own implementation for web tracking.

#### Install the GDDL Analytics tracker library

Add the following dependencies to your `package.json`:

```json
"dependencies": {
    "mediator-js": "^0.9.9",
    "analyticstracker": "git+https://bitbucket.org/xploregroup/xploregroup-webanalytics-analyticstracker"
    "analytics-transQA": "git+https://bitbucket.org/xploregroup/xploregroup-webanalytics-analytics-transqa"
}
```

Note: the analytics-transQA is an optional translator for passing events to the chrome devtool for QA. Use this translator if you're using the [Chrome Extension for inspecting GDDL events](https://chrome.google.com/webstore/detail/gddl-inspector/glemmkkipabbechhnlmfiddhebdmandc?hl=en-GB).

Then, run `npm i` to install dependencies.

```bash
$ npm i
```

#### Implement the Analytics tracker

Next, we're using the Analytics tracker on our pages to track a `page-impresssion` (pageview). Take a look at the code sample below (it uses the NuxtJS `mounted()` lifecycle hook).

```javascript
mounted() {
    var analyticstracker = require("analyticstracker")
    analyticstracker().trackEvent({
        event: "page-impression", 
        info: {
            title: "Example Page Title, 
            category: "Sports",
            url: document.URL
        }
    })
}
```

In this code sample, we're sending a `page-impresssion` event and we're setting 3 parameters in the info object: title, category and url.

![If you are using the GDDL Chrome Extension, you can verify that your events are firing when the component is mounted.](https://1552011828-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FViJhQICYXkQNp3cot99R%2Fuploads%2FiFax28cryQa9wuuHERQm%2FScreenshot%202022-02-01%20at%2011.24.35.png?alt=media\&token=5be4fd61-bf00-4cb4-9a1e-d63be05dd294)

Great, now we're tracking page-impression events!&#x20;

#### Additional resources

If you would like to learn more about the GDDL Framework and how to implement it, you might find more information here:

* [The GDDL gitbook](https://stitchd.gitbook.io/gddl/)
* [GDDL Analyticstracker repository](https://bitbucket.org/xploregroup/xploregroup-webanalytics-analyticstracker)

### Pod authentication

For the next part, we need to establish authentication with a Solid Pod. We're showing a popup asking the visitor to choose a provider to authenticate.

#### Install the Inrupt Client Libraries <a href="#id-2-install-the-inrupt-client-libraries" id="id-2-install-the-inrupt-client-libraries"></a>

Use `npm` to install Inrupt client libraries:

```bash
$ npm install @inrupt/solid-client @inrupt/solid-client-authn-browser @inrupt/vocab-common-rdf
```

#### Add the popup component

Call the `solid-client-authn-browser` library’s `login()` function to start the process. Below is the example code for the popup component:

```html
<template>
    <div class="modal-overlay" @click="$nuxt.$emit('close-modal')">
        <div class="modal" @click.stop>
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Get the best experience!</h5>
                    <button
                        type="button"
                        class="btn-close"
                        aria-label="Close"
                        @click="$nuxt.$emit('close-modal')"
                    >
                        Close
                    </button>
                </div>
                <div class="modal-body">
                    <p class="text">
                        To provide the best experiences, we advice you to authenticate with your Solid pod. That way, you remain in control over the data that you generate by visiting our platform. If you allow us to read this data, we can improve your user experience and provide personalised recommendations.<br>
                        <br>
                        Choose your Solid pod provider below:
                    </p>
                    <br />
                    <a
                        @click="loginWithPod('https://solidcommunity.net')"
                        href="#"
                    >
                        Solidcommunity
                    </a>
                    <a
                        @click="loginWithPod('https://inrupt.net')"
                        href="#"
                    >
                        Inrupt
                    </a>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { login } from "@inrupt/solid-client-authn-browser";

export default {
    name: "AuthModal",
    methods: {
        loginWithPod: function (oidcIssuer) {
            login({
                oidcIssuer: oidcIssuer,
                redirectUrl: window.location.href,
                clientName: "solid-demo",
            });
        },
    },
};
</script>
```

For more information on the login function and parameters, visit the [the Inrupt docs](https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/authenticate-browser/).

**Session Restore upon Browser Refresh**

For security reasons, `solid-client-authn-browser` does not store access tokens in the localStorage or any other place that persists across page refresh.

This means that upon page refresh/reload, the access token is lost, and your web application will be logged out. We'll use `solid-client-authn-browser`’s `handleIncomingRedirect()` function to log the application back in without user interaction. To automatically log the user back in after a page refresh, in your application, call `handleIncomingRedirect()` with `restorePreviousSession` set `true`.

To route the user back to the refreshed page instead of to the redirectURL, you can make use of the `sessionRestore` event and the associated callback `onSessionRestore()` function. With session restore enabled and the user returns back to the application after the silent authentication, the `sessionRestore` event is fired.

Use the code example below to handle session restore upon browser refresh:

```javascript
onSessionRestore((url) => {
    this.$router.push(url)
});

await handleIncomingRedirect({
    restorePreviousSession: true
}).then((info) => {
    console.log(`Logged in with WebID [${info.webId}]`)
    if(!info.webId) {
        // Show Auth modal
        setTimeout(() => {this.showModal = true}, 2000);
    }
});
```

To read more about session restore upon browser refresh, check out [the Inrupt docs](https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/restore-session-browser-refresh/).

### Write web tracking data to Pod

*We've written a solidService module containing a set of functions to help you get started reading/writing web tracking data to the Solid Pod. The code is publicly available, feel free to use and adapt it to your needs.* [*Documentation can be found in this repository*](https://bitbucket.org/xploregroup/xploregroup-webanalytics-solidservice)*.*

In order to write web tracking data to the Pod, we need to extend the Analytics tracker created in step 1. In order to do this, we'll create our own custom translator for the GDDL Analytics tracker.

```javascript
import Vue from "vue";
import analyticstracker from "analyticstracker";
import solidService from "~/pages/solid/solidService";

var analyticsTransSolid = function analyticsTransSolid() {
    if (!(this instanceof analyticsTransSolid)) {
        return new analyticsTransSolid();
    }

    this.tracker = analyticstracker();
    this._version = "1.0.1";
    this._subscribe();
};

analyticsTransSolid.prototype.getInstance = function () {
    if (!_instance) {
        _instance = analyticsTransSolid();
    }
    return _instance;
};

analyticsTransSolid.prototype._subscribe = function () {
    try {
        this.tracker.trackingSubscribe("QA", function (event, data) {

            try {
                if (solidService.isLoggedIn()) {
                    solidService.writeWebTrackingDataToPod(data);
                }
            } catch (err) {
                console.log(
                    "Solid Tracker ERROR: " + err.name + ": " + err.message
                );
            }
        });
    } catch (e) {
        console.log(
            "Solid Tracker subscribing ERROR: " + e.name + ": " + e.message
        );
    }
};

analyticsTransSolid.prototype.resetEventLog = function () {
    try {
        if (
            typeof w != "undefined" &&
            w != null &&
            typeof w.sessionStorage !== "undefined"
        ) {
            w.sessionStorage.setItem("eventLog", "");
        }
    } catch (e) {
        console.log("Solid Tracker ERROR: " + e.name + ": " + e.message);
    }
};

analyticsTransSolid.prototype.setAvailableEvents = function (eventlist) {};

Vue.use(analyticsTransSolid);
```

This translator script will subscribe to the Analytics tracker, and calls `writeWebTrackingDataToPod(data)` from the solidService module to transform and store the data in the Pod when the user is authenticated.

More information about the `writeWebTrackingDataToPod(data)` function can be found in the [solidService documentation](https://bitbucket.org/xploregroup/xploregroup-webanalytics-solidservice).

### Read web tracking data from Pod

*We've written a solidService module containing a set of functions to help you get started reading/writing web tracking data to the Solid Pod. The code is publicly available, feel free to use and adapt it to your needs.* [*Documentation can be found in this repository*](https://bitbucket.org/xploregroup/xploregroup-webanalytics-solidservice)*.*

On the personalized news page, we're reading data from the Solid pod to suggest a category of news articles based on your viewing history.

The example code below uses the `readWebTrackingDataFromPod()` function from the solidService module. This function returns a JSON array containing all the page-impression events that are stored on the Solid Pod. We're looping over the array and counting the categories to determine a winner (category with most occurrences).

```javascript
async getCategoryFromPod() {

    return await solidService
        .readWebTrackingDataFromPod()
        .then((response) => {
            if(!response || response.length == 0) {
                throw new Error("To be able to recommend you other articles, we require some browsing history. Browse some content first.");
            }
            // determine the winning category
            else {
                var maxCount = 0, resultArray = [], winner = '';
                response.forEach((element, index) => {
                    if(resultArray[element.category]) {
                        resultArray[element.category]++;
                    }
                    else {
                        resultArray[element.category] = 1;
                    }
                    
                    if(resultArray[element.category] > maxCount) {
                        maxCount = resultArray[element.category];
                        winner = element.category;
                    }
                })
                return winner;
            }
                    
        })
}
```

More information about the `readWebTrackingDataFromPod()` function can be found in the [solidService documentation](https://bitbucket.org/xploregroup/xploregroup-webanalytics-solidservice).

<br>
