The Web Monetization meta tag and API
Tags: webmonetization, coil, webdev
Published: 2021-07-06 10:00:33

[Part 1](https://dev.to/coil/let-s-talk-about-money-47i5) of this series made clear why web monetization is a good thing. [Part 2](/coil/how-it-works-1b1) described the Coil system at high level. In this third article we're going to take a closer look at details: the `<meta>` tag and the JavaScript API.

The [Coil developer site](https://developers.coil.com/) contains more information about technical topics, including a few example scripts.

## The meta tag

During the sign-up process for Coil and Interledger you set up a wallet, which enables you to receive payments. You are given a payment pointer for that wallet in the form `$url.of.server/someID`. In order to monetize a page you should add a `<meta>` tag on that page that contains this pointer:

```
<meta name="monetization" content="$url.of.server/someID">
```

Right now you need tthe Coil extension to read out the `<meta>` tag — but in the future, when browsers support web monetization natively, they will do so themselves. If a page contains multiple monetization `<meta>`tags the extension uses the first one and ignores the others.

All this works without JavaScript. Neither the current extension nor the future standard are reliant on scripting for the initiation of a payment stream. If you want to get any information, though, or if you want to change the payment stream’s direction, you need JavaScript.

You can change the payment pointer by changing the `<meta>`tag. It's ugly, but it works:

```
<meta name="monetization" content="$url.of.server/someID" id="paymentPointer">

function changePointer() {
	let meta = document.querySelector('#paymentPointer');
	meta.setProperty('content','$url.of.server/myOtherID');
}
```

The plugin will pick up on this change even in the middle of a session and divert all future payments to the new payment pointer.

One reason to do so is a collaborative article. If an article has, say, three authors, JavaScript could pick one of them at random and send the payment stream their way. Technically, you do this by switching the `<meta>`tag's content, as shown above. See [this article](https://webmonetization.org/docs/probabilistic-rev-sharing/) for more information.

You could also use the Intersection Observer to figure out which page element is in view right now, and change the payment pointer based on that information. This could be useful if one page shows art by several creators, for instance. [This article](https://coil.com/p/sabinebertram/Web-Monetized-Image-Gallery-Intersection-Observer-Demo-/HY5nl9NT) gives an overview and a code example.

### Future: link

In the future specification the `<meta>` tag will likely change to a link tag, like this one:

```
<link rel="monetization" content="https://url.of.server/someID">
```

The reasons are complex and can be [read here](https://github.com/WICG/webmonetization/issues/19#issuecomment-705407129). The [upcoming Firefox implementation](https://community.webmonetization.org/wmfirefox/exploring-integration-of-web-monetization-into-the-web-platform-grant-report-1-5ama) uses this link, and not a `<meta>`.

That means that in the future any script that changes the payment pointer has to be rewritten, possibly changing the pointer in both the `<meta>` and the link tag. For that reason it would be nicer if the JavaScript API offered a direct, imperative way of setting the pointer, like:

```
document.monetization.pointer = '$url.of.server/someOtherID';
```

Right now the API doesn’t support this, although it is one of the many ideas [under discussion](https://github.com/wicg/webmonetization/issues/).

## JavaScript API

Since we’re on the topic anyway, let’s discuss the [JavaScript API](https://webmonetization.org/docs/api/). It’s a light-weight, useful thing to have in your back pocket while messing about with payment streams. It consists of the `document.monetization` container, three events, and one property.

This API is part of the proposed standard, and if browsers start supporting web monetization natively they’ll take over this API as well. In that sense, current extension serves as a polyfill and scripts you write now will continue to work in the future.

### document.monetization

`document.monetization` is the container for all API functionality, and its presence indicates that your current visitor supports monetization:

```
if (document.monetization) {
	// user may monetize you;
	// find out and do something
} else {
	// user is certain not to monetize you
}
```

`document.monetization` is a `<div>` DOM node that is not inserted into the document. Thus you can read `document.monetization.nodeName` and most other DOM properties, even though there is no practical reason to do so.

Making it a DOM node allows the firing of the custom monetization events we’ll treat in a moment. Without this trick it appears to be quite difficult to fire custom events from extensions, though specific information is surprisingly hard to find.

### state

`document.monetization.state` contains information about the current monetization state. It can take three values:

* `started`: a monetization stream has started and you will receive money. At least one valid Interledger package has been received.
* `pending`: a monetization stream has not yet started, but the extension is trying to connect.
* `stopped`: no monetization stream possible: the page has no `<meta>` tag, or the pointer is invalid.

If no `<meta>` tag is found the initial state is `stopped`. If a `<meta>` tag is present the initial state is `pending`.

If the `<meta>` tag contains no valid payment pointer the state becomes `stopped`. If a valid payment pointer is present the extension connects to the Interledger server and waits for the first package. Once that package arrives the state becomes `started`.

The state remains `started` even if the connection drops — the extension keeps track of the time spent on the site, after all.

If you change the payment pointer the extension first goes to `pending` and then to either `started` or `stopped`, depending on the validity of the new pointer.

So this snippet tells you if the user is currently paying you:

```
if (document.monetization && document.monetization.state === 'started') {
	// user is currently paying you
}
```

### Events

`document.monetization` allows you to capture four events, three of which mirror the `state` property pretty closely:

* `monetizationpending`: a monetization stream is being started up, but is not sending payments yet. Fires when the `state` is set to `pending`.
* `monetizationstart`: a monetization stream has started. Fires when the `state` is set to `started`.
* `monetizationprogress`: a new single payment has arrived. See below.
* `monetizationstop`: a monetization stream has stopped. Fires when the `state` is set to `stopped`.

Typically, when a payer enters a payee’s page and a `<meta>` tag is present. the `monetizationpending` event will fire, followed by a `monetizationstart` event and an indeterminate amount of `monetizationprogress` events. If the payment pointer is invalid `monetizationstop` fires.

This is exactly the same sequence as with the `state` property, except that no event will fire if no `<meta>` tag is present. The sequence restarts at `pending` whenever you change the payment pointer.

The information the events deliver allows you to build a basic script to show/hide extra content:

```
if (document.monetization) {
	let extraContent = document.querySelector('#extraContent');
	document.monetization.addEventListener('monetizationstart',function() {
		extraContent.style.display = 'block'; 
		// or any other way of showing content
	});
	document.monetization.addEventListener('monetizationstop',function() {
		extraContent.style.display = 'none'; 
	});
}
```

Again, this script is fairly easy to hack, and won't work without JavaScript being enabled. It’s not suited for serious use, especially not in web development sites. Still, it serves as an example of using the monetization events.

### monetizationprogress

The monetizartionprogress event fires whenever an Interledge package with a non-zero sum arrives from the Coil servers, which is generally every second or so. It contains information about the amount that's been paid so far, and you could use it to build a [micropayment counter](https://webmonetization.org/docs/counter/).

If the connection drops the payment stream also drops and the monetizationprogress event stops firing. If the connection is restored the event resumes after a new connection to the Interledger server has been made. As we saw before, the extension keeps track of the time the user has spent on your site, and the first payment after the restoration of the connection will pay for that entire time. Thus, you cannot assume that the payer stopped paying just because monetizationprogress stops firing.

### Event properties

If you want to find out wha the current payment status is you can use the special properties of these events. All these are properties of `event.detail`.

* `amount` is the amount contained in the current Interledger package, as an integer.
* `assetCode` is a code for the currency, either a cryptocurrency or a real one.
* `assetScale` is the number of places past the decimal for the amount. This serves to keep `amount` an integer.
* `paymentPointer` is the payment pointer the extension read from the `<meta>` tag.
* `receipt` is a proof of payment sent back to the payer.
* `requestID` is a transient ID temporarily assigned to your payment stream.

For instance, this gives you the amount the last package delivered:

```
document.monetization.addEventListener('monetizationprogress',function(e){
	let amt = e.detail.amount;
	let scale = e.detail.assetScale;
	let code = e.detail.assetCode;
	let amount = amt * Math.pow(10,-scale);
	let printableAmount = code + ' ' + amount;
	// do something with amount or printableAmount
})
```

`paymentPointer` contains the same information as the `<meta>` tag. `receipt` and `requestID` contain values that are internal to the Interledger packages. You can use it to write a [receipt verifyer](https://webmonetization.org/docs/receipt-verifier/) if you like.

Reading out the amount of money an Interledger package contains requires the amount-related properties. For instance, if `amount` is 17 and `assetScale` is 3 you received 17*10^-3, or 0.017, of the currency indicated in `assetCode`.

That concludes our study of the `<meta>` tag and API. In the [final part](/coil/the-future-of-web-monetization-2n3) we’ll take a look at web monetization’s future, which includes a formal W3C standard.