web-monetization

Web Monetization Explainer

Web Monetization is a proposed API standard that allows websites to request a stream of very small payments from a user e.g. fractions of a cent.

This provides a framework for new revenue models for websites and web-based services, as an alternative to subscription services or advertising, while preserving the user’s privacy.

In exchange for payments from the user, websites can provide the user with a “premium” experience such as exclusive content or by removing advertising or even the need to login to access content or services.

Skip straight to code…

Goals

Provide websites with a way to collect multiple small payments from users in exchange for consuming the content and/or services on the website.

The experience must be frictionless for users. It must allow users to pre-approve payments in aggregate or delegate the authorization of the individual small payments to a component/service (a Web Monetization Agent) that makes decisions about when to pay websites, and how much, without the need for user interaction.

This system must preserve the user’s privacy: It must not be possible for websites to track users on the basis of the payments they make, and it must not be possible for the user’s payment provider to get details of a user’s browsing history.

Non-goals

Online purchases. Web Monetization is intended to enable very small payments. This distinction is important because very small payments can be performed with different levels of user consent to larger payments such as those used in traditional e-commerce.

Overview of the Flow

Glossary

Prerequisites

Flow

This flow is simplified to exclude some edge cases. Numbers correspond to the diagram above.

  1. Sites that support Web Monetization include a meta tag whose content is a Payment Pointer. As the name implies, the Payment Pointer is where the site accepts payments.
  2. The browser uses its internal Web Monetization Agent to calculate an appropriate rate of payments to make to the website.
  3. The browser generates a unique session id for this payment session.
  4. The browser fetches a unique receiving address and secret for the session from the website’s WM Receiver.
  5. While the user has the page in focus, the browser begins initiating payments at the calculated rate to the website using the user’s WM Sender. (ISSUE: What about people listening to monetised music in a background tab? See Issue #12)
  6. The WM Sender sends the payment to the WM Receiver.
  7. The WM Sender notifies the browser of successful payments.
  8. The browser, in turn, dispatches an event that informs the web page of the payment.
  9. The web page can connect to its own backend systems to verify that the payment was received (using the session id to correlate the incoming payment stream with the session id generated by the browser in the current page context).

Why is a standard required?

There are many services attempting to provide alternative means to monetize the Web and generate revenue for content creators and service providers without selling ads.

However, most of these require that the user and the creator/producer/service provider join a common network that offers to facilitate the transactions between users and these services.

The result is a fragmented Web of closed content and service silos, rather than the global and open Web we desire. Further, users sacrifice their privacy because the service is both, collecting payments from the user and, paying out to the creator/producer/service provider. It is therefor able to correlate these and collect data about which services are used by users.

With Web Monetization the sender and the receiver are decoupled, using the browser as an intermediary, the privacy of users is protected and payments can’t be used to track a user across sites.

Design Discussion Points

This proposal is modelled on a working implementation that uses a browser extension to provide the necessary browser-side functionality. However, there are various design decisions that may be worth discussing further as a community as we figure out how this could be built directly into browsers.

By bringing this work to the WICG, our goal is to get input from multiple WM providers and implementors to refine the design and produce a W3C standards-track specification.

Declaritive vs Imperative API?

The current proposal is for a hybrid declarative and imperative API. Websites declare their ability to accept WM payments using a <meta> tag in the page header. Imperatively, a developer can then access the global monetization object on the DOM to track incoming payments stream/events and react to these.

Use updated Payment Request and Payment Handler APIs?

The Web Payments WG has designed two APIs that follow a similar pattern to Web Monetization but for a different use case.

The Payment Request API is an imperative API that websites can use to request a single discrete payment: the Payment Request API is designed to always prompt the user for authorization as part of the flow as it is designed for payment sizes where this is necessary. However, nothing prevents this API also supporting a non-interactive flow that supports Web Monetization use cases.

Further, the Payment Handler API aligns well with the model anticipated for Web Monetization senders: A sender might manifest as a specialized Payment Handler capable of returning not just a PaymentResponse but also a handle to a stream of micropayments.

This sounds a lot like Streams…

In-keeping with the trend toward streaming APIs, the API surface could be updated to implement the WHATWG Stream API rather than events.

We will investigate the pros/cons of using streams and events for Web Monetization as part of the incubation process.

Concepts

Web Monetization depends on two critical technologies/concepts that enable open and interoperable payments between providers and websites for very small amounts.

Interledger

Interledger is a payment messaging protocol for making payments of any size that can be aggregated and settled over existing payment networks (including those that do not support very small payment sizes or real time payments clearing).

The design of the protocol also allows for payments to be made that span multiple underlying settlement networks, improving the interoperability and reach of existing networks.

WM senders and WM receivers use the Interledger protocol to exchange payments. The sender and receiver MAY be directly connected or may connect via one or more intermediaries, this will be driven by the regulatory requirements and the status of intermediaries as registered money services businesses.

For more details see https://interledger.org

Payment Pointers

Payment Pointers are a convenient and concise way to express a URL that points to a secure payment initiation endpoint on the Web.

Payment Pointers resolve to an HTTPS URL using simple conversion rules.

Using Payment Pointers, systems that offer payment accounts to users can to give them a simple and easy to remember identifier for the account, that is safe to share with 3rd parties (i.e. not like a credit card number) and is immediately identifiable as a payment account identifier.

An example of a Payment Pointer is: $alice.wallet.example or $wallet.example/alice

These resolve to https://alice.wallet.example/.well-known/pay and https://wallet.example/alice respectively.

Websites that use Web Monetization require a receiving address for their payments (which they will get from their WM receiver) and insert this into the appropriate meta tag as EITHER a URL or a Payment Pointer.

For more details see https://paymentpointers.org

Getting Started

Setup a receiving account

To use Web Monetization a website owner must have a financial account at a service provider capable of receiving payments via the Interledger protocol (i.e. a WM receiver).

Such a service (a digital wallet, bank, or similar) would provide the website owner with a Payment Pointer that serves as the public address for the account.

Example: Alice owns the website at https://rocknrollblog.example and opens an account at Secure Wallet Ltd.. Secure Wallet tells Alice that the Payment Pointer for her account is $secure-wallet.example/~alice. For privacy reasons Alice might also get the Payment Pointer $secure-wallet.example/db74f8b4-d6a0-4489-a021-e785e5efb229 or be able to generate new addresses on demand (this would be a feature of her WM receiver).

Add <meta> tag to website header

The website puts a <meta> tag in the header of the HTML documents it serves with the name attribute equal to monetization and the content attribute equal to the Payment Pointer where the website will accept payments.

Example: Alice puts the tag <meta name="monetization" content="$secure-wallet.example/~alice"> into the <head> section of https://rocknrollblog.example.

Web Monetization only works on secure pages served over HTTPS (or http://localhost for testing), in order to preclude bad actors like ISPs injecting their own <meta> tags onto pages.

ISSUE: How dow we ensure only legitimate tags are parsed by the browser?

See Issue #5

Handle payments

When a user visits the page with a supported browser the website will find a document.monetization object in the DOM. This will have a state property that the website can check to determine if the user’s provider has started sending payments.

The document.monetization object will emit events when monetization starts and then subsequently each time a payment is sent successfully by the provider. The start event will contain a unique identifier for the payment stream that the website can use to correlate the payments at its receiver with the user’s current browser session.

Example: Alice adds some client-side code to her website that listens for the relevant monetization events and only shows advertising if she isn’t receiving payments.

<head>
  <meta name="monetization" content="$secure-wallet.example/~alice" />
</head>
<script>
  if (document.monetization) {
    document.monetization.addEventListener('monetizationstart', event => {
      // User has an open payment stream

      // Connect to backend to validate the session using the request id
      const { paymentPointer, requestId } = event.detail
      if (!isValidSession(paymentPointer, requestId)) {
        console.error('Invalid requestId for monetization')
        showAdvertising()
      }
    })

    document.monetization.addEventListener('monetizationprogress', event => {
      // A payment has been received

      // Connect to backend to validate the payment
      const {
        paymentPointer,
        requestId,
        amount,
        assetCode,
        assetScale
      } = event.detail
      if (
        isValidPayment(paymentPointer, requestId, amount, assetCode, assetScale)
      ) {
        // Hide ads for a period based on amount received
        suspendAdvertising(amount, assetCode, assetScale)
      }
    })
    // Wait 30 seconds and then show ads if advertising is no longer suspended
    setTimeout(maybeShowAdvertising, 30000)
  } else {
    showAdvertising()
  }
</script>

ISSUE: Should the amount in the monetizationprogress event use the existing PaymentCurrencyAmount type?

See Issue #11

Browser Behaviour

A browser supporting Web Monetization exposes a DOM object document.monetization that implements EventTarget and has a readonly state property. Initially the browser sets document.monetization.state to pending.

  1. If the browser finds a valid Payment Pointer in a Web Monetization <meta> tag it generates a fresh UUID (version 4) and uses this as the Session Id from this point forward. This Session Id MUST be unique per page load, not per browser, session nor site.

    • The <meta> tags MUST be in the <head> of the document.
    • If the Web Monetization <meta> tags are malformed, the browser will abort Monetization processing here. The browser SHOULD report a warning via the console.
    • If the Web Monetization <meta> tags are well-formed, the browser should extract the Payment Pointer.
  2. The browser uses its internal Web Monetization Agent to calculate the rate it should pay the current website. If the result is 0 it aborts.

  3. The browser resolves the Payment Pointer and gets a unique Interledger Address and Shared Secret to use for the current session. It then begins sending payments via the WM Sender.

  4. The browser invokes the user’s Web Monetization Sender by emitting new PaymentRequestEvent events with the necessary details.

  5. Once the sender has successfully completed the first payment with a non-zero amount, the browser sets document.monetization.state to started and then dispatches the monetizationstart event on document.monetization. The event’s type is monetizationstart. The event has a detail field with an object containing the Payment Pointer and the Session ID.

  6. The browser continues to send payments at the calculated rate. Every time the it completes a payment (including the first payment) it dispatches a monetizationprogress event from document.monetization. The event has a detail field with an object containing the amount and currency of the payment.

  7. Payment continues until the user closes/leaves the page. The browser MAY decide to stop/start payment at any time, e.g. if the user is idle or backgrounds the page.

Auditing / Dashboard

It must be possible for the user to get a summary of payments compiled by the browser. These should be broken down by origin of the websites paid and the WM sender making the payments, date and time to allow the user to reconcile data from websites and WM senders about how much they have paid.

It should also be possible to tell the browser NOT to pay a particular website any money. (Use case: web user needs to visit a monetized web site with unpalatable viewpoints etc and doesn’t want to contribute financially.)

Bruce reckons that document.monetization shouldn’t be present in this case - site should not be able to guess that their site is blocked because document.monetization.state never moves from pending.

It should also be possible to tell the browser a list of sites which can optionally be paid more than the usual sum. (Use case: web user visits favourite charity’s website.)

WM Sender Interface

The WM Sender interface leverages the Payment Handler API.

More details are provided here

Existing Implementations

Please submit a PR if you are aware of updates to the lists below.

WM Receivers

WM Senders

Browsers