It took us a little while to get our Uphold account set up and approved, but once we managed to get our payment pointer, integrating Web Monetization was pretty easy: just adding the <meta>
tag with our payment pointer to each of our pages.
<meta name="monetization" content="$ilp.uphold.com/nzj2HrUbBDKa" />
We're not looking to put Interruptor's content behind a pay wall, so we'll be working to create extra features for people supporting us through Web Monetization as a way to say thanks.
In the meantime, we've set up the site to actually say "thanks" when someone uses the site with Web Monetization activated.
Our site is made with TypeScript, React and NextJS, so we made a useWebMonetizationState
hook to check when WM is activated:
import { useEffect } from 'react'
import {
MonetizationEventMap,
MonetizationEventType,
MonetizationObject,
MonetizationState,
} from '@webmonetization/types'
import { TEventListener } from '@webmonetization/types/build/genericEventListeners'
import { atom, useAtom } from 'jotai'
/**
* Add Web Monetization to the global types
*/
declare global {
interface Document {
monetization?: MonetizationObject
}
}
/**
* Add the event listener and return a function for removing it later
*/
const addEventListener = <TEvent extends MonetizationEventType>(
event: TEvent,
eventListener: TEventListener<MonetizationEventMap[TEvent]>,
): (() => void) => {
document.monetization?.addEventListener(event, eventListener, {
passive: true,
})
return () => document.monetization?.removeEventListener(event, eventListener)
}
/**
* Create the atom where we'll store the current monetization state
*/
const webMonetizationStateAtom = atom<MonetizationState>('pending')
export const useWebMonetizationState = (): MonetizationState => {
const [state, setState] = useAtom(webMonetizationStateAtom)
useEffect(() => {
const onStart = () => setState('started')
const onStop = () => setState('stopped')
const events = [
addEventListener('monetizationstart', onStart),
addEventListener('monetizationprogress', onStart),
addEventListener('monetizationstop', onStop),
]
return () => {
events.forEach((removeListener) => removeListener())
}
}, [setState])
return state
}
For now, since the only thing we're checking is whether it's started, we created a separate hook for that:
export const useHasWebMonetizationStarted = (): boolean => {
const state = useWebMonetizationState()
return state === 'started'
}
We then use that hook in a component so that we can show the thank-you message when payments are being sent.
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'react-toastify'
import { AnalyticsEvent, trackEvent } from 'utils/analytics'
import { useHasWebMonetizationStarted } from 'utils/monetization'
export const WebMonetizationToaster: React.FC = () => {
const { t } = useTranslation('monetization')
const hasStarted = useHasWebMonetizationStarted()
useEffect(() => {
if (!hasStarted) return
// Show the thank-you message
toast.success(t('thanks'))
}, [hasStarted, t])
useEffect(() => {
if (!hasStarted) return
// Send an event to Plausible so we can see how many visitors use it
trackEvent(AnalyticsEvent.WEB_MONETIZATION_ACTIVE)
}, [hasStarted])
return null
}
It might get refactored a bit in the future, but for now it's working, which is the most important thing!
Top comments (0)