Documentation

Purpose
Formal documentation of the Web Monetization specification
Sources
The specification — not yet published
JavaScript API
The Web Monetization meta tag and API
Technical contact
Marcos, Alex

This page documents the Web Monetization Specification 2.0 Alpha.

The specification can be found at [I don't know the URL].

Purpose

The WMS specifies a deliberately simple way of implementing a monetization stream, that is, a stream of continuous payments from the visitor to the owner of a web page. Other payment schedules are possible — for instance Payment Request API’s discrete payments such as buying an item or a subscription — but this version of the specification does not cover them. It focuses solely on the continuous payment stream.

Web Monetization is expressly designed not to require any user interaction. If a monetized user visits a monetized page, the monetization stream starts up automatically and only stops when the user leaves the page.

Web Monetization does not require a back-end. It can be implemented in static HTML pages even by newbie web developers.

Site owners have the option of showing premium content to visitors that pay them, although at the moment this depends on JavaScript and the premium content mechanism can likely be enabled by web developers with some JavaScript knowledge.

Overview

Site owners should add a <link> tag that contains a valid payment pointer to the pages or page elements they wish to monetize. They can listen to a monetization event that fires whenever a receipt for a payment comes in. This allows them to react to the presence or absence of a monetization stream, for instance by showing or hiding content.

<link> tag

Site owners can add <link> tags to their sites, such as:

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

Such a <link> tag must have rel="monetization" and its href attribute must contain a valid payment pointer.

<link> tags are typically placed in the document’s <head>, but this is not required. If only a certain portion of a page is monetized it makes sense to embed the <link> tag in that portion. For instance, this <link> tag is placed in a video element.

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

This one is placed in a section whose content should only be shown when the user pays the site.

<section id="premiumContent">
  <link rel="monetization" href="https://example.com/premiumcontent/pay">
</section>

If a Web Monetization implementation encounters such a <link> tag it automatically starts up a payment stream. However, implementations may set a maximum on the number of payment streams allowed from a single page, so adding dozens of <link> tags is unlikely to work.

monetization event

Monetization <link> tags fire monetization events. Web developers can listen to these events and find out if they’re being monetized. They can react by showing premium content.


errors

error event on link works only in firefox

No connection. General error. JSON error.

package can expire if takes too long. If enough expiries take place the state is set to idle. Number decided by monetization agent. Leads to a general error.

payment pointer wrong error. Specific error web dev should know about.

offline

If the user goes offline all monetization streams stop and the monetization state of all pages is set to idle.

This will not be specified in the WMS. The WM API will not notify web developers that a page has gone offline. The web developer will only know that the monetization stream stopped.

Ben: if page goes offline the stream just stops. Seems to make no effort to catch up. This might change once batched payments are implemented.

Nick: We actually have a branch where we are doing batched payments, paying on a much less frequent schedule than the current couple of packets a second. It's a similar problem to solve I guess.

iframes

iframes have an allow attribute that specifies its feature policy. The WMS defines the monetization value that, if set, allows monetization of the page in the iframe.

If allow="monetization" is set, the iframe will start up a monetization stream that's independent of the main page's stream. If the value is not set the iframe cannot be monetized.

This behavior will be described in the Web Monetization Specification. Issue. It will not state HOW the payment stream is divided, though.

Ben told me it isn't yet clear how iframes and main page are going to split revenue. There are potential privacy issues (number of concurrent connections might reveal what site you're on)

Malicious web developers might include hundreds of iframes on their pages to get hundreds of payment streams. This is undesirable, so some form of revenue splitting is necessary.

Nick: The extension currently supports arbitrarily nested iframes, as long as the chain of elements all include "allow monetization" in their content security policies. We've talked about various ways of sharing and what makes the most sense. Only the top frame? Only the currently "visible"/"active"f frame[s], shared equally etc. There's not been much clear consensus

Nick: It was quite a pain to implement/hack and I imagine would be pretty tricky to do natively.

