Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/img/blog/2025-10-17/tools-flowpng.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
167 changes: 167 additions & 0 deletions src/content/blog/2025-10-23-redesigned-publisher-tools-technical.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
---
title: "How the Redesigned Publisher Tools Work: A Technical Dive"
description: "A technical exploration of the architecture details behind the redesigned Publisher Tools"
date: 2025-10-23
slug: redesigned-publisher-tools-technical-dive
authors:
- Darian Avasan
author_urls:
- https://www.linkedin.com/in/darian-avasan/
tags:
- Interledger
- Web Monetization
- Publisher Tools
- Technical
- Architecture
---

If you haven’t heard of Publisher Tools yet, you’re missing out on a simple way to monetize your content! Don’t worry, you can catch up on the details [here]. Today, we’ll focus on the redesign.

The Publisher Tools have been completely redesigned with a focus on simplicity, but there’s a lot happening behind that simplicity. Let's find out how things work after the embed script tag gets added to a website.

### From Script Tag to Rendered Component: The Complete Flow

![Configuration flow](/developers/img/blog/2025-10-17/tools-flowpng.png)

**Key flow steps:**

1. Publisher customizes customize through the interface (the `frontend` module) → Configuration stored as JSON (keyed by wallet address + preset tag e.g., ($ilp.link/your-wallet)", "version1").
2. Visitor loads page with embed script → Script loads from `cdn` module
3. Script fetches configuration → `api` retrieves stored JSON and returns it
4. Script renders the Tool → Instantiates Web Component from `components` with fetched configuration

This system cleanly separates responsibilities: publishers customize through the interface (the `frontend` module), and visitors consume the configuration at WebPage runtime. The `frontend` and visitor-facing flow never interact directly, they're connected only through stored configuration.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also mention the components you see in preview are exactly same as what your users will see, as we use web components.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that's mentioned in a section below.


### The Publisher Embeds the Script

```html
<script
id="wmt-widget-init-script"
type="module"
data-wallet-address="https://ilp.wallet.money/alice"
data-tag="version1"
src="https://cdn.webmonetization.org/widget.js"
></script>
```

**Why we need a `cdn` module**

Publishers embed this script on their sites, so it must load quickly. The `cdn` module bundles the component source code, optimizes it for production, and serves it from Cloudflare's global network.\
The CDN's role is pure delivery: take the source code from `components`, bundle it and serve it.

### Configuration Fetch from API

The script makes an HTTP request to fetch the widget's configuration:

```typescript
async function fetchConfig<T extends Tool>(
apiUrl: string,
tool: T,
params: ReturnType<typeof getScriptParams>
): Promise<ToolConfig<T>> {
const url = new URL(`config/${tool}`, apiUrl)
url.searchParams.set('wa', params.walletAddressId)
url.searchParams.set('preset', params.presetId)
...
}
```

Looking at the above URL, it includes the wallet address and preset tag. The API looks up the stored configuration and returns it as JSON.

**Why we need an `api` module**

Configuration needs to be stored server-side and served dynamically. This enables publishers to update their widget appearance without touching their website code or doing redeployment.\
The **`api`** provides a service that retrieves configuration and later can handle payment operations too, so it serves two critical purposes:

1. **Configuration delivery:** Fetch stored settings and serve them to embedded widgets
2. **Payment proxy:** Handle the Open Payments protocol flow (quote generation, grant authorization, payment finalization)

### Tool Rendering

All our Interactive Tools are built as custom Web component elements within Shadow DOM to prevent host page CSS from affecting the Tool and vice versa.\
With the configuration fetched, the script creates and renders the web component:

```typescript
fetchConfig(API_URL, "widget", params).then((config) => {
const element = document.createElement("wm-payment-widget");
element.config = {
receiverAddress: walletAddress,
...config
};
document.body.appendChild(element);
});
```

The `<wm-payment-widget>` element is one of our interactive tools defined in the `components` module. The script creates an instance, passes the configuration as properties, and appends it to the DOM, using Shadow DOM for style encapsulation.

**Why we need a `components` module**

The UI logic for widgets needs to live somewhere separate from the embed script, hence `components` module contains the actual Web Component implementations: the rendering logic, event handlers, state management, and UI interactions.

By keeping components as standalone source code, they can be consumed in multiple ways:

- Bundled by the `cdn` module for production embed scripts
- Imported by the `frontend` module for live preview during configuration
- 🎉 Potentially published as an npm package for developers who want to bundle them with their own build systems

### Runtime Payment Operations

Beyond the new architecture, the Publisher Tools also handle payments using our [Open Payments (OP) protocol][here]. Every step of the payment flow is proxied through our the `api` module.For example, when a visitor interacts with the widget (entering an amount, clicking "Pay"), the component makes API requests:

```typescript
// Generate a quote
await fetch(`${apiUrl}/payment/quote`, {
method: "POST",
body: JSON.stringify({
senderWalletAddress,
receiverWalletAddress,
amount
})
});

// Initialize grant authorization
await fetch(`${apiUrl}/payment/grant`, { method: "POST", body: "..." });

// Finalize payment after authorization
await fetch(`${apiUrl}/payment/finalize`, { method: "POST", body: "..." });
```

The API manages all interactions with Open Payments SDK handling grant authorization, creating outgoing payments, and coordinating with the component to complete the full protocol flow for the payment.

**Key flow steps:**

1. Visitor interacts with widget (from `components`) → Enters wallet address and amount
2. Component requests quote → `api` proxies to Open Payments infrastructure to handle the amount
3. Component initializes grant → `api` returns authorization URL
4. Visitor authorizes in popup → Wallet provider redirects back with interaction reference
5. Component finalizes payment → `api` creates outgoing payment on Interledger network

## What's Next?

The redesigned Publisher Tools establish a foundation for future enhancements:

**More tools** Add new interactive tools with new ways of visitors to interact and sponsor your content through open payments.

**Analytics integration** We want to give publishers insight into how visitors engage with their tools: how often users interact and how revenue breaks down per page.

**Webhook notifications** Give callback webhooks to publisher when payments occur, with the amount and currency received.

## Try It Yourself

The redesigned Publisher Tools are live at [webmonetization.org/tools](https://webmonetization.org/tools). The source code is open source at [github.com/interledger/web-monetization-tools](https://github.com/interledger/web-monetization-tools).

## Resources

**GitHub Repository:** [interledger/web-monetization-tools](https://github.com/interledger/web-monetization-tools)

**Publisher Tools:** [webmonetization.org/tools](https://webmonetization.org/tools/)

**Open Payments Specification:** [openpayments.dev](https://openpayments.dev/)

**Web Monetization Documentation:** [webmonetization.org/docs](https://webmonetization.org/docs/)

**Interledger Foundation:** [interledger.org](https://interledger.org/)

---

_Questions or feedback about the technical implementation? Open an issue or discussion on [GitHub](https://github.com/interledger/web-monetization-tools) or connect with the Interledger developer community._