Web Monetization allows websites to automatically receive payments from users, facilitated by the user agent and a user's preferred monetization provider.

This specification is a work in progress within the community on the best shape it should take. Please see the explainer for more info.

The specification reflects the desired end-state of the Web Monetization APIs as currently anticipated and agreed to between the contributors. The specification is being prepared here, in this format, to collect the input of the Web community and prepare the work to ultimately follow the W3C standards track should it have the necessary support to do so.

For the most accurate reflection of the APIs that have been implemented by providers see the API documentation.

Usage examples

Checking if Web Monetization is supported

There are multiple ways to check if Web Monetization is supported. One way is to call {{DOMTokenList/supports()}} on a [^link^] element's {{HTMLLinkElement/relList}} passing the `"monetization"` keyword. Alternatively, you can check if either the {{MonetizationEvent}} interface or the "`onmonetization`" [=event handler IDL attribute=] exist on the {{Window}} object.

Monetizing a web page

Monetization events

The {{MonetizationEvent}} DOM events provide information such as the amount sent, the currency of the payment, and a link to the incoming payment at the [=monetization receiver=] which can be used to verify the receipt of payment. As in the previous example above, these events are dispatched to [^link^] elements and bubble up the DOM tree.

To listen for {{MonetizationEvent}} events, an [=event listener=] needs to be added to the relevant [^link^] element (or to one of its ancestors) via JavaScript:

Verifying a payment

The {{MonetizationEvent}}'s {{MonetizationEvent/incomingPayment}} attribute is a URL that can be used to verify the payment at the [=monetization receiver=].

In most cases requests to the {{MonetizationEvent/incomingPayment}} URL will need to be authenticated as they fetch sensitive details such as the `receivedAmount`. The specifics of this authentication are agreed by the website and the [=monetization receiver=] when setting up the receiving account.

Below is a hypothetical naive verification method that will make a request to the {{MonetizationEvent/incomingPayment}} URL and simply return the results. For simplicity it has no logic for authenticating the request.

A more sophisticated implementation should track the `receivedAmount` property and ensure it is increasing after each {{MonetizationEvent}} to verify that a new payment has been received.

Monetizing media

The following example shows how to monetize various types of media using different [=payment pointers=].

Model

Monetization:
Payments made by a user to a website, facilitated through a [=monetization provider=].
Monetization provider:
The party making payments on behalf of the user. A monetization provider leverages the [[[Interledger]]] suite of protocols and technologies (e.g., [[Open Payments]] based on [[STREAM]]) to provide a high-level way to pay a [=monetization receiver=].
Monetization receiver:
The party receiving payments on behalf of the website, whose details are provided by a [=payment pointer=].
Payment Pointer:
A [=URL=] to an Open Payments API entry-point (i.e., a JSON resource containing details that facilitate payment to an account).
Payment session
An session between a [=monetization provider=] and [=monetization receiver=] initiated by the [=user agent=] at the [=monetization receiver=]. One or more payments can be initiated by the [=monetization provider=] in a single session.

Goals

Link type "monetization"

The monetization keyword indicates a [=payment pointer=] used to monetize the document.

The monetization keyword may be used with link elements. This keyword creates an external resource link.

The monetization keyword indicates that some aspect of the document is monetized.

The default type for resources given by the monetization keyword is application/json.

The appropriate times to fetch and process this type of link is:

A user agent MUST NOT delay the load event for this link type.

The linked resource fetch setup steps for this type of linked resource, given a link element element and request request, are:

  1. If element cannot navigate, then return false.

  2. If element's node document is not [=allowed to use=] the "monetization" feature, return false.

  3. Let context be element's node document's browsing context.

  4. Set request's initiator to "`document`".

  5. Set request's destination to "monetization".

  6. Set request's mode to "cors".

  7. Set request's credentials mode to the CORS settings attribute credentials mode for element's crossorigin content attribute.

  8. Return true.

