DEV Community

Cover image for 🔥 Introducing PayTrackr - an easy way to keep track of all your micropayments!
Robert
Robert

Posted on • Updated on

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

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

Top comments (13)

Collapse
 
wobsoriano profile image
Robert • Edited

v0.2.0

  • Removed real-time dashboard to improve performance
  • Add reload button to get latest data instead
  • Moved theme switcher and currency converter in options dialog

Demo

Collapse
 
wobsoriano profile image
Robert

Hello everyone!

Good news! v0.2.2 has tons of interesting updates:

  • Payment counter
  • Toggling real-time dashboard on/off
  • Toggling monetization on/off

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

Collapse
 
wobsoriano profile image
Robert • Edited

Added a new feature for v0.1.1

Probabilistic RevShare - Agreeing to support the developer gives him 5% chance of getting a payment every second a member is in a Web-Monetized content.

Probabilistic Revenue Sharing

Collapse
 
emma profile image
Emma Goto 🍙

This looks super cool and useful!

Collapse
 
wobsoriano profile image
Robert

Thanks a lot Emma!

Collapse
 
ben profile image
Ben Halpern

Very cool! I have it installed and it looks great!

Collapse
 
wobsoriano profile image
Robert

Awesome. Thanks Ben! ♥️

Collapse
 
thomasbnt profile image
Thomas Bnt ☕

This is super cool 😍

Collapse
 
wobsoriano profile image
Robert

Thanks Thomas! 👍

Collapse
 
dfoderick profile image
Dave Foderick

Awesome. I have already started using this.

Collapse
 
wobsoriano profile image
Robert

Thanks Dave!

Collapse
 
ttpro1995 profile image
Thai Thien

How can I enable "charity option" ?

Collapse
 
wobsoriano profile image
Robert

Available in Chrome now!