Formal documentation

Purpose
Create formal documentation that can be merged into MDN.
+ web monetization agent https://github.com/WICG/webmonetization/issues/133#issuecomment-985760305

The Web Monetization specification provides a frictionless payment experience for site owners and site visitors. It deliberately does not provide a user interface; instead, when a web-monetized visitor visits a web-monetized website a transaction takes place automatically. Thus, visitors automatically pay a small sum per time unit to any web-monetized website they visit.

Web Monetization core concepts

Both visitor and owner must have an account at an Interledger-enabled ledger. Payments will be made from the visitor's to the owner's account. In addition, visitors must be members of a payment provider that arranges for the payments to be sent from their account to the owner's account.

Site owners must add a <link> tag with a payment pointer to their site that defines a payment end point. When web-monetized visitors are logged in to their payment provider the web monetization implementation (for instance a browser or an extension) will automatically scan for payment pointers and initiate a payment stream from the visitor's account to the defined end point (i.e. the owner's account).

A payment stream typically sends a small amount every second, or any other time unit chosen by the payment provider. Thus, the longer visitors stay on a web-monetized site, the more money the owner receives.

A monetization event fires each time a payment arrives and that allows site owners to monitor whether payments are being sent, and if so how large they are. This allows owners to tailor the site content to the payments received — for instance by showing premium content only to paying visitors.

Iframes embedded in a web-monetized site can be monetized as well, but only if their allow attribute contains the value monetization and the document in the iframe contains a payment pointer. In that case the page in the iframe shares in the monetization stream of the parent page.

<link> tag

<link> tags with a payment pointer must have the following structure:

<link rel="monetization" href="https://example.com/pay-me">

It must have a rel="monetization" that declares the <link> tag is a payment pointer. The href attribute must contain a link to the actual payment pointer.

The payment pointer is a JSON file that implementations download and read. This file contains Interledger SPSP instructions that allow implementations to connect to the actual payment end point for the payments. If no JSON is found, or the JSON is malformed, the link element will fire an error event and no payment stream will be initiated.

An HTML document can contain several <link> tags, all of which will share in the monetization stream. However, implementations may set a practical maximum to this number.

<link> tags do not need to be in the <head>. This, for instance, is a valid payment pointer:

<video src="myvideo.mp4">
  <link rel="monetization" href="https://example.com/video/pay">
</video>

Site owners can add a script that plays the video only if the visitor monetizes their site. [Add link to example script, which will do just that.]

Payment pointers will be re-evaluated every time implementations send out an SPSP request. Thus, if a script changes the link's payment pointer or the disabled attribute, this change will be reflected in the next iteration of the payment stream. The stream will be diverted if the <link> tag contains a new payment pointer, and it will stop if disabled is true or a new payment pointer causes an error. Implementations will continue to try to initiate a stream, so once the problem is resolved the payment stream will re-start.

Monetization event interface

The monetization event interface is added to each monetization link element and defines a single monetization event that fires each time an Interledger receipt containing a proof of payment reaches the browser.

Syntax

let monetizationLink = document.querySelector('link[rel=monetization]');
monetizationLink.onmonetization = adjustContent;
// or
monetizationLink.addEventListener('monetization',adjustContent);

function adjustContent() {
//	show or hide content based on the visitor's monetization status
}

Event bubbling

The monetization event bubbles up.

Event properties

The monetization event’s detail has the following properties:

amount
An integer with the amount of money received according to the last receipt.
assetCode
The three-letter code describing the currency; e.g. USD, EUR.
assetScale
The scale of the amount.
receipt
The base-64 encoded Interledger Stream receipt the browser received.
paymentPointer
The <link> tag's payment pointer.

amount is an integer. assetScale gives the scale of the amount. For instance, if amount is 1172 and assetScale is 5, the receiver received 1172*10^-5 or 0.01172 of whatever currency was defined in assetCode.

Examples

In this simple example the video is web-monetized and starts playing only when a web monetization stream has started. The <link> tag is embedded in the video for ease of scripting.

<video src="myvideo.mp4" id="myVideo">
  <link rel="monetization" href="https://example.com/video/pay">
</video>

A monetization event listener is added to the video element. Once the first payment of the web monetization stream arrives the event fires, bubbles up to the video;, and the event handler adds controls to the video and starts playing it.

let monetizedItem = document.querySelector('#myVideo');
monetizedItem.addEventListener('monetization',function(e){
	this.controls = true;
	this.play();
},{once:true})

The following example keeps track of how much money the video received in the current session, i.e. from the last time the visitor loaded or refreshed the page.

let monetizedItem = document.querySelector('#myVideo');
let totalAmount = 0;
monetizedItem.addEventListener('monetization',function(e){
	let amount = e.amount;
	let scale = e.assetScale;
	let currentAmount = amount * 10^-scale;
	totalAmount += currentAmount;
	if (totalAmount > 0.002) {
		// do something, such as starting the video
	}
})

The final example updates the payment pointer by changing the href attribute of the <link> tag. The next payment request will go to the account specified by the new pointer.

let newPointer = 'https://example.com/pay-me-more';
let link = document.querySelector('video link');
link.setAttribute('href',newPointer);