This would mean the iframes share the parent page's stream.

Backgrounded

If a browser window is placed in the background, for instance because the user puts the focus on another page, the monetization stream should stop and the monetization state should be set to idle. Users cannot read the page, so they should not be charged. Pages that stream audio ane an exception: they will continue to be monetized, since users continue to consume (part of) their content.

For potentially useful events see also Page Lifecycle API.

A window's position in foreground or background is determined by its visibilityState — the extension listens to the visibilitychange event that fires whenever visibilityState switches. The state becomes hidden when no pixel of that window is currently visible on the screen. Thus, the following actions will send a window to the background:

Or the page? To be tested with a browser window with massive chrome.

For Chrome it's window, and not page. If just the tabs interface is visible, this does not count as hidden.

If even a single pixel of the window remains visible the visibilityState does not change and the page will continue to receive payments. This can lead to odd situations where users think they have sent a page to the background, but the monetization stream actually continues because a tiny sliver remains visible. The system is not perfect, but more fine-grained definitions of visible and invisible are extremely hard to implement, and will likely lead to many more false positives or negatives.

audio

I made up this rule. I think we need something like it, though.

Browser windows that stream audio form an exception to these rules. They will continue to receive payments even if they are fully in the background, since users can still hear (part of) the content.

For detecting audio:

let globalPlayState = false;
let playList = {};
window.addEventListener('play',logPlay,true)
window.addEventListener('pause',logPlay,true)
let ctr = 0;

function logPlay(e) {
	let state = e.type === 'play';
	let tg = e.target;
	let check = tg.dataset.audioCheck;
	if (!check) {
		check = 'audioCheck' + ctr;
		ctr++;
		tg.dataset.audioCheck = check;
	}
	playList[check] = state;
	globalPlayState = false;
	for (let i in playList) {
		globalPlayState = globalPlayState || playList[i];
	}
	// globalPlayState is true when any audio is playing
}

Not perfect; a video without audio is reported as playing; an audio or video element that's never added to the document does not fire the events, even though it may play audio. Not tested with Web Audio.

Also audible attribute of Chrome extensions. Possibly also useful.

Browser compatibility

Puma, and that's it. See Browsers page.

See also

Monetization Interface

Purpose
Formal documentation of the monetization interface
Sources
Spec - new version
JavaScript API
The Web Monetization meta tag and API
Technical contact
Marcos, Alex

The navigator.monetization interface exposes the monetization API as defined in the Web Monetization specification. It allows web developers to retrieve basic information about the current monetization stream and to listen to events describing that stream.

See the Spec Questions page for the current discussions.

Properties

navigator.monetization has the following properties:

navigator.monetization.state Read only
A string that contains the state of the monetization stream.
navigator.monetization.pointer
A URL to the payment end-point.
navigator.monetization.onstatechange
Event handler attribute.

Event

navigator.monetization has the following events:

monetization
Fires when an Interledger receipt is received.

When a succesful Interledger payment is made the receiver is notified by a receipt. If the browser receives such a receipt it fires a monetization event. Since receipts may be received every second or so, this event will fire many times.

The monetization event is useful if you are waiting for a particular payment, for instance a tip. Although the current monetization implementation does not support tipping, future ones will. This would for instance allow you to ask for a tip of at least $1 in order to read an article. You would listen to the monetization event until this amount comes in in one single receipt, and then reveal the article.

Properties

The monetization event has the following properties in event.detail:

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.
requestId
The monetization ID created by Interledger.
url
The payment pointer.

The last three properties are not very important to web developers. You need them only if you have to dive into the Interledger details.

The first three attributes contain the amount of money the page just received. The assetScale specifies the scale of the amount. The formula is

let receivedSum = amount * 10^-assetScale

Thus, with an amount of 6 and an assetScale of 3 you received 6 * 10 ^-3 or 0.006 of whatever currency is specified in assetCode.

Examples

Example script here or refer to Web Monetization tutorials?