🔥 Introducing PayTrackr - an easy way to keep track of all your micropayments!

Robert - May 25 '20 - - Dev Community

Currently, web monetization providers doesn't have a feature to show subscribers a breakdown of where their money went. This is due to the fact that providers don't track or know where their subscribers go, in the name of privacy. It's a tough balance between privacy and data.

What I built

I built a secure browser extension that lets you track and manage your micropayments to Web-Monetized websites, having a web monetization provider membership (i.e. Coil).

PayTrackr stores all of your micropayments locally on your device. Only you have access to your data. Not even the web monetization providers can read your data.

PayTrackr is 100% open source software. The source code for PayTrackr is hosted on GitHub and everyone is free to review, audit, and contribute to the PayTrackr codebase.

PayTrackr is currently in beta testing so there will be changes anytime soon.

Submission Category:

Creative Catalyst / Exciting Experiments

Download links:

Demo

Dashboard - Aggregated breakdown on how much went to each site in total

Dashboard

Recent Payments - History of micropayments to websites with web monetization

Recent Payments

Enable/Disable Monetization

Enable/Disable Monetization

Payment Counter - Floating counter of how much went to each active tab in total

Payment Counter

Payment Alerts - Get notifications when a certain amount is reached

Payment Alerts

Export History - Export micropayments history to csv/xlsx

Export History

Charity - Turn on to split payments between the Web-Monetized website and the PayTrackr developer. (Switched off by default)

Charity

You can find updated demos in the comment section.

Benefits

Installing PayTrackr side by side with Coil or any other provider soon gives us benefits like:

  • We become financially aware and improve money management
  • We can allocate money to each site equally if we want to
  • We can monitor payment streams in real-time

Link to Code

The code and installation instructions are hosted on GitHub.

GitHub logo wobsoriano / paytrackr

Track and manage your micropayments into one place 🎉

PayTrackr

PayTrackr is the easiest and safest way to track and manage your micropayments to Web-Monetized websites, having a web monetization provider membership (i.e. Coil).

Download links

Features

  • Dashboard - Aggregated breakdown on how much went to each site in total
  • Recent Payments - History of micropayments to websites with web monetization
  • Enable/Disable Monetization
  • Payment Counter - Floating counter of how much went to each active tab in total
  • Payment Alerts - Get notifications when a certain amount is reached
  • Export History - Export micropayments history to csv/xlsx

Usage

$ npm install
$ npm run build:dev
Enter fullscreen mode Exit fullscreen mode

Running locally

Google Chrome

  1. Open Chrome and type chrome://extensions in the search bar. Turn the switch Developer mode on.
  2. Look for the button Load unpacked at the top-left and select the dist folder found in the root's path of our extension when we run npm run build:dev.

How I built it

Tech Stack

  • Vue - JavaScript Framework
  • Vuetify - Material Design component framework for Vue
  • Chart.js - Flexible JS Charts
  • SheetJS - Used to export data to csv/xlsx
  • CoinGecko API - XRP/USD conversion

Browser APIs used:

  • Storage - used to store payment streams locally
  • Notifications - used to notify user when a certain amount declared in the Alerts tab is reached.
  • Tabs - used to send updates when toggling monetization status, etc.

My discovery along the way

If you're not familiar with browser extension development, I advise you to take a look at Chrome's Getting Started Tutorial or Mozilla's.

The first thing I did is to figure out how can I listen to monetization events in each page I visit. This is the most important part in building this extension because we can't really do much without having access to streamed payments.

Luckily, we can use a content script since it has access to all pages we visit in the browser.

But no. We can't use a content script.

document.monetization is an expando property on a standard DOM document interface, this property is not a part of DOM, it's essentially a JavaScript object so it's not accessible directly from a content script which runs in an isolated world - all JavaScript objects/variables/expandos are isolated so the page scripts can't see the JS objects of content scripts and vice versa.

In Chrome, to overcome this, we need to run a code in page context and then use standard DOM messaging via CustomEvent to coordinate the code in page context and the content script.

First we create a file called inject.js.

if (document.monetization) {
  document.monetization.addEventListener("monetizationprogress", (e) => {
    document.dispatchEvent(
      new CustomEvent("paytrackr_monetizationprogress", {
        detail: e.detail,
      })
    );
  });
}
Enter fullscreen mode Exit fullscreen mode

Then create our content script file called content.js and add this code.

let s = document.createElement('script');
s.src = chrome.runtime.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);
Enter fullscreen mode Exit fullscreen mode

Basically we injected a code and it is now running in page context. Then to communicate between the injected page script and the content script, we can add this to our content.js file.

document.addEventListener('paytrackr_monetizationprogress', (e) => {
  console.log('received', e.detail);
});
Enter fullscreen mode Exit fullscreen mode

With that, we can now listen to monetization progress events for all Web-Monetized content we visit which holds mostly the data we need to build our extension.

To do this in Firefox, we can use wrappedJSObject.

This is now what our manifest.json looks like.

{
  "name": "PayTrackr",
  "description": "Track and manage your micropayments into one place 🎉",
  "version": "0.0.1",
  "manifest_version": 2,
  "icons": {
    "48": "icons/icon_48.png",
    "128": "icons/icon_128.png"
  },
  "browser_action": {
    "default_title": "paytrackr",
    "default_popup": "popup/popup.html"
  },
  "background": {
    "scripts": ["background.js"]
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ],
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
  "web_accessible_resources": ["inject.js"],
  "permissions": ["storage", "unlimitedStorage", "notifications"]
}
Enter fullscreen mode Exit fullscreen mode

To listen to events from iframes, we can set all_frames to true in our content script.

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "all_frames": true,
      "js": ["content.js"]
    }
  ],
Enter fullscreen mode Exit fullscreen mode

Note: We need to add inject.js in the web_accessible_resources for Chrome to not refuse to load our script and display the following error in the console:

Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
Enter fullscreen mode Exit fullscreen mode

Charity implementation

So you may be wondering how I did the split payments when the charity option is enabled.

I created a function that creates an iframe element and appends it to the body of the document.

 const attachIframe = () => {
    const iframe = document.createElement("iframe");
    iframe.src = "https://paytrackr-developer.now.sh/";
    iframe.style = "width:0;height:0;border:0;border:none;";
    iframe.allow = "monetization";
    document.body.appendChild(iframe);
  };
Enter fullscreen mode Exit fullscreen mode

The area of focus in the code above is the iframe.src and iframe.allow. The value of the iframe.src is basically an empty Web-Monetized page I deployed in vercel and to monetize the iframe, we add monetization to the iframe's allow attribute.

Walls I bumped into

Originally, I was going to use chrome.storage.sync instead of chrome.storage.local to store micropayments and have synchronization between devices but the sync property have limits.

Because of that, I refactored my code to use chrome.storage.local and good thing about this is that we can store unlimited amount of data ... but without sync.

Future plans

  • Sync data between devices
  • ✅ Start/Stop/Pause payment streams?
  • Send history to email

Thank you Dev and Grant For The Web for conducting this awesome hackathon and giving all the participants an opportunity to contribute.

Please let me know if you have any questions.

Cover photo by Josh Appel on Unsplash

. . . . . . . . . . . . . . . . . . .
Terabox Video Player