Skip to main content

Exclusive Content

One of the perks of Web Monetization is that its JavaScript API can be used to make your page respond to Web Monetization. You can reward the people who support your site by giving web monetized viewers exclusive content.

A basic example

Web Monetization makes providing exclusive content easy! This is a very simple example of showing exclusive content only to web monetized visitors:

> **Careful!** These examples hide content on the client side. A clever user > could pretend to be web monetized by using the developer console. Examples on > how to verify Web Monetization can be found [further down](#exclusive-content-with-payment-verification).

Code

<head>
<!-- this should be set to your own payment pointer -->
<link rel="monetization" href="https://wallet.example.com/alice" />

<style>
.hidden {
display: none;
}
</style>

<script>
const link = document.querySelector('link[rel="monetization"]')
if (link.relList.supports('monetization')) {
link.addEventListener('monetization', ev => {
document.getElementById('exclusive').classList.remove('hidden')
})
}
</script>
</head>

<body>
<p>Content will appear below here if you are Web monetized.</p>
<hr/>
<div id="exclusive" class="hidden">Here's some exclusive content!</div>
</body>

How does it work?

There's only three things this code does. The code is encompassed in the <script> tag.

First, we check whether Web Monetization is supported by calling supports() on a link element's relList and passing "monetization" as a parameter. If it doesn't exist, then we can't listen for the monetization event to tell us when Web Monetization initializes.

const link = document.querySelector('link[rel="monetization"]')
if (link.relList.supports('monetization')) {

Next, we add an event listener to the link element. The monetization event is emitted when Web Monetization initializes.

link.addEventListener('monetization', ev => {

Finally, we select our exclusive content element and make it visible. We defined a CSS class that made it hidden, so removing that class will make it visible. If you want to do something else when Web Monetization starts, you can replace this line. You can trigger any JavaScript, so the sky's the limit.

document.getElementById('exclusive').classList.remove('hidden')})
}

Interactive example

This example simulates showing exclusive content to a web monetized visitor and hiding the content from a non-web monetized visitor. The example doesn't require you to have Web Monetization enabled in your browser. No real payments are occurring.

Click the View as Web Monetized/non-Web Monetized visitor button to toggle your monetization state.

If you see the source files instead of the example, click View App in the bottom right.

A complete example

In reality, your requirements will be a little more complex. You should:

  • Show web monetized visitors an indicator while they wait for Web Monetization to initialize.
  • Tell non-web-monetized visitors that there's exclusive content they can get.

This means there's three states in total:

  • Show a call-to-action to a non-web-monetized visitor
  • Show a loading message to a web monetized visitor
  • Show exclusive content to a web monetized visitor

Code

<head>
<!-- this should be set to your own payment pointer -->
<link rel="monetization" href="https://wallet.example.com/alice" />

<style>
.hidden {
display: none;
}
</style>

<script>
function showExclusiveContent() {
document.getElementById('exclusive').classList.remove('hidden')
document.getElementById('loading').classList.add('hidden')
document.getElementById('cta').classList.add('hidden')
}

function showCTA() {
document.getElementById('loading').classList.add('hidden')
document.getElementById('cta').classList.remove('hidden')
}

function showLoading() {
document.getElementById('loading').classList.remove('hidden')
}

if (window.MonetizationEvent) {
const link = document.querySelector('link[rel="monetization"]');
link.addEventListener("monetization", ev => {
showExclusiveContent()
})
}

window.addEventListener('load', () => {
if (!window.MonetizationEvent) {
showCTA()
} else {
showLoading()
}
})
</script>
</head>

<body>
<div id="loading" class="hidden">Loading exclusive content...</div>

<div id="exclusive" class="hidden">Here's some exclusive content!</div>

<div id="cta" class="hidden">
Please install a Web Monetization extension to support me!
</div>
</body>

How does it work?

We have three functions to activate our three different states: showLoading displays the loader, showCTA displays the call-to-action to get web monetized, and showExclusiveContent shows the exclusive content. This works just like the basic example where we turn the hidden class on/off for our divs.

When the visitor is web monetized, we listen for the monetization event. Just like the previous example, this event will show the exclusive content when it's triggered and hide the other divs.

if (window.MonetizationEvent) {
const link = document.querySelector('link[rel="monetization"]')
link.addEventListener("monetization", ev => {
showExclusiveContent()
})
}

When the page loads, we check whether Web Monetization exists in the visitor's browser.

    window.addEventListener('load', () => {
if (!window.MonetizationEvent) {

If the visitor doesn't have Web Monetization, then we show the CTA right away. If the visitor does have Web Monetization, we show the loader right away.

      if (!window.MonetizationEvent) {
showCTA()
} else {
showLoading()
}

Interactive example

This example simulates showing and hiding content based on whether your visitor is web monetized. Web monetized visitors will see exclusive content that's hidden from non-web monetized viewers. Non-web monetized visitors will see the message, "Please install a Web Monetization extension to support me", which is hidden from web monetized visitors.

The example doesn't require you to have Web Monetization enabled in your browser. No real payments are occurring.

Click the View as Web Monetized/non-Web Monetized visitor button to toggle your monetization state.

If you see the source files instead of the example, click View App in the bottom right.

## Exclusive content with payment verification

The above examples only hide content client side which could be spoofed by a clever user. A web monetized can be verified checking the [incomingPayments](/docs/monetization-event-incoming-payments) attribute of the `MonetizationEvent` interface.

The above examples only hide content client side which could be spoofed by a clever user. Since the introduction of STREAM receipts it is possible to verify payments using a STREAM receipt verifier.

The Exclusive Content Generator allows users to generate an encrypted piece of content that can be embedded on the web page.

info

Want to try the Exclusive Content Generator right away? Check it out here.

How does it work?

The Exclusive Content Generator derives an encryption key from the user's payment pointer and a master key and returns it to the Creator's client. The client then encrypts the exclusive content and the verifier endpoint and displays all the information required for decryption in a div tag. It also provides a JavaScript script to be embedded on the Creator's web page.

The embedded JavaScript script will parse all the exclusive content div tags and include the proxy payment pointer in the web page's header (if there are multiple, it will select one at random). If Web Monetization is enabled by the User, receipts can now be obtained from the receipt property of the MonetizationEvent event interface. The receipts, together with the payment pointer and the encrypted verifier endpoint, are submitted to the Exclusive Content Generator, which derives the encryption key and decrypts the verifier endpoint. If the Exclusive Content Generator is able to verify the receipts with the STREAM receipt verifier, it shares the encryption key with the User's client, who is now able to decrypt the content and display it.

Interactive example

The example page will request the decryption key for each piece of exclusive content if Web Monetization is enabled. If it is not enabled, it will say "🔒 This content is exclusive for users with Web Monetization enabled."

The preview below simulates showing exclusive content to a web monetized visitor and hiding the content from a non-web monetized visitor. The example doesn't require you to have Web Monetization enabled in your browser. No real payments are occurring.

Click the View as Web Monetized/non-Web Monetized visitor button to toggle your monetization state.

If you see the source files instead of the example, click View App in the bottom right.

If you want to interact with a fully functionable example which does require you to have Web Monetization enabled in your browser, visit this demo page with Web Monetization enabled.