Marketlinx DIGITAL
+44 7782 631 115 Ask about the DMS

Built by Marketlinx DIGITAL for C3 Consulting

The Donor Management System

Donor records, event imports, IRS-compliant tax receipts and a self-serve donor portal, synced to the nonprofit's HighLevel account. Built on one rule: nothing writes to the database until a human has reviewed it and signed.

See how it works Ask about a build like this

Running in production for C3 Consulting. Screens below are recreated from the live product.

Why nonprofits needed their own system

Nonprofits run on event exports from platforms like Greater Giving and OneCause, cheques in the post, and volunteers doing data entry. The commercial donor platforms price small organisations out, and generic CRMs don't understand tax deductibility, fair market value or receipt law.

The DMS was built around that reality. It imports what nonprofits actually have, catches the duplicates a spreadsheet never would, produces receipts the IRS will accept, and keeps the HighLevel account in step so communication runs from live giving data.

The system at a glance

  • Commissioned by C3 Consulting; in production with real donor data
  • Admin app: dashboard, donors, events, uploads, receipts, submissions, sync log
  • Donor portal: giving history, receipt downloads, missed-gift submissions
  • One-time-code login delivered through the nonprofit's own HighLevel channel
  • One-way sync of donor aggregates to HighLevel custom fields, every attempt logged
  • In-app help on every non-obvious screen, plus a public help centre

The admin home

A dashboard that never guesses

Every number on the dashboard reads from precomputed aggregates, so it loads in under a second and is never stale by more than one transaction. The header always names the connected HighLevel sub-account, so an admin can't bulk-operate on the wrong nonprofit by accident.

/dashboard
DMS Admin Dashboard Events Donors Upload Submissions Receipts Sync log

Dashboard · Example Nonprofit

Connected to GoHighLevel sub-account: Example Nonprofit (location-id)

Donors

73

Total raised (YTD)

$73,125

Events

9

Avg gift

$926

EventDateRaisedDonors
Annual Gala 20252025-04-29$73,12573
Spring Lunch 20262026-04-10$7002
Anniversary Gift 20262026-04-01$1,0001

Also on the real screen: three years of year-on-year giving, totals by transaction category, and donor tiers at $100 / $1k / $5k / $25k of lifetime giving.

Uploading data

Five stages between a CSV and the database

Whether an admin types in a single cheque or drops a 2,000-row event export, the data goes through the same pipeline. The single-entry form is literally wrapped into a one-row CSV behind the scenes, so duplicates are caught either way.

  1. STAGE 1

    Parse

    Headers normalised, money parsed, three date formats accepted, multi-date rows split. Banner rows from Greater Giving auto-skipped.

  2. STAGE 2

    Validate

    Required columns checked, transaction types validated, and every row must carry an identity: an email, a full name or a business name.

  3. STAGE 3

    In-batch dedup

    Rows inside the same file sharing a fingerprint of donor, event, type and amount are flagged as a group.

  4. STAGE 4

    Cross-batch dedup

    Rows matching a transaction already in the database are pre-flagged, so last month's import can't be counted twice.

  5. STAGE 5

    Confirm

    Every row, flag and match candidate shown to the admin, who signs before anything writes.

Header mapping

It reads event exports the way they arrive

Greater Giving, OneCause and BidPal all name their columns differently. Built-in presets translate the common exports automatically; anything else is mapped once in a dialog. One column can feed several fields (a single donor name split into first and last), and several columns can feed one (item name and detail concatenated into a description).

/upload · header mapping

Map your columns · example-event-2025.csv · 18 columns

All required fields are mapped. Click Continue to validate the rows.

Your columnSampleMaps to
bid_number423bid_number
donor_nameJane Smithfirst_name + last_name
split on whitespace
total_extended$1,500.00amount_paid
item_value$800.00fair_market_value
internal_refWK-001Ignore this column
Cancel Continue with this mapping

The confirmation screen

The most important screen in the product

Nothing writes until the admin ticks the authorisation, types a signature and clicks Confirm. Fuzzy matches above 85 per cent confidence default to merging with the existing donor; between 65 and 85 the system asks; duplicates from earlier imports default to being skipped. Every default can be overridden per row.

/upload?batch=b398f5db · confirmation

Confirm Import · example-event-2025.csv · Batch b398f5db

Valid rows

