Skip to content

Guides

Write a campaign story#

The story is the one block on a donation page a donor actually reads rather than scans. It has its own step in the Fundraisers console wizard and its own tab on the Campaign record page — the same toolbar in both, and a preview that renders it exactly the way the public page will.

Where it lives#

Open the Pledgivo app → Fundraisers tab → New (or edit an existing fundraiser), and go to the Story step — step 2, right after Type & basics. The same step also holds the hero image URL and the social share text, because all three are "what this campaign looks like to a donor".

The step writes the Campaign's Story field.

Or from the Campaign record page#

If you are already looking at the campaign record rather than the console, open its Story tab. It opens showing the story the way a donor sees it — the same renderer the public page uses — with a label telling you whether the story is currently published. Edit gives you the same toolbar, the same byte counter and the same rules described on this page, plus the Show this story on the public page switch, and Save puts you back into reading view.

The tab handles those two things and nothing else. The hero image and the social share text stay on the wizard's Story step and on the record's detail fields, because the tab saves only what it shows — which is exactly why it is safe to use on a campaign someone else is editing elsewhere.

Use whichever you are nearer to; they write the same field, run the same checks and produce the same result. What you should not do is edit the Story field directly — through the API, a list-view inline edit, or a data loader. Both the wizard and the Story tab put what you write through the same server-side clean-up before it is saved, and that clean-up is what stands between a pasted script tag and your public donation page. A raw field write skips it.

Everything below the toolbar is a plain text box. There is no rich-text editor, no font picker and no colour picker, and that is deliberate: the story's typography comes from the campaign's page design, so a story pasted with its own fonts and colours would fight the theme it lands in. What you control is structure — this is a heading, this is a quote, this is a list — and the design decides what each one looks like.

What each toolbar button does#

Put the cursor where you want the thing, or select the text you want to change, then click.

Button What it inserts What a donor sees
H2 ## at the start of the line A section heading
H3 ### at the start of the line A smaller subheading under an H2
B ** around the selection Bold text
I * around the selection Italic text
Link a popover asking for URL and link text A link that opens in a new tab
• List - at the start of the line A bulleted list
1. List 1. at the start of the line A numbered list
Quote > at the start of the line A pull quote, set apart in the design's quote font
Divider --- on its own line A horizontal rule between sections
Image a popover asking for image URL and caption A full-width image with the caption under it
Video a popover asking for a YouTube URL, a label, and an optional poster image A video block — see Video below

Nothing here is magic syntax you have to memorise. Type the story as plain paragraphs, separated by blank lines, and it renders correctly with no markup at all. The toolbar is for when you want more than paragraphs.

Use the preview

Show preview renders the story with the same component the public page uses — not an approximation of it, the same code. If it looks right in the preview, it is right on the page. Colours and fonts still come from the campaign's page design, so the preview shows structure and the live page shows structure in your theme.

The counter counts bytes#

The number under the box (811 / 131,072) is bytes, not characters. Accented letters and emoji cost more than one byte each, so a story of 130,000 emoji is over the limit while a character count would still read green. It turns amber past 90% and red over the limit, and a save over the limit is rejected with the same number you were looking at.

131,072 bytes is roughly 20,000 words of plain English. If you are near it, the problem is not the limit.

The full format#

If you would rather type than click, or you are pasting from somewhere else, this is everything the story format accepts. Anything not on this list is shown as the literal characters you typed — it is never silently dropped, and it never turns into something else.

Block level — each of these has to start at the beginning of a line:

## A section heading
### A subheading

A plain paragraph. Blank lines separate paragraphs.

> A pull quote. Consecutive quote lines join into one quote.

- A bullet
- Another bullet

1. A numbered item
2. Another one

---