To process this type of linked resource given a link element element, boolean success, and response response:

  1. If |response|'s status is not an OK status, the set |success| to false.

  2. Otherwise, if response's Content-Type metadata is not a application/json, then set success to false.

  3. Let |json| be the result of [=parse JSON bytes to an Infra value=] passing |response|'s [=Response/body=].
  4. If |json| is an exception, then set success to false.
  5. If the user agent has exhausted the number of allowed [=payment sessions=], set |success| to false.

  6. Otherwise, establish a new [=payment session=].
  7. [=Queue an element task=] on the [=networking task source=] given |element| and the following steps:
    1. If |success| is true, [=fire an event=] named `"load"` at |element|.
    2. Otherwise, [=fire an event=] named `"error"` at |element|.

If a "monetization" link becomes browsing-context disconnected, a user agent MUST stop the [=payment session=].

`onmonetization` event handler

The `onmonetization` event handler is an [=event handler content attribute=] that can be applied to any [=element=]. The user agent uses it to notify that some [^link^] has been [=monetized=].

monetization event

When the [=payment session=] has sent a |payment| with a non-zero amount, perform the following steps:

  1. Let |target:HTMLLinkElement| be the {{HTMLLinkElement}} associated with the [=payment session=].
  2. If |target| is `null`, then return.
  3. Let |eventInitDict:MonetizationEventInit| be a {{MonetizationEventInit}} dictionary, whose members are initialized to match |payment|'s details.
  4. Let |event:MonetizationEvent| be a newly constructed {{MonetizationEvent}} initialized with |eventInitDict|.
  5. [=Queue a task=] on the [=monetization task source=] to perform the following steps:
    1. If |target| is not connected, return.
    2. [=Fire an event=] named `"monetization"` at |target|, with {{Event/bubbles}} initialized to true.

Task sources

The following [=task source=] is defined by this specifications.

The monetization task source
Used by this specification to queue up non-blocking {{MonetizationEvent}}s.

`MonetizationCurrencyAmount` interface

The `MonetizationCurrencyAmount` interface maps directly to the {{PaymentCurrencyAmount}} dictionary as defined in [[payment-request]].

          [SecureContext, Exposed=Window]
          interface MonetizationCurrencyAmount {
            readonly attribute DOMString currency;
            readonly attribute DOMString value;
          };
      

currency member

The currency of the MonetizationCurrencyAmount. See the definition of the `currency` member of {{PaymentCurrencyAmount}} in [[payment-request]] for details.

value member

The amount of the MonetizationAmount. See the definition of the `value` member in of {{PaymentCurrencyAmount}} in [[payment-request]] for details.

`MonetizationEvent` interface

        [SecureContext, Exposed=Window]
        interface MonetizationEvent : Event {
          constructor(DOMString type, MonetizationEventInit eventInitDict);
          readonly attribute DOMString? amount;
          readonly attribute DOMString? assetCode;
          readonly attribute octet? assetScale;
          readonly attribute DOMString? receipt;
          readonly attribute MonetizationCurrencyAmount amountSent;
          readonly attribute USVString paymentPointer;
          readonly attribute USVString? incomingPayment;
        };

        dictionary MonetizationEventInit : EventInit {
          required DOMString? amount;
          required DOMString? assetCode;
          required octet? assetScale;
          required DOMString? receipt;
          required PaymentCurrencyAmount amountSent;
          required USVString paymentPointer;
          required USVString? incomingPayment;
        };
      

The `amount`, `assetCode`, `assetScale` and `receipt` attributes are deprecated.

All [=monetization receivers=] should be migrating from generating a [[[Receipt]]] to supporting incoming payments via [[Open Payments]] and will no longer be returning receipts to the browser.

As such the {{MonetizationEvent}} no longer represents an amount received, it represents an amount sent and returns a URL as the {{MonetizationEvent/incomingPayment}} attribute that can be used to determine the amount received.

amount attribute (deprecated)

The amount received as reflected in the receipt from the [=monetization receiver=]. When getting, returns the value it was initialized with.