63

Row errors

2

To merge

11

To create

48

To drop

4

4 rows match existing transactions from a previous import. They are pre-selected to drop so nothing double-counts.

RowDonorEventPaidDecision
2John Smith
john.smith@example.com
Annual Gala 2025$500.00Create new donor
3Jane Smith
⚠ FMV ($800) exceeds amount paid ($750)
Annual Gala 2025$750.00Merge into Jane Smith (92%)
4Acme Corporation
Already imported 04/05/2026
Annual Gala 2025$5,000.00Skip (already imported)

☑ I confirm this data is accurate and I have authority to submit it.   Signature: A. Admin

Confirm and import

Flags under each donor catch what spreadsheets miss: fair market value exceeding the amount paid, organisation names typed into person fields, zero-amount pledges, unpaid transactions, donors with no email who can't reach the portal.

Wrong fuzzy match? Two John Smiths at the same nonprofit can match each other at 100 per cent. One click on the decision dropdown keeps their giving records separate.

On confirm, transactions write, donor aggregates recompute, and the HighLevel sync fires. Rejecting the batch discards every staged row and writes nothing.

Receipts

Tax receipts the IRS will accept

/receipts/WYK-2024-003

WYK-2024-003 draft

Jane Doe · Tax year 2024 · Total paid $250.00 · Deductible $175.00

Section 1 · Donations, fully deductible

2024-04-29General fund donation$150.00$150.00

Section 3 · Tickets, tables, sponsorships

2024-04-29Gala ticket$100.00 FMV $75.00$25.00
Finalize Regenerate Preview PDF

One click generates a draft receipt for every donor with tax-relevant giving in a chosen year. Each is a three-section PDF: donations are fully deductible, auction wins and event tickets deduct the amount paid minus fair market value, and raffle tickets are excluded entirely, because the IRS says so.

Finalised receipts lock at the database level with no exceptions. A correction never edits the original: regenerating issues a new receipt with a supersede pointer back to the old one, and both stay in the audit trail. Donors download their own from the portal on signed links that expire after an hour.

The donor portal

Donors serve themselves, admins approve

Donors sign in with a six-digit one-time code sent through the nonprofit's own HighLevel channel. They see lifetime and year-to-date giving, every transaction with its deductible value, and a download button for each finalised receipt.

Made a gift that isn't showing? They submit it from the portal: date, amount, description. It lands in the admin's review queue as pending, and nothing becomes a real transaction until an administrator checks it against the bank and approves. Rejections carry a note the donor can see, and either outcome shows in their portal.

/submissions · admin review queue

Donor submissions · 2 pending review

Jane Doe · $500 donation

pending

Submitted 2026-06-22 · 2026-06-15 · donation · "Check #1042, mailed last week. I sent this to the PO Box; please confirm receipt."

Approve Reject

Approving creates the transaction, recomputes aggregates and fires the HighLevel sync. The DMS never guesses against your bank; the verification step is human.

HighLevel sync

Every push logged, every failure explained

/sync-log

Synced

30

Failed

0

Last attempt

2026-05-28 10:18

WhenDonorStatusDetail
10:18:49Acme CorporationsyncedhjNo5Yf3GxqTfFCh3xmH
10:18:48John Smithsyncedsnk1NhXHawVF93PeYus8
10:18:47Jane DoesyncedZEaFdrWerDeWkFMHtxj6

Donor aggregates push one way into custom fields on the HighLevel contact, so campaigns, workflows and segments always run from live giving data. Matching is on email, updates are idempotent, and a manual "Sync this donor" button exists for the impatient.

The log keeps the last 200 attempts with the exact error on any failure: an expired token says so, a deleted custom field says so, and rate limits retry automatically with backoff. This is the reversible, logged, no-mystery approach I put into every build, applied to a whole product.

Want this for your nonprofit, or something like it for your industry?

The DMS runs in production today. The same architecture, staged writes, full logging and a HighLevel sync, applies to any industry where the data has to be right.

Free account audit

Tell me what you need built

I read these myself and reply myself. Prefer to talk? Call +44 7782 631 115.

Free account audit

Tell me what's going wrong

Two minutes now, a written answer inside two working days. Anything urgent goes to the front, so say so in the form.

No sequence, no newsletter. I read these myself and reply myself. Prefer to talk? Call me.