![A caption for the image](https://example.org/photo.jpg)

@[Watch the two-minute tour](youtube:https://www.youtube.com/watch?v=XXXXXXXXXXX)

Inline — these work anywhere inside a paragraph, heading, quote or list item:

**bold**  *italic*  [link text](https://example.org)  [with a tooltip](https://example.org "Tooltip")

Escaping. To show one of the format's own characters literally, put a backslash in front of it: \* renders a plain asterisk. This works for * [ ] ( ) ! @ # > - and the backslash itself. The Bold and Italic buttons do this for you — if your selection contains an asterisk, they escape it so your text survives intact.

Things the format deliberately does not support#

  • Nested emphasis. Bold inside italic is one level only. An unclosed * stays a literal asterisk rather than swallowing the rest of the line.
  • Nested lists. One level. Indenting a bullet does not create a sub-list.
  • Tables, code blocks, footnotes, reference-style links ([text][label] and [label]: url). These render as the literal text you typed.
  • HTML. A <b> in a story is the four characters <b>, shown to the donor, not bold text. A story that still contains HTML from before this feature renders it as visible text — markup was never a supported input here, and the story field has always been a plain text field.

There is no upload button on the Story step, and the app stores no image or video files. Both the Image and Video buttons take a URL pointing at a file you host somewhere else — exactly the way the Hero image URL on the same step has always worked.

That means the host is your responsibility, and a dead host is a broken image on your donation page with nothing in Salesforce to tell you. Use something you control and that stays up: your own website, a CDN, a Salesforce Files public link, or the same place your hero images already live. Check the images on a campaign before you re-share its link to a new audience.

Image URLs must be https://

An http:// image address is refused, and the image block is dropped rather than rendered broken. This is not a preference — a browser blocks an insecure image on a secure page anyway, so accepting one would only produce a broken image that nobody can diagnose. The same rule applies to a video's optional poster image.

Links inside a paragraph may be https://, http:// or mailto:. A javascript: or data: address keeps the link text and quietly loses the destination.

Every link in a story opens in a new tab, so a donor reading your story never loses the donation form behind it.

Video#

Paste a normal YouTube address into the Video popover — a youtube.com/watch?v=… link, a youtu.be/… short link, or the bare video id. Give it a label (that is the caption, and it is what a screen reader announces), and optionally a poster image URL to show before it plays.

Out of the box, a video is a poster card, not a player. It shows your poster image — or the design's video backdrop colour if you did not give one — with a play button and your label, and clicking it opens the video on YouTube in a new tab. Nothing at all is loaded from YouTube until the donor clicks. That costs your page no third-party requests, no cookies, and no consent banner question, which is why it is the default.

Playing the video on the page instead#

If you would rather the video played in place, it takes two steps — a setting, and a one-time piece of org configuration you have to do yourself.

1. Turn the setting on. Settings → General → Organization & Donations → Story media → "Play story videos on the page".

2. Create the CSP Trusted Site. In Setup → Security → CSP Trusted Sites, click New and enter:

Field Value
Trusted Site Name anything you like — YouTube_Embeds is a good choice
Trusted Site URL https://www.youtube-nocookie.com
Active ticked
Context Experience Builder Sites
CSP Directives tick frame-src and nothing else

The setup panel prints these same values next to the toggle once you turn it on, so you do not have to come back here.

Why the app doesn't create this for you

Every trusted site a managed package ships shows up in the Approve Third-Party Access dialog every customer sees at install. This package keeps that list to the payment processor and nothing else, so a customer installing a fundraising app is asked to approve payments — not a video platform they may never use. The cost of that choice is this one manual step, for the orgs that want inline video.

Order matters in one direction only. The toggle without the trusted site gives you a blocked, empty frame rather than an error — the browser refuses the embed silently and no Salesforce API can tell the app whether you created the site, so nothing can warn you. If a video goes blank after you turn the setting on, the trusted site is what is missing. Turning the setting back off restores the poster card immediately.

Playback uses youtube-nocookie.com, YouTube's privacy-enhanced host, and the player loads lazily — it does not fetch until the donor scrolls it into view. The player occupies the same shape as the poster card, so the page does not jump when you switch the setting.

Story images need no trusted site at all. They load from wherever you host them, like the hero image.

Stories written before all this#

Nothing needs migrating. A story written as plain paragraphs, with or without a leading > for a quote, was already valid in this format and renders exactly as it did before — same paragraphs, same quote, picking up its campaign's fonts and colours.

The one thing to know is the HTML case above: if someone pasted markup into the field in the past, the tags are now visible as text. Open the story in the wizard, delete the tags, and use the toolbar buttons for the same effect.

  • Set up your first campaign


    The full walkthrough this step sits inside.

    Read more →

  • Post campaign updates and documents


    The other narrative surface on a public page.

    Read more →

  • Campaigns concept


    What a Campaign gains from the package, and how theming works.

    Read more →