{"id":51189815,"url":"https://github.com/nmbrthirteen/crm-connect","last_synced_at":"2026-06-27T14:01:46.171Z","repository":{"id":363610665,"uuid":"1264120764","full_name":"nmbrthirteen/crm-connect","owner":"nmbrthirteen","description":"WordPress plugin that captures every form submission - fields, UTMs, trackables - and reliably forwards them server-side to a CRM (Freshsales) via configurable per-form mapping. Persist-before-send queue with retries, dead-lettering and auto-pause.","archived":false,"fork":false,"pushed_at":"2026-06-09T16:16:09.000Z","size":68,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T17:23:32.122Z","etag":null,"topics":["crm","elementor","form-submissions","freshsales","lead-capture","php","utm-tracking","wordpress","wordpress-plugin"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nmbrthirteen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-09T15:22:30.000Z","updated_at":"2026-06-09T16:24:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nmbrthirteen/crm-connect","commit_stats":null,"previous_names":["nmbrthirteen/crm-connect"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nmbrthirteen/crm-connect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmbrthirteen%2Fcrm-connect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmbrthirteen%2Fcrm-connect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmbrthirteen%2Fcrm-connect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmbrthirteen%2Fcrm-connect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nmbrthirteen","download_url":"https://codeload.github.com/nmbrthirteen/crm-connect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nmbrthirteen%2Fcrm-connect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34855826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crm","elementor","form-submissions","freshsales","lead-capture","php","utm-tracking","wordpress","wordpress-plugin"],"created_at":"2026-06-27T14:01:44.272Z","updated_at":"2026-06-27T14:01:46.154Z","avatar_url":"https://github.com/nmbrthirteen.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CRM Connect\n\nA whitelabeled WordPress plugin that captures website form submissions - every field, UTM and trackable - and reliably forwards them **server-side** to a CRM (Freshsales first) via a configurable per-form mapping. See [`DESIGN.md`](./DESIGN.md) for the full design rationale.\n\n## Install (development)\n\n1. Copy this folder into `wp-content/plugins/crm-connect`.\n2. Optional but recommended: `composer dump-autoload -o` (a PSR-4 fallback autoloader is built in, so this is not required).\n3. Activate **CRM Connect** in WP Admin → Plugins. Activation creates the queue table.\n4. Go to the **CRM Connect** menu:\n   - **Settings** - enter your Freshsales domain (`yourco.myfreshworks.com`) + API key, then **Test connection**. Set branding, alert email/Slack, retention, auto-pause.\n   - **Mappings** - add a mapping: pick a form, add a CRM object (Contact/Deal), map fields, set the dedupe key and a catch-all field. **Save**.\n   - **Submissions** - live log of every submission with status, full payload, CRM request/response, and retry.\n\nRequires PHP 8.0+, Elementor Pro (for the Elementor form source).\n\n## Architecture (two swappable seams)\n\n```\nForm submit ─▶ FormSource (Elementor) ─▶ CaptureService ─▶ QueueStore (DB, persist-first)\n                                                                  │\n                          Attribution cookie (first+last touch) ──┘\n                                                                  ▼\n                                  QueueWorker (retries, backoff, dead-letter, 429-aware, auto-pause)\n                                                                  ▼\n                                  CrmProvider (Freshsales) ◀─ FieldMapper (per-form profile)\n```\n\n- **CRM is pluggable** via the `crm_connect_provider` filter (`CrmProvider` interface). Freshsales is provider #1.\n- **Form platform is pluggable** via the `crm_connect_form_sources` filter (`FormSource` interface). Elementor is source #1.\n- The queue, mapping, capture, log, and alerting layers are agnostic to both.\n\n### Key extension points (filters/actions)\n\n| Hook | Purpose |\n|---|---|\n| `crm_connect_provider` | Return a `CrmProvider` to swap CRM |\n| `crm_connect_form_sources` | Add/replace `FormSource` implementations |\n| `crm_connect_trackables` | Add custom trackable source keys |\n| `crm_connect_attribution_enabled` | Gate the attribution cookie behind a consent manager |\n| `crm_connect_attribution_lifetime_days` | Cookie lifetime (default 90) |\n| `crm_connect_dead_letter` / `crm_connect_worker_paused` | Hook delivery failures |\n\n## Reliability properties\n\n- **Persist-before-send**: the full payload is written to the DB inside the form hook, before any CRM call - a CRM outage can never lose a submission.\n- **Retries** with exponential backoff → **dead-letter** after 6 attempts.\n- **429-aware**: honors Freshsales' `Retry-After`; schema reads are cached (rate-limit budget is 1000/hr).\n- **Crash recovery**: items stuck in `sending` for \u003e5 min are re-claimed.\n- **Auto-pause** after N consecutive failures + email/Slack alert; manual resume.\n- **Retention purge** of old sent rows (configurable, default 180 days).\n\n## Releases \u0026 updates\n\nThe plugin self-updates from GitHub Releases via [Plugin Update Checker](https://github.com/YahnisElsts/plugin-update-checker) (bundled in `lib/`). Installed sites see the native WordPress \"Update available\" notice and can one-click update (or enable WordPress's per-plugin auto-update toggle for hands-off updates).\n\nTo cut a release:\n\n```\nbin/release.sh 0.3.0\n```\n\nThis bumps the version, commits, tags `v0.3.0`, and pushes. The `Release` GitHub Action then builds a clean `crm-connect.zip` and publishes it to the release automatically.\n\n## License\n\nGPL-2.0-or-later. See [`LICENSE`](./LICENSE).\n\n## Known follow-ups (not yet built)\n\n- **Reconciliation cron** against Elementor's `wp_e_submissions` tables (defense-in-depth backfill if the hook itself ever fatals). Deferred pending verification of Elementor's submission-table schema.\n- **Deal orchestration**: a Deal needs `name`, `amount`, `sales_account_id`. The lookup-or-create-Sales-Account-by-company step is not yet wired - currently Deal fields are mapped directly like any object.\n- **`create_field` form id**: Freshsales' custom-field endpoint path (`settings/\u003centity\u003e/forms/\u003cform_id\u003e/fields`) uses a placeholder form id `0`; verify against a live account.\n- Choice-mapping UI for CRM dropdown fields (value → choice) is stubbed; mapping currently passes raw values (unmatched values fall to the catch-all).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnmbrthirteen%2Fcrm-connect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnmbrthirteen%2Fcrm-connect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnmbrthirteen%2Fcrm-connect/lists"}