How digitalscientists.com captures leads, attributes campaigns, and routes every form submission and meeting booking into Pipedrive — automatically.
All contact and inquiry forms on the site submit to a single Formspree endpoint (formspree.io/f/xvzbywbr). Formspree stores the submission, fires an email notification, and triggers a webhook to a Netlify Function that creates the appropriate Pipedrive record.
Every form automatically includes hidden UTM fields (injected by ds-includes-v2.js from sessionStorage) and a hidden source field identifying the page — so every submission is traceable back to its origin.
formspree-webhook.mjs receives the POST. It finds or creates a Person (deduplicated by email) and an Organization (from company field), then checks for UTM parameters.| Page | Source ID | Pipedrive Title | Also Has Scheduler? |
|---|---|---|---|
| CORE CONVERSION PAGES | |||
/ | homepage | Homepage — New Lead | No |
/start/ | start-page | Get Started — New Lead | Yes (button) |
/proof/ | proof-landing-page | Proof in 5 Days — New Lead | No |
/method/ | method-page | Method Page — New Lead | No |
/reasons-to-believe/ | reasons-to-believe | Reasons to Believe Page Inquiry | No |
| HEALTHCARE HUB & SOLUTIONS | |||
/healthcare/ | healthcare-hub | Healthcare Hub — New Lead | No |
…/patient-portal-digital-front-door/ | patient-portal | Patient Portal Inquiry | No |
…/electronic-health-record-practice-management/ | ehr-practice-management | EHR/Practice Management Inquiry | No |
…/telemedicine-app-development/ | telemedicine-app-development | Telemedicine Solutions Inquiry | No |
…/healthcare-interoperability-solutions/ | healthcare-interoperability | Healthcare Interoperability Inquiry | No |
…/predictive-analytics-healthcare/ | predictive-analytics | Predictive Analytics Inquiry | No |
…/population-health-management/ | population-health-management | Population Health Management Inquiry | No |
…/remote-patient-monitoring-solutions/ | remote-patient-monitoring | Remote Patient Monitoring Inquiry | No |
…/cdss-clinical-decision-support-system/ | cdss | Clinical Decision Support Inquiry | No |
| HEALTHCARE CAPABILITIES | |||
…/healthcare-ai-development/ | healthcare-ai-development | Healthcare AI Development Inquiry | No |
…/healthcare-saas-development/ | healthcare-saas | Healthcare SaaS Development Inquiry | No |
…/healthcare-data-analytics-engineering/ | healthcare-data-analytics | Healthcare Data Analytics Inquiry | No |
…/healthcare-ux-design-research/ | healthcare-ux-design | Healthcare UX Design Inquiry | No |
…/software-as-medical-device-samd/ | software-as-medical-device | Software as Medical Device Inquiry | No |
| HEALTHCARE ASSESSMENT & OTHER | |||
/healthcare/assessment/partnership/ | healthcare-assessment-partnership | Partnership Assessment Inquiry | No |
/healthcare/assessment/platform/ | healthcare-assessment-platform | Platform Assessment Inquiry | No |
| Newsletter popup (all pages) | newsletter-popup | Insights Newsletter — New Subscriber | N/A |
| Page | Scheduler Format |
|---|---|
/thank-you/ | Button — post-form conversion CTA |
/healthcare/assessment/ | Embedded iframe — in-page booking widget |
/event/paltc26-annual-conference/ | 4 buttons — hero CTA + "Book time" pills + footer CTA |
/event/beckers-health-it-rcm-2026/ | 4 buttons — hero CTA + "Book time" pills + footer CTA |
/event/2026-nchcfa-annual-convention-expo/ | 1 button — footer CTA |
Note: /start/ is the only page with both a Formspree form and a Pipedrive Scheduler link.
Replaced Calendly in March 2026. The Scheduler creates meetings natively in Pipedrive, eliminating a third-party middleware layer. Because booking happens on Pipedrive's domain (not ours), campaign attribution and contact details can't be captured in a single request — so the integration runs in two phases.
All scheduler links point to: digitalscientists3.pipedrive.com/scheduler/kOOeAEu2/meeting-with-bob-klein
ds-includes-v2.js intercepts the click and reads UTM data from sessionStorage.schedule-lead.mjs creates a Deal in Inbound Project → Marketing Qualified with UTM fields and source page populated. No person linked yet.activity.create. scheduler-webhook.mjs fetches full Activity details (note text is not in the webhook payload — requires a separate API call), then searches for a recent unlinked Deal by title pattern within a 10-minute window.The same UTM capture mechanism feeds both Formspree and the Scheduler. When a visitor arrives via a campaign link, ds-includes-v2.js stores the UTM values in sessionStorage — persisting across page navigations within the same session. At conversion (form submit or scheduler click), UTMs are passed to the Netlify Function.
| Field | API Key | UTM Parameter |
|---|---|---|
| UTM Source | 2d987c86f8c2ba6d4a2ba671202fb101963cb7ae | utm_source |
| UTM Medium | 5bc2cf59b8f65bac7fee4f0049decda09e64eefb | utm_medium |
| UTM Campaign | f6983c094a3678e33fa339a912595b1d8c1a0ed3 | utm_campaign |
| UTM Content | de10675163c2f6d75a0699052c21d3a36e71091e | utm_content |
| Source Page | 1fe5fef0101f8b10a757d9944b072e0c098da15a | (source field) |
utm_campaign=paltc26/start/, UTMs storedformspree-webhook.mjs runsutm_campaign=paltc26-invite/proof/, fills out formPipedrive's native two-way calendar sync connects Scheduler bookings to Bob's Google Calendar. Pipedrive is the single source of truth — no duplicate events (the old Calendly setup could write directly to Google Calendar and create doubles).
Configured in Pipedrive → Settings → Calendar Sync → Google Calendar. "Meeting" activity type must be enabled for sync.
Triggered by Formspree webhook on every form submission. Finds/creates Person + Org, then creates a Deal (UTMs present) or Lead (no UTMs) in Pipedrive.
Pre-booking. Called by frontend JS on scheduler click. Creates a Deal with UTM fields for campaign traffic; passthrough for organic.
Post-booking. Triggered by Pipedrive Webhook #3102756 on activity.create. Enriches Deal with person/org/note, or creates a Lead if no Deal found.
Frontend JS, loaded site-wide. Captures UTMs into sessionStorage, intercepts scheduler clicks, and injects UTM hidden fields into Formspree forms.
| From | To | Connection Type | Credential |
|---|---|---|---|
| Website forms | Formspree | HTML form action | None (public endpoint) |
| Formspree | Netlify Function | REST webhook (x-hook-secret) | Configured in Formspree dashboard |
| Netlify Functions | Pipedrive API | REST API v1 | PIPEDRIVE_API_TOKEN env var |
| Pipedrive | Netlify Function | Webhook v2.0 (#3102756, activity.create) | Registered via Pipedrive API |
| Pipedrive | Google Calendar | Native two-way sync | OAuth (Pipedrive Settings) |
| Website | Pipedrive Scheduler | iframe embed + outbound links | Public scheduler URL |
| Setting | Location | Value |
|---|---|---|
| Webhook #3102756 | Settings → Webhooks | activity.create → scheduler-webhook.mjs |
| Calendar sync | Settings → Calendar Sync | Google Calendar, two-way, Meetings enabled |
| UTM custom fields | Settings → Data Fields → Deal | 5 fields (see keys table above) |
| Scheduler | Settings → Scheduler | kOOeAEu2/meeting-with-bob-klein |
PIPEDRIVE_API_TOKEN must be set in Netlify's environment variables. All three Netlify Functions authenticate with Pipedrive using this token.
| Failure | Impact | Mitigation |
|---|---|---|
| Pre-booking function fails | Visitor still reaches Scheduler (2s timeout fallback) | Post-booking webhook creates a Lead without UTMs |
| Scheduler webhook doesn't fire | Activity + Person still created by Pipedrive natively | Lead/Deal must be created manually; bookings are not lost |
| Formspree webhook fails | Formspree still stores submission + sends email | Function returns 200 to prevent retries; check Netlify logs |
| Pipedrive API down | Functions log errors, return gracefully | Formspree retains submissions; Scheduler retains bookings — can backfill |
| UTM sessionStorage cleared | No campaign attribution captured | Rare (private browsing, storage cleared); visitor shows as organic |
| Concurrent campaign bookings | Webhook could mismatch Deals (10-min window) | Extremely rare in B2B; review Deal titles if suspicious |
With UTM fields on Deals, Pipedrive's built-in reporting can answer:
Sent to scheduler-webhook.mjs on activity.create. The webhook uses person_id and org_id to link the Deal. Booking form text (name, phone, company, agenda) is not in this payload — the handler fetches it via a separate call to GET /activities/{id}.
{
"data": {
"id": 12345,
"type": "meeting",
"subject": "Jane Smith / Bob Klein - Meeting with Bob Klein",
"person_id": 20348,
"org_id": 13528,
"due_date": "2026-03-25",
"due_time": { "value": "10:00:00" }
},
"previous": null,
"meta": {
"action": "create",
"entity": "activity",
"version": "2.0"
}
}