Getting Started
Set up your Experience Cloud site#
Public donation pages, the donor portal, and event tickets all run on an Experience Cloud (Enhanced LWR) site. Pledgivo ships every component that goes *on* that site — it doesn't create the site itself. That's a one-time manual setup you do in Salesforce Setup, not something the package installs for you.
Internal-only orgs can skip this
If you're only recording gifts staff take over the phone and never publishing a public donation page, you don't need Experience Cloud at all — skip ahead to Setup assistant.
Watch it first#
What it is. Seven and a half minutes building the site this package’s public pages run on — enabling Digital Experiences, creating and selecting the site, opening it to guests, assigning the guest permission set, granting Campaign read by hand, then publishing and activating. The last two chapters are the payoff and the catch: what an anonymous visitor actually gets on each public route, and the one checklist row the panel cannot fully verify for you.
Before you start#
Confirm your org edition supports Experience Cloud — Enterprise, Unlimited, Performance, or Developer. Professional edition can't publish public pages; see Installation.
1. Enable Digital Experiences#
Setup → Digital Experiences → Settings → Enable Digital Experiences.
Until you tick this, Digital Experiences does not appear in Setup at all — there is no All Sites list and nothing to create. Salesforce asks you to choose an Enhanced Domain subdomain as part of switching it on; that name becomes part of every public donation URL, is org-wide, and cannot be undone, so pick one you are happy to publish.
The Settings console's Site & Domain panel is a seven-step checklist that starts with this same step, machine-checks it against your org, and links you straight to the Setup page.
2. Create the site#
Setup → Digital Experiences → All Sites → New.
- Choose the Build Your Own (LWR) template.
- Name the site (e.g. "Giving" or your org's name). Salesforce derives the URL prefix from
this name — if it appends a suffix like
vforcesitebecause your preferred prefix was already reserved elsewhere, you can change it afterward under Experience Builder → Settings → URL & Access. - Click Create. Site creation runs as a background job and can take several minutes.
All Sites renders an empty pane
On some orgs the All Sites screen loads its shell — breadcrumb, heading — and then shows nothing at all: no site table, no New button. A hard reload does not fix it. It is the same blank-shell behaviour the Lightning Permission Sets page sometimes shows, and it has nothing to do with this package; it simply blocks the documented path.
Create the site from the CLI instead — it produces exactly the same site:
sf community create --name "Giving" --template-name "Build Your Own (LWR)" \
--url-path-prefix giving --target-org <your-org-alias>
Creation is asynchronous either way. Confirm it landed with:
sf data query --query "SELECT Name, Status, UrlPathPrefix FROM Network" --target-org <your-org-alias>
Read the prefix back rather than assuming it. Salesforce may return something other
than what you asked for — giving came back as givingvforcesite on a first-ever site in
a completely clean org, not only when the prefix was already taken. Never hardcode the
prefix anywhere; take it from that query.
Once the site exists, open the Settings console's Experience Cloud → Site & Domain panel, pick it in the Create or choose your site step, and click Use this site — that writes the site's address into Settings as the Experience Site URL.
This URL is the only source of every donor-portal link
The sign-in email, the "Manage your giving" links on the public pages, and the
link a staff member sends from a donor record are all built from this one value.
Until it is set, the public sign-in form accepts an email and sends nothing — the
reason is recorded in Diagnostic Logs — and the staff "Send portal link" action
is disabled with the same message. Paste the address of the LWR site (the one
ending in the URL prefix you chose, e.g. /fundraising), never the companion
Visualforce site that Salesforce creates alongside it.
3. Build the Donate page#
Campaigns, fundraiser pages, team pages, and event registration all share one page and
one component — Public Fundraising Experience. It reads the campaign's record type,
subtype, and URL slug to decide what to render, so you only build this once regardless of how
many campaign types you run.
- Open the site in Experience Builder.
- Pages → New Page → Standard → Flexible Layout.
- Name it (e.g. "Donate") and, in Page Properties, set its URL — e.g.
donate. - Drag the Public Fundraising Experience component into the content region and Save.
A campaign's public link then looks like https://<your-site-domain>/donate?slug=<the campaign's public URL>.
Component missing from the palette?
Publish the site and hard-refresh Experience Builder — a newly-installed component sometimes doesn't show up until the org's cache picks up the change.
The red warning on the component is Salesforce boilerplate
Experience Builder shows a red notice on every custom component from any managed package, warning that a third-party component may not be safe under Strict CSP or Lightning Web Security. It is generic text, shown before Salesforce has looked at the component at all — it is not a finding about this package. Every component this app ships is built and tested with Strict CSP and Lightning Web Security on, which is how the public pages are expected to run. Drag it in and carry on.
Built the Donate page at a URL other than donate?
Set Donation page path to match, in the Settings console: General → Organization &
Donations → Gift rules. The Campaign Gallery's donate links, the embed widget's checkout
handoff, and the Fundraisers console's public-links panel all build their URLs from this
setting — it defaults to /donate, so leaving it blank while your page lives somewhere else
silently breaks every one of those links with a 404. Leave it blank if you used the default
donate path above.
4. Build the other pages you need#
Each of these pages is independently optional, but other pages link to them by URL — using a different path than the one listed breaks that link with a 404. Build only the ones your rollout actually uses:
| Page | URL | Component | Needed for |
|---|---|---|---|
| Home | / |
Campaign Gallery | A public campaign directory — many sites already have a Home page, in which case just add the component to it |
| Thank you | thank-you |
Thank You | Event checkout — the buyer is sent here immediately after a successful charge |
| Receipt | receipt |
Donation Receipt | Anyone you email a receipt link to — build this if you send receipts at all |
| Donor portal | donor |
Donor Dashboard | The donor self-service portal, where returning donors sign in with an emailed code — see Publish a donor portal page |
| Tickets | tickets |
Event Tickets | Event ticketing. The Donor Dashboard links here on every event order — skipping this page breaks that link even if you don't otherwise use the Tickets page directly |
thank-you, receipt and tickets are fixed paths — build them exactly as written. donate
and donor are configurable in the Settings console under General → Organization & Donations
and General → Email & Receipts. The Site & Domain panel's Build each public page step
shows the paths your org is actually configured with, plus a live link to each page so you can
confirm it loads.
Build each the same way as the Donate page: New Page → Standard → Flexible Layout, set the URL in Page Properties, drag in the named component, Save.
Delete the template's placeholder from Home before you publish
"Build Your Own (LWR)" seeds the Home page with a stock HTML Editor component reading "Start Building Your Page — Drag and drop a component into the content slots." Dropping the Campaign Gallery onto Home does not replace it: the placeholder stays, sits above your gallery, and publishes to donors as the first thing they see. It is easy to miss because it looks like Builder chrome rather than page content.
It also cannot be selected by clicking it on the canvas the way a component you dropped can. Delete it through the rail instead:
- In Experience Builder, open Page Structure (the layers icon in the left toolbar).
- Expand the Home page's content region and select the HTML Editor entry.
- Click the delete (trash) icon and confirm the Delete component? dialog.
- Save, then publish.
Do this on every page you build from the template, not only Home — each new Flexible Layout page gets its own copy.
Replace the site's \"Invalid Page\" message
Every LWR site already has an Error page: the site shows it for any URL that matches no page, such as a mistyped campaign link, a removed page or an old bookmark. Out of the box it is one line of text reading "Invalid Page", with no way back into the site. The package ships a branded Page Not Found component to use in its place. Installing the package can't put it there for you, because Salesforce does not package site pages:
- In Experience Builder, open the page menu at the top and choose Error.
- Select the "Invalid Page" text on the canvas and delete it.
- Drag Page Not Found into the empty content region.
- Save, then publish.
The component links donors to your open fundraisers and to the donor portal. If your portal
page is not at donor, set Donor portal page path in the component's properties. Leave
that property blank to hide both portal links.
Thank you is not optional if you sell tickets
Event checkout navigates to thank-you right after the charge succeeds. An org that skipped
this page takes the buyer's money and lands them on a 404 — the failure happens after payment,
so nothing earlier in your testing catches it.
Remove the template's empty header and footer sections
"Build Your Own (LWR)" ships its theme layout with an empty Theme Header and an empty Theme Footer region, and each one still renders a layout section — which brings 16px of padding above and below itself. The result is a 32px grey band across the top and bottom of every public page: the donation page's trust bar starts a band's width down the window instead of meeting its top edge, and the contact footer floats off the bottom.
Nothing on the page itself causes it, so it survives every page-level change you make. Remove the two sections once and it is fixed for the whole site:
- In Experience Builder, open the Theme panel (the paintbrush icon) and confirm your pages use the Scoped Header and Footer layout.
- Open Page Structure (the layers icon) and expand the Theme Header region.
- Select its Section entry and delete it. Do the same in Theme Footer.
- Save, then publish.
Only do this while the regions are genuinely empty. If you later drop a real site header or footer into either region, the section comes back with it — and that spacing is then yours, not the template's.
5. Activate guest access#
Setup → Digital Experiences → All Sites, then click Workspaces next to your site → Builder → Settings → General. Enable Public Access — without it, every visitor gets a login page instead of your donation form, no matter what permission sets are assigned below. Salesforce exposes no API to read this toggle back, so you're confirming it yourself; the Site & Domain panel marks this step Can't verify for the same reason, not because anything is wrong.
Then assign Fundraising_GuestDonor to that site's guest user. Finding the guest user is
the awkward part, so follow this route exactly — you will come back to it twice more below:
- From that same Builder → Settings → General screen, click the link under Guest User Profile.
- On the profile, click View Users. Exactly one user is listed — "<your site> Site Guest User".
- Open that user → Permission Set Assignments → Edit Assignments → move
Fundraising Guest Donorfrom Available to Enabled → Save. This screen is a plain two-list picker with no filters on it; if you are instead creating a permission set for the guest user, the licence rule that applies there is in After you install.
Two routes that look right and are not: Administration → Members assigns profiles and permission sets that may be members of the site, not permission sets to the guest user; and the guest user does not appear under Setup → Users at all, nor in Manage Assignments on the permission set itself. Without this assignment, guest visitors can view campaign pages but the donation form cannot submit — see Installation.
Next, grant that Guest User Read on the standard Campaign object. Fundraisers are
Campaign records, and Salesforce does not let a managed package ship permissions on standard
objects — they are removed when the package version is built — so Fundraising_GuestDonor
carries every custom object and field grant your public pages need and can never carry this one.
Without it a visitor gets an error on every campaign, donation and ticket page.
Build it as a permission set — the same screen in every org, and the one figure gs-38 shows:
- Setup → Permission Sets → New. Label it Guest Campaign Read (any name works; this one
matches the screenshots). Leave License as
--None--— a set created under a specific user licence refuses to go onto a guest user, and the error does not mention the licence. - Object Settings → Campaigns → Edit → tick Read — and nothing else — → Save.
- Assign it from the guest user's own record, by the Guest User Profile → View Users route above: Permission Set Assignments → Edit Assignments → move Guest Campaign Read to Enabled → Save. Manage Assignments on the permission set does not list a site guest user.
A guest user must never hold Create, Edit or Delete on Campaign. If you have already built the donor credential set in Connecting Stripe, you may add this grant to that set instead of creating a second one; the Site & Domain check reads the grant, not the set. This one is machine-checked: the Site & Domain panel's Give the guest user read access to Campaign step reads the grant back and reports Done or Pending.
Finally, grant the public Stripe credential to that same Guest User — the same Builder →
Settings → General → Guest User Profile → View Users route as above. Salesforce does not let a
managed permission set grant access to an external credential principal, so this package can never
ship that grant — you create your own permission set (name it whatever you like) holding that
credential's principal and
assign it to the guest user as well as to your fundraising staff. Keep the admin credential's
grant on a separate permission set that the guest user is never assigned: it carries the full
secret key, so a guest user holding it can issue refunds. Unlike the Public Access toggle above,
this one is machine-checked: the un-numbered guest-credential row at the foot of the Site &
Domain panel reads the grant back via SetupEntityAccess and reports Done once a permission
set granting the donor credential's principal is assigned to the site's guest user, or Pending
with the specific reason (no grant found at all vs. granted but not assigned to this guest user)
otherwise. That row grades the
donor credential only — on the Payments panel, Let your public site use the credential names
the exact permission sets your guest user holds so you can confirm none of them is the admin one,
and Prove the donor key is restricted catches the same exposure from the other side by proving
the key a guest can reach cannot issue a refund. (Prove the admin key is restricted does the
same for the back-office key, which no guest can reach — that one is about limiting the blast radius
if the key ever leaks, not about guest exposure.)
Full walkthrough: Grant the Stripe credential.
6. Publish, then activate#
These are two separate actions on two separate screens, and you need both. Publishing without activating is the single most common reason a donation link 404s for donors while working perfectly for you.
Publish. Click Publish in Experience Builder (top-right). This is a separate step from saving your pages — nothing you build in Builder is visible to guest users until you publish.
Activate. Setup → Digital Experiences → All Sites → Workspaces beside your site →
Administration → Settings → Activate. Only this moves the site's status from
Preview (UnderConstruction) to Live.
Workspaces won't load? Activate from the CLI
On some orgs Experience Workspaces fails to initialise and never renders — a spinner, an Aura init error, or a blank pane. This compounds the empty All Sites list described in §2, because reaching the site through Workspaces is the documented way around that: when both fail there is no working UI route to activate at all. Neither is caused by this package, and neither produces an error message worth searching for.
There is no sf command that activates a site, but the Metadata API does it. Retrieve the
Network, flip its status, and deploy it back:
# 1. Retrieve the site's Network metadata (use the site NAME, not its URL prefix)
sf project retrieve start --metadata Network:Giving --target-org <your-org-alias>
# 2. Flip the status to Live (the file lands under force-app/main/default/networks/)
perl -pi -e 's{<status>UnderConstruction</status>}{<status>Live</status>}' \
force-app/main/default/networks/Giving.network-meta.xml
# 3. Deploy it back
sf project deploy start --metadata Network:Giving --target-org <your-org-alias>
Retrieve first rather than hand-writing the file — Network carries required fields whose
values are yours, and a hand-authored file will fail to deploy. Confirm it took:
Status reads Live when activation succeeded. Activating this way sends the same member
welcome emails the button does.
Publishing does not activate
Experience Builder will report Published with a live URL on a site the public still cannot reach. Builder has no Activate control at all — the button is in Workspaces, and the Settings console's Site & Domain and Get Started panels are both graded on the activation status, not on whether you have published. A successful publish leaves both rows amber until you activate.
Publish again after every future change
A metadata deploy alone does not update the live site — a package upgrade or a Settings change to page composition still needs an explicit Publish to go live. Hard-reload the page after publishing before you verify anything — a cached bundle can make a successful publish look like it didn't take effect. Activation, once done, stays done.
Next#
-
Connect the site in Settings
Point the Settings console at the site you just created.
-
Publish your first campaign
Design a donation page and go live.
-
Publish the donor portal
Give returning donors code sign-in access to their giving history.