Skip to content

Core Concepts

Settings & integrations#

Configuration is deliberately split across three tiers by how often it changes and how sensitive it is — not thrown into one catch-all object.

The three tiers#

Tier Storage Editable by Holds
1 Settings__c (Hierarchy Custom Setting) Admins, at runtime, from the Settings console Everything an admin should be able to tune without a deploy — retry counts, grace periods, feature toggles, thank-you copy
2 Packaged code and metadata — PaymentGatewayRegistry (Apex), Theme_Token__mdt (Custom Metadata Type) Nobody in the subscriber org; changes only via package upgrade Facts about what the package itself ships — which class implements which processor, which theme tokens a page design may override
3 External + Named Credentials, built by hand in Setup — the package ships none and creates none Admins, in Setup only; never through custom Apex or a custom field Secrets — API keys, tokens

This split matters because it maps directly to who can safely change what: a fundraising admin should be able to change the recurring retry count without a code deploy, but should never be able to (or need to) directly edit which Apex class handles Stripe calls, and a secret key should never be readable through a SOQL query or a debug log.

Settings__c in practice#

Settings__c is a Hierarchy Custom Setting, which means it supports org-wide defaults with optional profile- or user-level overrides, though in practice nearly everything is configured at the org-default level through the Settings console. It covers refunds, recurring/dunning behavior, event defaults, logging verbosity, Experience Cloud/embed toggles, donor portal copy, and organization display defaults — see the Settings data model reference for the complete field list.

Two of its fields describe your payment processor rather than your fundraising: Fee Coverage Percent and Fee Coverage Fixed hold the rate used to gross up a gift when a donor chooses to cover processing fees. Both are optional — blank falls back to the US card standard (2.9% + $0.30) — and neither has any effect until a campaign opts in. See Donations & payments.

SettingsService is the typed accessor every Apex class reads through — application code never queries Settings__c directly, so a field rename or a new default only has to change in one place.

Reading what the logger wrote — the Diagnostic Logs tab#

Logging verbosity is a setting; reading the logs is not. Diagnostic Logs in the app navigation lists the most recent entries the package wrote about its own behaviour — newest first, capped at 200, and the page says so rather than presenting a truncated list as the whole story. The Logging panel in the Settings console still decides what gets recorded. This tab is where you read it, and it deliberately sits outside that console: troubleshooting happens repeatedly, during an incident, and often by someone who has no business changing the org's settings on the way past.

The part worth understanding is what an empty list means, because on its own it means nothing. The page reads both logging settings back and says which case you are in: if Log level is Off nothing is being written at all, and a banner says so; at the Error default the info or debug entry you are hunting for was never recorded; and because the nightly retention job deletes by age, an incident from last quarter can be gone rather than absent. Only once none of those apply does an empty list actually mean the org is clean — and that is the one reading a log viewer must never get wrong.

Who sees it follows from who can already read the underlying records. Log__c is Private, and AppLogger writes each entry as whoever ran the transaction, so the tab is granted to Fundraising_Admin and Fundraising_ReadOnly — the two sets holding View All on the object — and deliberately not to Fundraising_User, which would see only its own sessions and read that partial list as an all-clear.

See Monitor donations and read the logs for the filters and a worked sequence.

The payment gateway registry#

PaymentGatewayRegistry exists so a second payment processor could be added later without touching the donation pipeline: it maps a processor to the class implementing IPaymentGateway, the API version to call, and the shape of credential that processor needs. PaymentGatewayFactory.getByAccount() is the one place that resolves a Payment_Account__c to its gateway implementation — nothing else in the codebase branches on the processor. Today, Stripe (StripeGateway) is the only registered implementation.

The registry is Apex rather than custom metadata, which is why tier 2 above is described as "packaged code and metadata" rather than "custom metadata". It used to be a CMDT (Payment_Gateway__mdt, removed August 2026), and that was the wrong tier for it: every value in it named something the package itself ships, so no subscriber could ever meaningfully change one — being data bought no flexibility and cost a compile-time check. The rule of thumb it produced: if an admin may need to change it between upgrades it belongs in tier 1; if every value names a part of the package, it belongs in code.

NPSP, detected not required#

Pledgivo works in any org, with or without the Nonprofit Success Pack installed. If NPSP is present, NpspSyncService optionally mirrors recurring donations to npe03__Recurring_Donation__c and fund designations to NPSP's GAU Allocations — each gated by its own Settings__c toggle, both off by default. See NPSP →.

  • Setup assistant


    A tour of every Settings console panel.

    Read more →

  • Settings console reference


    What every setting does, and behavior on update.

    Read more →

  • Settings fields


    Complete field-level reference for Settings__c.

    Data model →

  • Stripe integration


    How IPaymentGateway and PaymentGatewayRegistry fit together.

    Read more →