How-To Guides6 min read

How to Embed a Stripe Donation Form in Plain HTML

You have a hand-coded site and you want to take donations through Stripe. There are two real ways to do it, one is powerful and a genuine project, the other is a paste-and-go. Here is the honest version of both.

KindLumen TeamDecember 9, 2025Updated December 9, 2025

Quick answer

  • Two paths: build it with Stripe.js plus a backend, or paste an embed.
  • The DIY path is powerful but is real, ongoing dev work.
  • A hosted embed gets you live with no backend to maintain.

You have a static site, or a hand-coded one, and you want to take donations through Stripe. Good news: Stripe is excellent and your site is exactly the kind of place a clean embed belongs. Less-good news: there are two real ways to do this, and a lot of tutorials pretend there is only one.

Path one is building it yourself with Stripe.js and a backend. It gives you total control and it is a genuine engineering project, not a snippet. Path two is pasting a hosted embed, which gets you live today with no server to babysit. This guide lays both out honestly, including a minimal code sketch for the DIY route and a frank read on what you sign up to maintain.

website planning notes and campaign materials on a desk for How to Embed a Stripe Donation Form in Plain HTML

The two honest paths

Before any code, get the fork in the road clear in your head, because the rest of your decisions follow from it.

  • Build it yourself. You use Stripe.js on the front end and a small backend to create a Checkout Session or a Payment Intent. You own the form, the validation, the success and cancel handling, and the webhook that confirms the payment. Maximum control. Real work.
  • Paste a hosted embed. You drop a snippet from a donation tool (or a Stripe Payment Link / pricing-table embed) into your HTML. No backend, no webhook, no maintenance. Less control over the exact flow.

Neither is "the right answer." A developer who wants a fully custom donor experience and does not mind owning a server picks the first. Someone who wants donations live by lunch picks the second. Most people overestimate how much they need the first one.

The simplest possible Stripe option is a Payment Link or Checkout: you create it in the Stripe Dashboard and link a button to it. It is the cheapest in fees and it works. But understand what you give up.

A raw Payment Link sends the donor to Stripe's hosted checkout. There is no branded form on your page, no row of suggested amounts, no custom-amount nudge, and no donor records beyond what Stripe stores, unless you build all of that yourself. For a developer that may be fine. For a nonprofit that wants a designed giving moment, it is bare. Stripe's standard rate is 2.9% + 30 cents, and registered nonprofits can apply through Stripe.org for a discounted 2.2% + 30 cents. More on that in how to accept donations with Stripe.

The DIY path: a minimal sketch

If you want the custom route, here is the shape of it. The front end loads Stripe.js and hands off to a backend endpoint that creates a Checkout Session. This is a sketch to show the moving parts, not a copy-paste production app.

The pieces, in order:

  1. Include the Stripe.js library via its script tag in your HTML head.
  2. On your donate button click, call your own backend endpoint, for example a route named create-checkout-session, passing the chosen amount.
  3. Your backend (Node, Python, a serverless function, whatever you run) uses your secret key to create a Checkout Session in donation mode, with the amount and a success and cancel URL.
  4. The backend returns the session URL or id, and your front-end script redirects the donor to Stripe to pay.
  5. You set up a webhook endpoint that listens for the checkout.session.completed event so you can record the gift, send your own receipt, or update a total. Without the webhook you will not reliably know a payment succeeded.

That is the honest minimum: a front-end script, a backend endpoint, a secret key kept off the client, and a webhook. None of it is exotic, but all of it is yours to run.

What the DIY path actually costs you

The code is the easy part. The maintenance is the part the tutorials skip. When you build it yourself, you own:

You ownWhat that means
The backendA server or serverless function that has to stay up, or donations fail silently.
WebhooksVerifying signatures, handling retries, keeping the endpoint reachable.
Receipts and recordsStripe sends a basic receipt; a branded one and a donor record are on you to build.
Recurring logicSubscriptions, failed-payment retries, and cancellations are extra work.
Security and keysKeeping your secret key off the client and rotating it if it leaks.
API updatesStripe versions move; your integration needs occasional care.

If you have a developer who enjoys this and time to maintain it, the DIY path gives you a one-of-a-kind form. If "keep a webhook endpoint healthy" sounds like a chore you will forget about until it breaks during a campaign, that is your signal to look at the embed route.

The embed path: live today, no backend

The other route skips all of that. A donation tool gives you a hosted, Stripe-powered form and a one-line snippet. You paste the snippet into your HTML where you want the form, and you are done, the form renders inline, the processing happens on the tool's side, and the receipts and records come built in.

This is where a tool like KindLumen fits a static site neatly: it is a Stripe-powered form you embed with one line, it renders inline and branded on your page, and donations flow into your own Stripe account with recurring giving and branded receipts already handled, no backend, no webhook to maintain. The features page shows the embed and the recurring setup. For the broader how-to, see how to accept donations on a website.

Which path is right for you

Pick the DIY path if you want a completely custom donor flow, you already run a backend, and maintaining a webhook is not a burden. You will get a form that is exactly yours, at the cost of being the one who keeps it alive.

Pick the embed path if you want donations live today, you would rather not run a server for it, and you are happy to let receipts, records, and recurring be handled for you. For most static-site owners, even technical ones, the embed gets you 90 percent of the value for 10 percent of the upkeep.

Whichever you choose, test it the same way: load the live page, make a real $1 donation from your phone, confirm the money and the receipt land, then refund yourself. That single test catches more problems than any amount of staring at the code.

Frequently asked questions

Can I embed a Stripe donation form in plain HTML?

Yes, two ways. You can build it with Stripe.js plus a backend that creates a Checkout Session, or you can paste a hosted donation embed that runs on Stripe with no backend of your own. The embed is faster; the DIY route gives more control.

Do I need a backend to take Stripe donations?

For a custom build, yes. Creating a Checkout Session or Payment Intent and verifying payments with a webhook requires server-side code so your secret key stays off the client. A hosted embed removes that requirement entirely.

Is a bare Stripe Payment Link enough for donations?

It works and it is cheap on fees, but it sends donors to Stripe-hosted checkout with no branded form, no suggested amounts, and no donor records unless you build them. For a designed giving experience, most orgs want more than a raw Payment Link.

What does maintaining a custom Stripe donation form involve?

Keeping a backend or serverless function running, handling webhooks and retries, building branded receipts and donor records, managing recurring logic, protecting your secret key, and occasionally updating for Stripe API changes. It is real ongoing work, not a one-time setup.

Product links

Use the research, then choose the right donation setup.

Compare your options, then move into a donation setup your team can launch and maintain with confidence.

Related reading