Solution: BrightFuture Foundation
Work in Progress
This content is currently being reviewed for accuracy and will be updated soon.
Architecture Decisions
AD-1: Nonprofit Cloud Platform: Agentforce Nonprofit
Decision: Use Agentforce Nonprofit on Enterprise Edition, built on the current Nonprofit Cloud standard data model (Fundraising, Program Management, Volunteer Management). BrightFuture qualifies for 10 free Agentforce Nonprofit CRM licenses through the Power of Us program, which replaced the earlier free NPSP licenses in December 2025.
Rationale: Agentforce Nonprofit is the current Salesforce nonprofit platform and the successor to the legacy NPSP managed package. It provides a native standard object model for Fundraising (GiftCommitment, GiftTransaction, Gift Allocation), Program Management (Program, ProgramEngagement, BenefitAssignment), and Volunteer Management on the core platform. For a net-new implementation in 2026, Agentforce Nonprofit is the correct starting platform: Salesforce has consolidated nonprofit investment on the native data model, the partner ecosystem has shifted to Agentforce Nonprofit certifications, and Trailhead content is actively maintained for this platform. BrightFuture has a six-month Salesforce admin and no developer on staff, but the declarative configuration model makes it viable for a junior admin with implementation partner support.
Trade-offs: Agentforce Nonprofit uses a native standard object model that differs significantly from the legacy NPSP managed package. Community resources and older implementation guides still reference NPSP objects (Opportunity-as-gift, npe03__Recurring_Donation__c, GAU). The implementation partner must have current Nonprofit Cloud expertise on the new data model, not just legacy NPSP experience. Mitigate by selecting a Salesforce Certified Consulting Partner with a Nonprofit specialization and verifying recent Agentforce Nonprofit project references.
Alternatives rejected: Standard Sales Cloud without Agentforce Nonprofit; the donor-centric fundraising objects, program engagement model, and volunteer tracking built into Agentforce Nonprofit represent months of custom work to replicate on a bare Sales Cloud org. Not viable within budget or timeline. Legacy NPSP is no longer the recommended platform for new implementations; Salesforce has stopped investing in the managed package and the data model is not forward-compatible with the native Nonprofit Cloud objects.
AD-2: Integration Platform: Salesforce-Native Flows with Apex REST Handler for Stripe
Decision: Stripe webhooks are received by an Apex REST endpoint deployed and maintained by the implementation partner. Mailchimp sync is handled by Mailchimp for Salesforce (an AppExchange managed package published by Beaufort 12, starting at $25/month per Salesforce org).
Rationale: No in-house developer means any Apex must be written by the partner and must be minimal in scope. A small Apex REST handler class for Stripe is the documented Salesforce pattern for receiving webhooks and requires no third-party middleware. A middleware platform (MuleSoft, Boomi) would add $15,000-$40,000 per year in licensing and require admin-level knowledge to maintain; not justified at BrightFuture’s scale or budget.
Mailchimp for Salesforce (an AppExchange managed package published by Beaufort 12) handles both the outbound audience push and the inbound unsubscribe/bounce sync without custom code. It runs on a configurable schedule (minimum 15-minute intervals), which satisfies the 24-hour unsubscribe sync requirement. At $25/month ($300/year), it is a minor budget line item compared to the middleware alternative.
Trade-offs: The Apex handler is a code dependency. If BrightFuture loses its implementation partner relationship, changes to Stripe’s API schema could break the integration. Mitigate by adding integration error records and alerting so failures are caught within minutes. Document the handler thoroughly.
AD-3: Program Management: Custom Objects on Core Salesforce
Decision: Build program enrollment and attendance on custom objects within the Agentforce Nonprofit org rather than adopting the bundled Program Management capabilities.
Rationale: Agentforce Nonprofit includes Program Management features (formerly the Program Management Module). However, the bundled program model uses a Service Delivery object model that maps well to social services but is a less natural fit for school-year enrollment with attendance rosters. Given the site-coordinator access control requirement (coordinators see only their site’s data), a custom object model with a Site lookup gives cleaner sharing rule granularity than the standard Service Program model. Budget permits the custom build, and the admin can maintain standard objects more easily than adapting the bundled program model to a non-standard use case.
Trade-offs: Custom program objects sit outside the Agentforce Nonprofit managed package. Future platform upgrades to program management features will not automatically benefit the custom objects. Document object relationships clearly to simplify any future re-mapping.
AD-4: Deduplication: Pre-Migration Matching, No Real-Time Merge Automation
Decision: All deduplication work happens in a pre-migration staging environment using a combination of Cloudingo (or similar data quality tool) and manual review for the fuzzy-match cases. Real-time duplicate prevention in Salesforce uses standard Duplicate Rules with the Salesforce default matching rules; no custom code.
Rationale: With 28,000 contact records across three source systems and no shared unique identifier, automated merge logic in a live org is high risk. A staging environment lets the implementation partner run matching algorithms (exact email match, fuzzy name match, phone match) and produce a conflict report for staff review before a single record goes into production. Cloudingo costs approximately $3,000-$5,000 for a one-time migration project and is widely used in nonprofit Salesforce implementations.
System Landscape
Data Model
Constituent Model (Agentforce Nonprofit Household Account)
Agentforce Nonprofit uses a Household Account model: every individual Contact is associated with a Household Account. This is different from standard Salesforce, where a Contact belongs to a business Account. In Agentforce Nonprofit:
- Household Account: auto-created per household. Stores address, giving totals, and household name. Soft credits for household joint gifts attach here.
- Contact; the individual. A person who is both a donor and a volunteer is one Contact record. Volunteer history and giving history both hang off the same Contact.
- Organization Account: used for corporate sponsors, foundations, and grant-making organizations.
- ContactContactRelation: the standard object that links a Contact to another Contact, Household, or Organization Account for corporate sponsor relationships, board affiliations, and staff-to-organization links.
Core Agentforce Nonprofit Objects for Giving
| Object | Purpose |
|---|---|
| GiftCommitment | Commitment to give: captures pledge, recurring donation, or one-time intent with amount, frequency, and schedule |
| GiftTransaction | Individual gift transaction: amount, status, transaction date, payment method, Stripe charge ID |
| GiftTransactionLineItem | Line-level detail on a transaction, including Gift Designations for earmarking to programs |
| GiftSoftCredit | Soft credits for matching gifts and joint household gifts |
| Gift Designation / Gift Allocation | Fund accounting: tags gifts to specific programs, campaigns, or funds |
Custom Objects for Volunteers
| Object | Purpose |
|---|---|
| Volunteer_Shift__c | Single shift definition: site, program type, date, capacity |
| Volunteer_Assignment__c | Junction: links Contact to Volunteer_Shift__c with attendance status |
| Volunteer_Hours_Log__c | Rolled-up hours per Contact per month for reporting |
Custom Objects for Programs
| Object | Purpose |
|---|---|
| Program_Site__c | Represents one of 18 physical sites (city, address, coordinator lookup) |
| Program__c | Tutoring, STEM Club, Arts: program type for a site and school year |
| Enrollment__c | Links Student_Contact__c to Program__c: status, enrollment date, school year |
| Attendance_Record__c | One record per student per session: date, present/absent flag |
| Student_Outcome__c | Pre/post assessment scores, completion flag, linked to Enrollment__c |
Donor/Volunteer/Family Overlap
A single Contact record carries all three roles via:
- Giving history through GiftCommitment (for pledges/recurring) and GiftTransaction (for individual gifts)
- Volunteer history through Volunteer_Assignment__c
- Family connection through a lookup on Enrollment__c (Student’s primary contact / guardian is a Contact, which may also be a donor Contact)
Household vs Individual Giving
In Agentforce Nonprofit, GiftTransactions are associated with the Household Account, with the primary donor Contact linked via a contact lookup. GiftSoftCredit records link additional Contacts to the same transaction (for example, a matching employer, or a spouse who co-gave). This is the standard Nonprofit Cloud pattern and must be respected throughout data migration.
Integration Architecture
Stripe: Event-Driven Webhook Pattern
Stripe is entirely event-driven. BrightFuture’s donation page is hosted externally and processes payments through Stripe. Salesforce must listen for Stripe’s webhook notifications.
Flow:
- Donor completes a gift on the donation page. Stripe processes the charge.
- Stripe fires an HTTPS POST to the Apex REST endpoint URL (
/services/apexrest/stripe/webhook). - The Apex handler verifies the Stripe webhook signature (using the signing secret, stored in a Custom Metadata record; not hardcoded).
- The handler parses the event type and enqueues a Queueable Apex job for processing (to keep the REST response fast and return HTTP 200 to Stripe within Stripe’s timeout window).
- The Queueable job:
- Looks up the Contact by the donor email in the event payload (case-insensitive SOQL query).
- If a match is found: creates a GiftTransaction linked to the matched Contact’s Household Account (and a GiftCommitment for subscription events).
- If no match: creates a new Contact record with
NeedsReview__c = trueand a staging GiftTransaction with a Pending Review status. An alert task is created for the admin queue. - Writes an Integration_Event_Log__c record regardless of outcome (event type, Stripe charge ID, email, match status, timestamp).
Stripe events handled:
| Stripe Event | Salesforce Action |
|---|---|
| payment_intent.succeeded | Create GiftTransaction with Status = Paid and link to Household Account |
| payment_intent.payment_failed | Create Integration_Event_Log__c with Failed status; create Task for admin |
| customer.subscription.created | Create GiftCommitment with Status = Active and recurring schedule |
| customer.subscription.deleted | Update GiftCommitment to Status = Closed |
| payment_method.updated | Update Payment Method on the GiftCommitment |
SLA: The 2-minute SLA (requirement 7) is met because Stripe fires the webhook within seconds of the charge and the Queueable job processes in the async queue. Under normal Salesforce org load, end-to-end time is under 30 seconds. The 2-minute clock starts when Stripe fires, not when the donor clicks submit.
Error handling: Stripe retries failed deliveries (HTTP non-200 responses) with exponential back-off over 3 days. The Apex handler always returns HTTP 200 on receipt (before processing) to prevent retry storms, then handles processing errors internally and writes to Integration_Event_Log__c.
Mailchimp: Scheduled Bidirectional Sync
Mailchimp is not event-driven for Salesforce’s purposes. Mailchimp for Salesforce (AppExchange managed package by Beaufort 12, starting at $25/month) uses a pull/push model on a scheduled interval.
Outbound (Salesforce to Mailchimp):
- Staff build a List View or Report of Contacts meeting campaign criteria.
- The Mailchimp connector maps Salesforce Contact fields to Mailchimp audience fields.
- Segment membership in Mailchimp can be driven by a Salesforce Report (one of the connector’s core features), eliminating the manual export step.
- Sync runs on a 15-minute schedule, or on-demand via a button on the Campaign record.
Inbound (Mailchimp to Salesforce):
- The connector polls Mailchimp for unsubscribe and hard bounce events on a scheduled interval (configurable to as low as 15 minutes, well within the 24-hour requirement).
- On unsubscribe: sets
HasOptedOutOfEmail = trueon the matching Contact. - On hard bounce: sets
Email_Bounce_Status__c = 'Hard Bounce'on the Contact (custom field) and also setsHasOptedOutOfEmail = trueto prevent future sends. - Unmatched Mailchimp subscribers (email not found in Salesforce) are written to Integration_Event_Log__c for admin review.
Error visibility: Both Stripe and Mailchimp write to the same Integration_Event_Log__c object. A Lightning Dashboard component on the admin home page shows open error records grouped by integration source, with links to resolve each one.
Security and Sharing Model
Organization-Wide Defaults
| Object | OWD | Reason |
|---|---|---|
| Contact / Account | Private | Donor records must not be visible across teams without explicit sharing |
| GiftTransaction / GiftCommitment | Private | Gift amounts are sensitive; development team only |
| Enrollment__c | Private | Student records contain minor data; site-scoped access required |
| Attendance_Record__c | Private | Rolls up from Enrollment; same restriction |
| Student_Outcome__c | Private | Assessment scores are sensitive |
| Volunteer_Shift__c | Public Read Only | Volunteers need to see available shifts |
| Volunteer_Assignment__c | Private | Only the coordinator and the assigned volunteer should see confirmed assignments |
| Program_Site__c | Public Read Only | Reference data; all staff need to see site list |
| Integration_Event_Log__c | Private | Admin team only |
Role Hierarchy
Executive Director├── Development Manager│ └── Development Staff (fundraising team)├── Programs Director│ ├── Seattle Site Coordinators (one role per city, or one per site)│ ├── Portland Site Coordinators│ └── Spokane Site Coordinators├── Operations / Admin└── Technology Team (system admin profile)Sharing Rules
- Development team sees all Contacts, GiftCommitments, and GiftTransactions (sharing rule: Role = Development Manager or subordinates, access = Read/Write on Contact, Read on GiftCommitment and GiftTransaction).
- Site coordinators see Enrollments and Attendance only for their assigned Program_Site__c records. Criteria-based sharing rules share records matching a field value with a specific public group; they do not dynamically compare against the current user. The implementation uses public groups per site (e.g., “Downtown Site Staff”) and a criteria-based sharing rule that shares Enrollment__c records where Site__c = “Downtown” with the “Downtown Site Staff” public group. Each site coordinator is a member of their site’s public group.
- Programs Director has a role above all site coordinator roles, granting rollup visibility across all sites without any extra sharing configuration.
- Volunteers are not Salesforce users; they interact with the public shift sign-up page only. No internal Salesforce licenses are consumed by volunteers.
Student Data Privacy
Student Contacts are a distinct record type from donor/volunteer Contacts. The Record_Type = Student filter is built into the sharing rules; volunteers (even if they are donor Contacts in Salesforce) have no profile access to the Student Contact record type. Development staff can see donor-linked family Contacts but not the student’s program records.
Minor Data Compliance
Student records contain information about children. BrightFuture should consult legal counsel on FERPA compliance and any applicable Washington, Oregon, or Idaho state data privacy laws before go-live. The sharing model described here creates the technical controls; the compliance review determines whether those controls are sufficient.
Migration Strategy
Source Systems and Volumes
| Source | Object | Records | Notes |
|---|---|---|---|
| Little Green Light | Contacts | 28,000 | 15% bad phone, 8% no email |
| Little Green Light | Gift records | 41,000 | 6 years of history |
| Little Green Light | Recurring gifts (as notes) | 800 | Requires structured conversion |
| VolunteerLocal | Volunteer contacts | 310 active | Subset overlaps LGL |
| VolunteerLocal | Shift records | 4,800/year | Load 2 years of history |
| VolunteerLocal | Hour logs | 9,200/year | Load 2 years of history |
| Google Sheets | Student enrollments | 2,400 active | Current school year + one prior |
| Google Sheets | Attendance records | ~18,000/month | Current school year only |
Deduplication Approach
Phase 1: Pre-migration staging (6 weeks before cutover):
- Export all three source systems to CSV.
- Load into a staging spreadsheet or Cloudingo staging environment.
- Run matching passes in priority order:
- Pass 1: Exact email match (catches most LGL/VolunteerLocal overlaps).
- Pass 2: Fuzzy name + zip code match (catches “Bob” vs. “Robert” with same address).
- Pass 3: Phone number match for records with no valid email.
- Produce a deduplication report: confirmed matches (auto-merge), probable matches (human review), unmatched (load as new).
Survivorship rules:
- Email: prefer LGL (donor system, more carefully maintained).
- Phone: prefer whichever record has a valid formatted phone.
- Name: prefer the more complete full name; flag “Bob” vs. “Robert” cases for staff confirmation.
- Address: prefer LGL.
- Volunteer hours: always preserve from VolunteerLocal; this data does not exist in LGL.
Phase 2: Structured data conversion:
- Recurring gift notes in LGL require manual review by the development team. Each of the 800 notes must be interpreted and mapped to amount, frequency, and next payment date before the migration load. Allocate 3 weeks for the development team to complete this review using a provided spreadsheet template.
Load Order
Data must be loaded in dependency order to satisfy lookup relationships:
- Program_Site__c records (reference data, no dependencies)
- Account records: Household Accounts and Organization Accounts
- Contact records (requires Account IDs from step 2)
- ContactContactRelation records (corporate/board/staff affiliations, requires Contact IDs)
- GiftCommitment records (recurring pledges, requires Contact + Account IDs)
- GiftTransaction records (individual gifts, requires Account + Contact IDs, optional GiftCommitment parent)
- GiftTransactionLineItem and Gift Designation records (requires GiftTransaction IDs)
- Volunteer_Shift__c records
- Volunteer_Assignment__c records (requires Contact + Shift IDs)
- Program__c records (requires Site IDs)
- Enrollment__c records (requires Contact + Program IDs)
- Attendance_Record__c records (requires Enrollment IDs)
- Student_Outcome__c records (requires Enrollment IDs)
Use Salesforce Data Loader or Dataloader.io for all loads. Agentforce Nonprofit rollup and automation processes should be paused during bulk loads and rerun from the Nonprofit Cloud settings page afterwards to prevent runaway recalculation during migration.
Cutover Constraints
- The end-of-year giving campaign runs November 15 through December 31.
- Go-live target is before the school year enrollment window (approximately 11 months from project start, roughly September).
- Target cutover window: late August, after the summer fundraising lull and before the enrollment window opens. This avoids the November-December blackout.
- For the Stripe integration specifically: run in parallel mode for 2 weeks pre-cutover. Stripe webhooks fire to both the old donation page processor and the new Salesforce endpoint. Compare records. Only decommission the old workflow once parity is confirmed.
Reporting Approach
All reports use native Salesforce Reports and Dashboards. No external BI tool is needed at BrightFuture’s data volume.
Executive Director dashboard (requirement 17): Four dashboard components on a single Lightning Dashboard: Summary Number for active donors (filter: GiftTransaction Transaction Date = this fiscal year, deduplicated by Contact); Summary Number for volunteer hours (filter: Volunteer_Hours_Log__c, current fiscal year); Summary Number for current student enrollments (filter: Enrollment__c status = Enrolled, school year = current); and a Gauge or Progress Bar chart for YTD funds raised against a manually entered Campaign target field.
Donor retention report (requirement 18): A joined report (or a Salesforce Report with cross-filter) showing Contacts who have a Paid GiftTransaction in the prior fiscal year but no Paid GiftTransaction in the current fiscal year, grouped by gift size range (using bucket columns: under $100, $100-$499, $500-$999, $1,000-$4,999, $5,000+). This is a standard Nonprofit Cloud lapsed donor pattern and does not require custom code.
Monthly site attendance summary (requirement 19): A custom Attendance Report Type (Contact + Enrollment + Attendance_Record) grouped by Program_Site__c, Program__c, and calendar month. A formula field on Enrollment__c calculates attendance rate as (present days / total session days). A dashboard filter lets the Programs Director drill by site. Site coordinators see only their site’s data due to sharing rules; the same report is safe to share with all coordinators.
Impact report by city (requirement 20): A cross-object impact view by city. Custom Report Types (CRTs) are built from one primary object plus related objects in a parent-child chain; a single CRT cannot join GiftTransaction, Enrollment, and Volunteer_Hours_Log as independent primaries. Use separate CRTs for each reporting domain (e.g., GiftTransaction + Account for fundraising by city; Enrollment + Program_Site__c for students served by city; Volunteer_Hours_Log + Program_Site__c for hours by city), or use CRM Analytics to join these datasets in a single lens. For a budget-conscious implementation without CRM Analytics, the three separate reports can be combined in a multi-component dashboard filtered by city.
Grant reporting (requirement 21): Each grant is tracked as a GiftCommitment with a Grant record type, associated to the funder’s Organization Account, and fulfilled by one or more GiftTransactions. Gift Designations on those transactions tag the funded programs. A grant reporting template (saved report) filters Enrollment and Attendance records by the programs tagged on the grant’s designations, making it possible for staff to run a quarterly grant report without customization per funder.
Volunteer impact export (requirement 22): Volunteer_Hours_Log__c rolls up hours by Contact, Site, and Program_Type__c (a picklist on Volunteer_Shift__c). A Report Export to CSV handles employer matching documentation. For formal letters, a Salesforce Document Generation tool (Conga Composer or DocGen, both available on AppExchange) generates a PDF volunteer hour summary letter. This is a light implementation effort and within budget.
Requirements Addressed
| # | Requirement | Solution |
|---|---|---|
| 1 | Unified constituent model | Agentforce Nonprofit Household Account + Contact model; all constituent types as one Contact with record type differentiation |
| 2 | Single record for donor-volunteer overlap | One Contact record; GiftTransaction for giving history, Volunteer_Assignment__c for shift history |
| 3 | Deduplication with name variations | Pre-migration staged deduplication: exact email, fuzzy name+zip, phone match; manual review for edge cases |
| 4 | Complete history post-migration | Full load of LGL gifts, VolunteerLocal shifts/hours, and Google Sheets enrollments per load order |
| 5 | Recurring gifts as structured records | Structured conversion of LGL notes to GiftCommitment with amount, frequency, next payment date, payment method type |
| 6 | Soft credits for matching gifts and household | GiftSoftCredit records on GiftTransaction; standard Nonprofit Cloud feature, no custom build required |
| 7 | Stripe webhook: gift created within 2 minutes | Apex REST endpoint + Queueable Apex; webhook receipt to record creation typically under 30 seconds |
| 8 | All five Stripe event types handled | payment_intent.succeeded, payment_intent.payment_failed, customer.subscription.created, customer.subscription.deleted, payment_method.updated; all handled in Apex event router |
| 9 | Match on email or create new with review flag | SOQL lookup by email in Queueable job; no match creates Contact with NeedsReview__c flag and admin Task |
| 10 | Mailchimp segments driven from Salesforce | Mailchimp for Salesforce (AppExchange managed package by Beaufort 12, $25/month); Salesforce Report drives Mailchimp audience segment; no manual export |
| 11 | Unsubscribe/bounce back to Salesforce within 24 hours | Mailchimp for Salesforce package polls on 15-minute schedule; sets HasOptedOutOfEmail and bounce status field |
| 12 | Integration errors in one place | Integration_Event_Log__c custom object; dashboard component on admin home page showing all open errors by source |
| 13 | Program enrollment in Salesforce | Enrollment__c custom object linking Contact, Program__c, Program_Site__c, school year, and status |
| 14 | Attendance with site-scoped coordinator access | Attendance_Record__c per student per session; criteria-based sharing rules restrict coordinators to own site |
| 15 | Outcome tracking with pre/post scores | Student_Outcome__c linked to Enrollment__c; fields for pre/post reading level scores, attendance rate formula, completion flag |
| 16 | Programs Director consolidated view | Role hierarchy position above all site coordinator roles provides rollup visibility; single report covers all 18 sites |
| 17 | Executive Director one-view dashboard | Four-component Lightning Dashboard: active donors, volunteer hours, enrolled students, YTD funds vs. target |
| 18 | Lapsed donor retention report | Cross-filter report: Contacts with prior-year Paid GiftTransaction, no current-year Paid GiftTransaction; bucketed by gift size |
| 19 | Monthly attendance by site with drill-down | Custom report type with attendance rate formula; sharing rules make it safe to deploy to all coordinators |
| 20 | Impact by city | Separate CRTs per domain (GiftTransaction, Enrollment, Volunteer_Hours_Log) filtered by city field on Program_Site__c; combined in a multi-component dashboard, or CRM Analytics for true cross-object joins |
| 21 | Grant reporting without per-funder custom dev | Gift Designations on the grant’s GiftTransactions tag funded programs; saved report template filters by designation for any grant funder |
| 22 | Volunteer impact export for documentation | Volunteer_Hours_Log__c report export to CSV; optional Conga/DocGen for PDF letter generation |
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Recurring gift note conversion takes longer than planned | High | Medium | Allocate full 3 weeks; bring implementation partner in for a data conversion workshop with the development team in month 2 |
| No developer on staff (Apex webhook handler becomes unmaintainable) | Medium | High | Thoroughly document the handler; include a maintenance retainer with the implementation partner contract; monitor Integration_Event_Log__c proactively |
| Deduplication edge cases delay migration | Medium | High | Run staging dedup 8 weeks before cutover (not 6); set a cutoff rule; records with no confident match are loaded as new and flagged for post-migration cleanup |
| Cutover timing conflicts with enrollment window | Low | High | Hard constraint: complete enrollment module go-live by week 36 of the 14-month project; if slipping, descope outcome tracking (requirement 15) to phase 2 |
Domain Scoring Notes
Integration Domain Probes
The review board will probe integration decisions heavily because the two integrations have different patterns and the candidate must demonstrate they understand why.
- Stripe is push (event-driven). Salesforce cannot poll Stripe for new transactions; it must receive webhook events. The key design decisions are: how you secure the endpoint (signature verification), how you handle Stripe’s retry behavior, and what happens when no matching contact exists.
- Mailchimp is pull/push on schedule. Salesforce cannot receive Mailchimp events in real time; the connector polls. The key design decision is the polling interval and what happens on a failed sync (retry queue, error log).
- Error handling is a first-class concern. Any answer that does not address what happens when an integration fails will lose marks. The Integration_Event_Log__c pattern with an admin dashboard component is the minimum expected answer.
Data Domain Probes
- The board will ask about the constituent model choice and expect a crisp rationale with trade-offs, not just “it’s easier.”
- Deduplication must not be treated as a migration task only. Post-migration, what prevents new duplicates from entering the system? Answer: Salesforce Duplicate Rules with a configured Standard Matching Rule using Email as the primary match key, supplemented by custom matching rules for Name + Zip fuzzy matching.
- The recurring gift conversion from unstructured notes is a data quality problem, not a migration problem. The board expects a plan for staff involvement in the conversion, not just a technical mapping.
What Would Fail
Anti-pattern 1: Using a middleware platform to receive Stripe webhooks. Adding MuleSoft Anypoint or a similar iPaaS for a single webhook endpoint adds $15,000+ per year in licensing, introduces a new system for a four-person tech team to maintain, and is architecturally disproportionate. The board would view this as over-engineering given the stated budget and staffing constraints.
Anti-pattern 2: Relying on scheduled data exports from the existing systems during migration. LGL has no API on the current tier; VolunteerLocal has no webhook or API on the current tier. Any migration architecture that assumes API access from these systems will fail. The only exit path is CSV export. A candidate who designs an API-based migration without checking the system constraints has missed a key fact in the scenario.
Anti-pattern 3: Giving site coordinators Public Read/Write on Enrollment__c and relying on honor-system data access. Student records are records about minors. An OWD of Public Read/Write on enrollment data, even with training, is not an acceptable design for a CTA review board. The scenario explicitly states that coordinators must not see other sites’ data, and the implicit requirement calls out minor data privacy. Private OWD with criteria-based sharing rules is the correct answer.
Scoring Rubric
| Criterion | Weight | What Strong Looks Like |
|---|---|---|
| Constituent data model | 20% | Agentforce Nonprofit Household Account model explained correctly; donor/volunteer overlap handled via single Contact; soft credits addressed |
| Integration architecture | 25% | Stripe and Mailchimp treated with different patterns; error handling and the unmatched-email case explicitly addressed; 2-minute SLA explained mechanically |
| Migration and deduplication | 20% | Three-source deduplication with matching passes explained; survivorship rules defined; load order correct; recurring gift conversion acknowledged as a staff work item |
| Security and access model | 20% | OWDs and sharing rules correctly set; student/minor data explicitly protected; volunteer access (no internal licenses) addressed |
| Reporting and impact measurement | 15% | All four reporting requirements addressed; grant reporting explained without requiring per-funder customization; no BI tool needed at this scale |
Self-Assessment Checklist
- Did I explain the Agentforce Nonprofit platform choice with trade-offs, or just say which one I picked?
- Did I address what happens when a Stripe webhook arrives for an email that has no matching Contact?
- Did I give Stripe and Mailchimp different integration patterns and explain why?
- Did I include student/minor data privacy as an explicit design concern in the sharing model?
- Did I plan for recurring gift conversion as a staff effort, not just a technical mapping?
- Did I define survivorship rules for deduplication, not just say “we’ll deduplicate”?
- Did I explain how grant reporting works for any funder without requiring custom development per funder?
- Did I show that all 22 requirements map to a specific design decision?
Q&A Prep
Q: Why Agentforce Nonprofit rather than building on standard Sales Cloud or using the legacy NPSP? A: Agentforce Nonprofit is the current Salesforce nonprofit platform and the only one receiving active investment. It provides native standard objects for fundraising (GiftCommitment, GiftTransaction, Gift Designation), program management, and volunteer management. Building these on bare Sales Cloud would take months of custom work outside this budget. Legacy NPSP is no longer the recommended starting point for new implementations; the native data model is forward-compatible and has the active Trailhead documentation, active partner certifications, and free CRM licenses through Power of Us.
Q: A Stripe webhook arrives with a donor email that is not in Salesforce. Walk me through exactly what happens. A: The Queueable job runs the SOQL query, finds no match, creates a new Contact with record type Individual and sets a NeedsReview__c checkbox to true. It creates a staging GiftTransaction with Status = Pending Review linked to the new Contact’s Household Account. It writes a record to Integration_Event_Log__c with status “Unmatched - New Contact Created.” It creates a Task assigned to the admin queue with subject “Review new Stripe donor contact.” The admin reviews, either merges with an existing record or confirms it as a new donor, and moves the GiftTransaction status to Paid.
Q: How does Mailchimp unsubscribe sync work if the Mailchimp connector polls every 15 minutes but Salesforce only has the 24-hour SLA? A: The 15-minute polling interval gives a comfortable margin inside the 24-hour requirement. The connector checks Mailchimp’s activity feed for unsubscribe and bounce events since the last poll timestamp, then updates the matching Salesforce Contact. If a poll fails, the connector logs the error and retries on the next cycle. The Integration_Event_Log__c catches persistent failures for admin attention.
Q: How do you prevent new duplicates from entering the org after migration? A: Standard Salesforce Duplicate Rules with a configured Standard Matching Rule using Email as the primary match key, supplemented by custom matching rules for Name + Zip fuzzy matching. The out-of-the-box standard matching rule on Email + First Name + Last Name is a starting point, but the custom fuzzy-name rule is needed to catch “Bob” vs. “Robert” variations at the same zip code. For donor-facing entry (Stripe webhook creates new contacts), the Apex handler always queries by email before creating a new record. For manual entry, Duplicate Rules surface a warning (or block, depending on the rule setting) if a rep tries to create a Contact that closely matches an existing one.
Q: Site coordinators are not technical users. How does attendance recording work for them? A: A simple Lightning page with a filtered list view of their site’s Enrollment records and an inline edit option on a custom Attendance_Record__c quick action. The sharing rules limit what they see automatically; they do not need to filter by site; their view only shows their records. Onboarding is under two hours because the workflow is: open the list, click the student’s name, click “Record Attendance,” select present or absent, save. No reports, no configuration.
Q: What happens if the implementation runs over budget? A: The scenario states no contingency. The architecture is designed to avoid this: Agentforce Nonprofit, Mailchimp for Salesforce ($25/month AppExchange managed package), and minimal Apex reduce implementation hours. If a risk materializes, the first thing to descope is Student_Outcome__c (requirement 15); pre/post assessment scores are valuable but not critical to go-live. That can launch as a phase 2 after the enrollment window opens. Volunteer impact PDF letters (requirement 22) could also move to phase 2.
Q: Why not use Salesforce Experience Cloud for volunteer shift sign-ups? A: Experience Cloud would require additional licenses (Partner or Customer Community licenses for ~310 active volunteers), adding cost. The existing VolunteerLocal sign-up workflow can be kept in place as the public-facing volunteer portal post-migration, with only the back-end hour data migrated into Salesforce. Alternatively, a public-facing Salesforce Site (free, no license per volunteer) with a Web-to-Object form handles shift sign-ups without Community licenses.
Q: The development manager says the Mailchimp export currently takes two hours per campaign. How does your solution eliminate that? A: The Mailchimp for Salesforce package maps a Salesforce Report directly to a Mailchimp audience segment. When Rosa’s team needs to send a campaign, they build a Contact report in Salesforce with their criteria, save it, and map it in the package settings. The package syncs the segment on schedule. No export, no format conversion, no two-hour manual step. The only manual action is setting up the Report-to-Segment mapping the first time, which takes about 20 minutes.
Q: Can you walk me through the migration cutover sequence for the donation workflow? A: Three phases. In the month before cutover, the new Stripe webhook endpoint is deployed to production and tested in a sandbox with Stripe test events. Two weeks before cutover, parallel mode begins: the old LGL donation entry continues in parallel with the new Salesforce endpoint. Both receive events; staff reconcile daily to confirm parity. One week before cutover, the development team does a final data load of LGL gift records through the day prior. On cutover day (targeting late August), the LGL donation workflow is deactivated and the Salesforce endpoint becomes the sole path. The old system stays in read-only mode for 60 days as a backstop.
Q: How do you handle Agentforce Nonprofit automation behavior during bulk data loads? A: Nonprofit Cloud provides settings to pause roll-up calculations and automation during bulk operations. Before each load phase, the admin suspends the Fundraising automations and rollups from Nonprofit Cloud settings. After the load, the admin runs the batch recalculation jobs from the same settings page. This is standard nonprofit platform migration practice and the implementation partner would own this step.
Q: How does the Programs Director see all 18 sites without manually combining data? A: The role hierarchy places the Programs Director above all site coordinator roles. Because Enrollment__c OWD is Private, records owned by site coordinator users are visible to the Programs Director via role hierarchy rollup. The consolidated view is a Salesforce Report filtered to the current school year with no site filter; the role hierarchy makes all records visible automatically. No sharing rules, no manual export.
Presentation Notes
Diagram Order
Present in this sequence to build the story logically:
- System landscape diagram: establish current state (three disconnected tools) and target state (single Salesforce org with two live integrations). Set the context in 90 seconds.
- Data model: walk the constituent model (Agentforce Nonprofit Household Account), then volunteer objects, then program objects. Emphasize that one Contact holds all roles. 4-5 minutes.
- Integration architecture: Stripe webhook flow end-to-end, then Mailchimp sync. Call out that they are different patterns. 5-6 minutes.
- Security and sharing model: OWD table plus role hierarchy sketch. Call out student/minor data explicitly; the board will probe this. 3-4 minutes.
- Migration strategy: three-source deduplication, load order, cutover window. Reference the November-December blackout explicitly to show you read the constraints. 4-5 minutes.
- Reporting: cover the executive dashboard, lapsed donor report, and grant reporting approach. 3-4 minutes.
Time Allocation (30-minute presentation)
- System landscape: 2 minutes
- Data model: 5 minutes
- Integration architecture: 7 minutes
- Security model: 4 minutes
- Migration strategy: 6 minutes
- Reporting: 4 minutes
- Wrap-up and assumptions stated: 2 minutes
Talking Points to Emphasize
- The implicit requirement you caught on minor data privacy (board expects unprompted identification).
- Why Stripe and Mailchimp need different patterns; this is the core integration design point.
- The recurring gift note conversion is a staff effort, not just a technical task; shows operational awareness.
- The cutover window choice (late August) is driven by two explicit constraints in the scenario: enrollment window opens in 11 months, November-December blackout. Naming these shows you read carefully.
- Agentforce Nonprofit platform choice: explain why it is the correct starting platform for a new nonprofit implementation in 2026, and how the free CRM licenses through Power of Us reduce cost.
Always verify against official Salesforce documentation
This content is study material for CTA exam preparation. Content compiled and presented with AI assistance. Not affiliated with Salesforce.
Personal study notes for the Salesforce CTA exam. Content compiled from VJ's study notes, official Salesforce documentation, community sources, and online publicly available content, then organized and presented with AI assistance. Not affiliated with Salesforce. © 2025–2026 VJ Srivastava.