Companion to the Digital Infrastructure & Growth Plan · By Clearoute
Salesforce migration — the full plan
How Every Pregnancy moves from HubSpot and a custom encrypted backend to one source of truth in Salesforce — partner data, donor data, giving history and reporting — in three dependency-ordered phases, without disrupting the live donation flow.
Draft Working statement of work, v1.0 · June 2026. All hour estimates are indicative and are confirmed once the pre-scoping questions are answered. Salesforce org provisioning & licensing sit with Every Pregnancy; this plan covers configuration & development.
The goal & the scope
Unify two competing data homes into one: partner/organisation data leaves HubSpot, donor data leaves the encrypted backend — both become Salesforce, the system of record. Every dashboard, the website and reporting then read from one place.
Crucially, "one source of truth" means Salesforce is the record + reporting brain — it does not mean every experience moves inside the CRM. The donation widget, the partner dashboard UI, and content authoring stay where they are and feed Salesforce or read from it. Seven components are in scope across three phases; the originally-scoped work is a draft 204–284 hours, with a donation-ingestion deliverable added by the decision below.
| Component | Phase | Est. hours | Status |
|---|---|---|---|
| Partner provisioning | Phase 1 | 24–32 | In scope |
| Donor management (nonprofit CRM) | Phase 1 | 60–80 | In scope |
| Offline donation approval workflow | Phase 1 | 24–32 | In scope |
| Donation ingestion (widget → Salesforce) | Phase 1 | TBD | Added by decision |
| Goal meter & boost algorithm | Phase 2 | 40–56 | In scope |
| Partner dashboard (data integration) | Phase 2 | 32–48 | In scope |
| WordPress API re-point | Phase 3 | 16–24 | In scope |
| Data decryption / CSV export utility | Phase 3 | 8–12 | Deprecate |
| Donation widget | — | — | Keep + integrate |
| BigQuery data pipeline | Evaluate | — | Pending review |
Draft Total for originally-scoped in-scope components: 204–284 hours. Donation ingestion is additive and scoped once the feed pattern is confirmed.
Decision applied — the donation widget stays
An earlier draft left the donation flow on hold pending evaluation of a third-party platform. That is resolved: the existing custom donation widget is retained and integrated with Salesforce — not replaced. This removes the highest-risk item from the migration and turns it into a clean data-feed (see Donation widget).
Salesforce is the brain; the platform stays the hands
Salesforce becomes the system of record and reporting. The donation widget, ep-server and Stripe keep running the live money flow and feed Salesforce via a batch/queue sync. The partner dashboard and public website read from Salesforce. Nothing in the payment path depends on Salesforce being up.
Feeding via ep-server (not widget-direct or per-webhook) protects the live money flow, reuses the existing Bull/Redis queue, and stays under platform-event limits.
The highest-confidence components — strongest native Salesforce fit, lowest execution risk, and prerequisites for everything that follows. Plus the donation-ingestion feed that keeps the donor CRM live.
Partner provisioning
24–32 hrsA HubSpot contact’s Approved field triggers a custom integration that provisions a dashboard login and welcome email — managed manually.
Partner orgs become Account records. A Flow triggers on approval, fires an Email Alert, and provisions an Experience Cloud user natively or calls an outbound webhook to the existing dashboard.
Deliverables: Account config · approval Flow · Email Alert template · outbound webhook (if dashboard retained) · deactivation flow.
Assumption: range reflects whether the existing dashboard is retained — full Experience Cloud adoption is near-entirely native (lower end).
Donor management — nonprofit CRM
60–80 hrsDonor data sits in an encrypted backend with no CRM layer; access needs a manual CSV decrypt. No reporting, lifecycle tracking, or tax receipts.
Salesforce’s nonprofit CRM as donor CRM — Contact records with full giving history, campaign & partner attribution, location, recurring support, duplicate detection. Tax receipts auto-generate on confirmation.
Deliverables: nonprofit-CRM install & config · donor schema · giving-history model · attribution · tax-receipt automation · duplicate rules · lifecycle segmentation · migration of existing encrypted records.
Assumption: lower end assumes a single tax jurisdiction and clean data; more jurisdictions, data remediation, and record volume move it upward.
Build on Nonprofit Cloud with dedicated Gift objects (not legacy NPSP, which isn’t offered to new orgs and models gifts on Opportunities). Same goal — different data model, migration and rollups. Correct the “install in a net-new org” assumption with the Salesforce partners.
Offline donation approval workflow
24–32 hrsPartners submit offline donations via the dashboard; an approval email with a link goes to the approver; approved amounts credit the partner total; receipt upload required.
Submission via Experience Cloud; Salesforce Approvals routes to the approver with approve/reject; receipt upload handled natively; on approval a Flow rolls up to the partner total. Full audit trail in standard reporting.
Deliverables: offline-donation object & records · Experience Cloud submission · Approval process with email routing · file-upload config · rollup Flow · per-partner / per-campaign reporting.
Assumption: single primary approver; delegated approvers or a reject-and-resubmit flow sit at the upper end.
Donation ingestion — widget → Salesforce added by decision
TBD · to scopeBecause the widget stays, live gifts are still born in the widget + Stripe + ep-server. Without a live feed, the donor CRM holds only migrated history that goes stale on the next donation.
Batch / queue sync — reuse the existing Bull/Redis queue, Bulk + Composite API, idempotent with catch-up; carry currency + Gift Aid per gift. Not a Salesforce call per Stripe webhook.
Deliverables (draft): ingestion job in ep-server · Salesforce inbound staging · idempotency, retry & catch-up · field mapping (amount, currency, attribution, recurring, Gift Aid) · reconciliation reporting.
Principle: Salesforce being down must never stop donations — the feed is asynchronous and reconciles.
These depend on Phase 1: the boost needs donation data already in Salesforce, and the dashboard re-point needs Salesforce confirmed as the system of record.
Goal meter & boost algorithm
40–56 hrsA Google Sheet is the calc engine — donations feed in, a person maintains the boost formula by hand, the dashboard pulls the output. The client has flagged this as a priority pain point to replace.
Per-partner totals as rollup summary fields on Accounts; boost logic in Flow (simple) or Apex (complex). Meter UI stays in the dashboard via REST, or becomes a Lightning Web Component if the dashboard moves to Experience Cloud.
Deliverables: rollup config for donation totals · boost in Flow or Apex · goal-meter data endpoint or LWC · updated downstream feed if boost data is used elsewhere.
Assumption — widest variance: a simple Flow formula ≈ 40 hrs; a multi-variable algorithm needing Apex ≈ 56+ hrs. The boost formula must be documented and shared before this estimate is confirmed.
The boost is cohort-competitive → stateful batch Apex, not a simple Flow; a real-time meter is hard natively. Multi-currency is real (donations carry a currency; 20+ countries) — decide the common-currency basis before designing rollups. The LWC / Experience Cloud rebuild is deferred unless the dashboard is retired into a Salesforce portal.
Partner dashboard — data integration
32–48 hrsA custom multi-tenant web app where partners manage their campaign presence, view their goal meter and donor activity; profile content also feeds the public website via API.
Phase 2 is data integration only — re-point the existing dashboard to Salesforce via REST. Salesforce becomes the system of record; the dashboard UI is preserved. A full UI migration into Experience Cloud is a future phase, not in this plan.
Deliverables: Salesforce REST config for partner data · dashboard re-point from custom backend to Salesforce · auth & access scoping · testing across partner and admin views.
Assumption: the dashboard exposes REST endpoints and the maintaining team is available; GraphQL or adapter work moves toward the upper end.
Keep content authoring in the dashboard (re-pointed to Salesforce) and add a read cache in front of the REST calls — store partner data in Salesforce, don’t migrate the authoring experience into Salesforce CMS (built for an org’s own authors, not 55+ partners self-managing profiles).
Low-effort items that become viable once Salesforce holds all partner and donor data. Done after the Phase 1 & 2 migrations are stable.
WordPress API re-point
16–24 hrsThe public site pulls partner-profile content from the custom backend API; dashboard-entered content appears on the site automatically.
WordPress calls Salesforce REST APIs for the same content — the pattern is unchanged, only the data source moves. If a WordPress rebuild is planned, fold this into that project.
Deliverables: SF REST endpoint config for public partner content · WordPress connector update · auth for public requests · end-to-end render testing on the live site.
Assumption: read-only from WordPress to Salesforce (add caching); any write-back use case is scoped separately.
Data decryption / CSV export utility Deprecate
8–12 hrsA utility that decrypts donor records from the encrypted backend and exports CSV — a workaround, and the only ad-hoc donor-data access today.
Once donor data is in Salesforce, this serves no purpose — export is handled by native reports, the scheduled export service, or the API. Formally decommission.
Deliverables: confirm all donor-data use cases are covered by Salesforce reporting · document existing export users & workflows · formal decommission.
Assumption: donor data is the only type through this utility; other record types add scoping.
Donation widget — kept and integrated
Was — on hold, highest risk
An earlier draft held the live donation flow pending a discovery session to evaluate a third-party donation platform. As a live production money flow, replacing it carried the highest execution risk of any component in the migration.
Now — retain & integrate resolved
The decision is made: the existing custom widget (Stripe, UK Gift Aid, recurring, multi-currency) stays in production. There is no risky replacement — only the Phase-1 donation-ingestion feed into Salesforce, the lower-risk path the analysis itself recommended.
Net effect: the migration’s biggest unknown is removed, the donor CRM stays live rather than going stale, and the “schedule a third-party discovery session” step drops out of the plan — replaced by scoping the ingestion feed.
Deferred & excluded
Experience Cloud portal
Migrating the dashboard UI into a Salesforce portal (with per-user licences) is a future phase — not needed while the existing dashboard is re-pointed to Salesforce data.
Donor marketing
Email marketing (Mailchimp today) consolidating into Salesforce Marketing Cloud Growth + Data Cloud is deferred to a later stage, once donor data is unified.
BigQuery pipeline evaluate
Its full scope wasn’t established in the walkthrough. Likely the same workaround as the decrypt utility — run a dependency audit; default to deprecate-or-downstream, and if kept, feed it from Salesforce.
Assumptions & exclusions
- Salesforce org provisioning & licensing are Every Pregnancy’s responsibility; this plan covers configuration & development.
- The nonprofit CRM is installed in a net-new / clean org (confirm Nonprofit Cloud vs legacy NPSP before finalising).
- A Salesforce-certified sandbox is available for dev/test before production deployment.
- The team maintaining the existing partner dashboard is available to support the Phase 2 integration.
- The backend / widget subject-matter expert (Fidil) is available to consult during Phases 1 & 2 — now especially for the donation-ingestion feed.
- Hour estimates exclude project management, status reporting, and documentation beyond handoff.
- UAT is Every Pregnancy’s responsibility; Clearoute supports & facilitates, but UAT hours are not included.
- This plan excludes work on the BigQuery pipeline (separate engagement). The donation widget is no longer excluded — it is integrated.
Next steps
Answer the pre-scoping questions
The ten questions in the accompanying pre-scoping document — estimates are confirmed or revised once responses are received.
Review & sign off on scope, phasing & exclusions
Align before work is scheduled, including the deferred items and the BigQuery review.
Scope the donation-ingestion feed
Confirm the widget / ep-server → Salesforce pattern (batch/queue), field mapping, and currency / Gift-Aid handling — replacing the former third-party discovery step.
Review the BigQuery data-engineering roadmap
A brief internal review of what the pipeline powers and who depends on it, before a retain / replace / deprecate recommendation.