assetCode attribute (deprecated)

The three letter asset code identifying the amount's units (e.g., "USD" for US dollars). When getting, returns the value it was initialized with.

assetScale attribute (deprecated)

The scale of the amount. For example, USD would have an assetScale of 2 when denominated in cents. When getting, returns the value it was initialized with.

The members of the `MonetizationCurrencyAmount` interface map directly to the `value` and `currency` attributes of a {{PaymentCurrencyAmount}} dictionary. See the documentation of {{PaymentCurrencyAmount}} for guidance on processing and display of these attributes.

amountSent attribute

The amount sent. This should be processed in the same way as a {{PaymentCurrencyAmount}} dictionary as defined in [[payment-request]]. When getting, returns the value it was initialized with.

receipt attribute (deprecated)

`null` or a base64-encoded [[[Receipt]]] issued by the [=monetization receiver=] to the [=monetization provider=] as proof of the total amount received in the [=payment session=]. When getting, returns the value it was initialized with.

paymentPointer attribute

A [=URL=] representing the [=payment pointer=] that has been monetized. When getting, returns the value it was initialized with.

incomingPayment attribute

A [=URL=] representing an incoming payment at the [=monetization receiver=]. When getting, returns the value it was initialized with.

Permissions Policy integration

This specification defines a [=policy-controlled feature=] identified by the string "monetization". Its default allowlist is `'self'`.

Content Security Policy

This section will eventually be moved into the [[CSP]] and [[FETCH]] specifications.

monetization-src directive

The monetization-src directive restricts the URLs from which a [=payment pointer=] is loaded. The syntax for the directive's name and value is described by the following ABNF:

          directive-name  = "monetization-src"
          directive-value = serialized-source-list
        

`monetization-src` Pre-request check

This directive's pre-request check is as follows:

Given a [=request=] (|request|) and a [=violation/policy=] (|policy|):

  1. Let |name| be the result of executing "Get the effective directive for request" on |request|.
  2. If the result of executing "Should fetch directive execute" on |name|, `monetization-src` and |policy| is "No", return "Allowed".
  3. If the result of executing "Does request match source list?" on |request|, this directive's value, and |policy|, is "Does Not Match", return "Blocked".
  4. Return "Allowed".

`monetization-src` Post-request check

This directive's post-request check is as follows:

Given a [=request=] (|request|) and a [=violation/policy=] (|policy|):

  1. Let |name| be the result of executing "Get the effective directive for request" on |request|.
  2. If the result of executing "Should fetch directive execute" on |name|, `monetization-src` and |policy| is "No", return "Allowed".
  3. If the result of executing "Does response to request match source list?" on |response|, |request|, this directive's value, and |policy|, is "Does Not Match", return "Blocked".
  4. Return "Allowed".

Security considerations

It is RECOMMENDED that a user agent provide some UI or indicator that allows the user to know when [=monetization=] is possible and/or when [=monetization=] is occurring. Providing such a UI allows the users to retain control of the monetization process by taking action (e.g., stop or start monetization of a particular site if they wish to do so).

As [=payment pointers=] are generally provided as a service (e.g., Uphold), a XSS attack could inject malicious [=payment pointers=] into a page that uses the same service. To mitigate such an attack, it is RECOMMENDED that developers:

Privacy considerations

Web Monetization is designed to be privacy-preserving: The user agent does not send any data to the [=monetization provider=]. Instead, it requests data from the [=monetization provider=] without ever revealing the URL of the web page the user is currently browsing.

Further, the user agent gets the payment information from the [=payment pointer=] to establish the [=payment session=]. This also ensures the [=monetization provider=] doesn't have access to a user's browsing history or to the [=payment pointer=].

Relation to Web Payments

Unlike [[[Payment-Request]]] and the [[[Payment-Handler]]], which only supports "one-off" payments, Web Monetization provides a [=payment session=] that supports both continuous payments and "one-off" payments.