@nbt-dev/nbt 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +177 -21
- package/README.md +16 -13
- package/TRADEMARKS.md +49 -0
- package/dist/nbt.js +398 -19
- package/package.json +5 -4
- package/stdlib/auth/README.md +83 -0
- package/stdlib/auth/migrations/20260424144652_initial/migration.nbt +48 -0
- package/stdlib/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
- package/stdlib/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
- package/stdlib/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
- package/stdlib/auth/schema.nbt +142 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/v2_calendar_pilot.json +12 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_changed.json +70 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_created.json +72 -0
- package/stdlib/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
- package/stdlib/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
- package/stdlib/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
- package/stdlib/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
- package/stdlib/calendar/schema.nbt +85 -0
- package/stdlib/chat/migrations/20260429222411_initial/migration.nbt +59 -0
- package/stdlib/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
- package/stdlib/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
- package/stdlib/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
- package/stdlib/chat/migrations/20260514202654_update_directmessageroom/migration.nbt +4 -0
- package/stdlib/chat/migrations/20260514202654_update_directmessageroom/schema_snapshot.nbt +80 -0
- package/stdlib/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
- package/stdlib/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
- package/stdlib/chat/schema.nbt +130 -0
- package/stdlib/crm/adapters/gohighlevel/README.md +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/README.md +159 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_138fields.json +222 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_140fields.json +219 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_alt.json +212 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_changed.json +102 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_created.json +95 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_full.json +213 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_sparse.json +161 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_a.json +197 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_b.json +197 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_changed.json +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_created.json +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_pilot.json +43 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_closed.json +7 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_open.json +7 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_appointment_delete.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_calendar_update.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_contact_create.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_opp_status_update.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_opportunity_pilot.json +16 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_pipelines_pilot.json +137 -0
- package/stdlib/crm/migrations/20260501210107_initial/migration.nbt +63 -0
- package/stdlib/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
- package/stdlib/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
- package/stdlib/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
- package/stdlib/crm/schema.nbt +146 -0
- package/stdlib/design/migrations/20260501210107_initial/migration.nbt +19 -0
- package/stdlib/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
- package/stdlib/design/migrations/20260610130000_design_system/migration.nbt +50 -0
- package/stdlib/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
- package/stdlib/design/schema.nbt +140 -0
- package/stdlib/dns/migrations/20260501210107_initial/migration.nbt +32 -0
- package/stdlib/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
- package/stdlib/dns/schema.nbt +68 -0
- package/stdlib/email/migrations/20260427235207_initial/migration.nbt +75 -0
- package/stdlib/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
- package/stdlib/email/schema.nbt +145 -0
- package/stdlib/ingest/README.md +29 -0
- package/stdlib/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
- package/stdlib/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
- package/stdlib/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
- package/stdlib/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
- package/stdlib/ingest/schema.nbt +37 -0
- package/stdlib/notifications/README.md +118 -0
- package/stdlib/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
- package/stdlib/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
- package/stdlib/notifications/schema.nbt +67 -0
- package/stdlib/phone/migrations/20260605205722_initial/migration.nbt +50 -0
- package/stdlib/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
- package/stdlib/phone/schema.nbt +95 -0
- package/stdlib/registry/migrations/20260602181932_initial/migration.nbt +8 -0
- package/stdlib/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
- package/stdlib/registry/schema.nbt +20 -0
- package/stdlib/workflows/schema.nbt +43 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/migration.nbt +48 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
- package/vendor/linux-x64/cartridges/auth/schema.nbt +142 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
- package/vendor/linux-x64/cartridges/calendar/schema.nbt +85 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/migration.nbt +59 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260514202654_update_directmessageroom/migration.nbt +4 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260514202654_update_directmessageroom/schema_snapshot.nbt +80 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
- package/vendor/linux-x64/cartridges/chat/schema.nbt +130 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/migration.nbt +63 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
- package/vendor/linux-x64/cartridges/crm/schema.nbt +146 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/migration.nbt +19 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/migration.nbt +50 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
- package/vendor/linux-x64/cartridges/design/schema.nbt +140 -0
- package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/migration.nbt +32 -0
- package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
- package/vendor/linux-x64/cartridges/dns/schema.nbt +68 -0
- package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/migration.nbt +75 -0
- package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
- package/vendor/linux-x64/cartridges/email/schema.nbt +145 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
- package/vendor/linux-x64/cartridges/ingest/schema.nbt +37 -0
- package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
- package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
- package/vendor/linux-x64/cartridges/notifications/schema.nbt +67 -0
- package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/migration.nbt +50 -0
- package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
- package/vendor/linux-x64/cartridges/phone/schema.nbt +95 -0
- package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/migration.nbt +8 -0
- package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
- package/vendor/linux-x64/cartridges/registry/schema.nbt +20 -0
- package/vendor/linux-x64/cartridges/workflows/schema.nbt +43 -0
- package/vendor/linux-x64/console +0 -0
- package/vendor/linux-x64/nbt +0 -0
- package/contracts/audit/.dist/contract.json +0 -56
- package/contracts/auth/.dist/contract.json +0 -252
- package/contracts/calendar/.dist/contract.json +0 -141
- package/contracts/chat/.dist/contract.json +0 -229
- package/contracts/crm/.dist/contract.json +0 -239
- package/contracts/design/.dist/contract.json +0 -85
- package/contracts/dns/.dist/contract.json +0 -123
- package/contracts/email/.dist/contract.json +0 -267
- package/contracts/embed/.dist/contract.json +0 -137
- package/contracts/ingest/.dist/contract.json +0 -86
- package/contracts/notifications/.dist/contract.json +0 -133
- package/contracts/phone/.dist/contract.json +0 -168
- package/contracts/registry/.dist/contract.json +0 -49
- package/contracts/workflows/.dist/contract.json +0 -106
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# GHL Adapter Tests
|
|
2
|
+
|
|
3
|
+
Two fixture sets, two purposes. Both describe the same GHL tenant
|
|
4
|
+
(`org=mlp, project=default, locationId=loc_test`) so a replay that uses
|
|
5
|
+
either source converges on the same CRM entity graph.
|
|
6
|
+
|
|
7
|
+
| Set | Role | Producer | Consumer | Discriminator |
|
|
8
|
+
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `fixtures/webhooks/*.json` | Inbound delta stream | GHL workflow engine (or v2 native subscription) | `tasks/classify_event_type.nbt` + downstream user-cart systems | `body.workflow.name` (workflow shape) → fall back to `body.type` (v2 native) |
|
|
10
|
+
| `fixtures/api/*.json` | Backfill / sync recovery snapshot | Mocked GHL REST replies (when `GHL_MOCK_DIR` is set, `native/mock.jai` reads from disk instead of curl) | All `tasks/fetch_*` / `tasks/list_*` tasks | URL-derived filename (see "Mock key derivation" below) |
|
|
11
|
+
|
|
12
|
+
The two sets carry **different shapes** because GHL emits different shapes:
|
|
13
|
+
the workflow engine flattens custom fields onto the top-level payload (with
|
|
14
|
+
`customFields[]` redundantly nested), while the REST API returns them under
|
|
15
|
+
a typed envelope (`{contact: {...}}`, `{opportunities: [...], meta: {...}}`,
|
|
16
|
+
etc.). The flattening logic and field classification live in the portal at
|
|
17
|
+
`packages/api/src/services/ghl/field-classification.ts`.
|
|
18
|
+
|
|
19
|
+
## Source of truth for shapes
|
|
20
|
+
|
|
21
|
+
- **Webhook payload shapes** — derived from the portal handler at
|
|
22
|
+
`apps/portal/app/api/v1/[...route]/routes/webhooks/ghl.ts` (the consumer is
|
|
23
|
+
authoritative; GHL workflow webhook payloads are user-configurable and not
|
|
24
|
+
formally schema'd).
|
|
25
|
+
- **API response shapes** — the GHL marketplace API docs are authoritative;
|
|
26
|
+
cross-check each API fixture against the corresponding endpoint page:
|
|
27
|
+
- `GET /contacts/:id` — https://marketplace.gohighlevel.com/docs/ghl/contacts/get-contact
|
|
28
|
+
- `GET /contacts/` — https://marketplace.gohighlevel.com/docs/ghl/contacts/get-contacts
|
|
29
|
+
- `GET /opportunities/:id` — https://marketplace.gohighlevel.com/docs/ghl/opportunities/get-opportunity
|
|
30
|
+
- `GET /opportunities/search` — https://marketplace.gohighlevel.com/docs/ghl/opportunities/search-opportunity
|
|
31
|
+
- `GET /opportunities/pipelines` — https://marketplace.gohighlevel.com/docs/ghl/opportunities/get-pipelines
|
|
32
|
+
- `GET /calendars/` — https://marketplace.gohighlevel.com/docs/ghl/calendars/get-calendars
|
|
33
|
+
- `GET /calendars/events` — https://marketplace.gohighlevel.com/docs/ghl/calendars/get-calendar-events
|
|
34
|
+
- `GET /calendars/blocked-slots` — https://marketplace.gohighlevel.com/docs/ghl/calendars/get-blocked-slots
|
|
35
|
+
- `GET /users/` — https://marketplace.gohighlevel.com/docs/ghl/users/get-user-by-location
|
|
36
|
+
- `GET /locations/:id/customFields` — https://marketplace.gohighlevel.com/docs/ghl/custom-fields/get-custom-fields
|
|
37
|
+
|
|
38
|
+
## Shared CRM graph (referenced by both sets)
|
|
39
|
+
|
|
40
|
+
| Entity | ID | Notes |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| Contact | `ctc_alice_001` | Alice Anderson; full address + property custom fields. After `contact_changed`, last name → `Anderson-Smith`, address → `456 Updated Ave`, email → `alice.smith@example.com`. |
|
|
43
|
+
| Contact | `ctc_bob_002` | Bob Builder; minimal — exists so `contacts__page1` is non-trivial. |
|
|
44
|
+
| Opportunity | `opp_001` | Alice's 8 kW solar deal. `Created` lands at `pip_solar / ps_qualified` @ $24 500. `Changed` advances to `ps_proposal_sent` @ $28 500 with an `Appointment Outcome=showed`. |
|
|
45
|
+
| Pipeline | `pip_solar` | 5 stages: `ps_lead → ps_qualified → ps_proposal_sent → ps_won / ps_lost`. |
|
|
46
|
+
| Calendar | `cal_solar_consult` | `America/Toronto`, team `usr_001`/`usr_002`. |
|
|
47
|
+
| Appointment | `apt_001` | Alice + cal_solar_consult. `Created` confirms for 2026-05-12 14:00 EDT. `Changed` reschedules to 2026-05-15 10:00 (timezone-naive) and transitions to `showed`. |
|
|
48
|
+
| Users | `usr_001..003` | Bob Brown / Charlie Chen / Diana Davis — match the `Setter`/`Closer` strings in webhook payloads. |
|
|
49
|
+
| Custom fields | `cf_utility`, `cf_avg_bill`, `cf_shade`, `cf_owner` (contact model); `cf_proposal`, `cf_inspection_date` (opportunity model); plus the deal-tracking projection (`cf_setter`, `cf_closer`, `cf_appt_outcome`, `cf_total_contract`, `cf_date_sold`). |
|
|
50
|
+
|
|
51
|
+
## Webhook fixtures (`fixtures/webhooks/`)
|
|
52
|
+
|
|
53
|
+
One fixture per real published GHL Workflow shape. Every payload mirrors
|
|
54
|
+
something GHL actually posts; synthetic probes (unknown event, wrong
|
|
55
|
+
tenant, v2 native subscriptions) have been dropped — they tested code
|
|
56
|
+
paths that don't fire for the real tenant configuration.
|
|
57
|
+
|
|
58
|
+
| File | `workflow.name` | `body.type` | Expected classifier output |
|
|
59
|
+
| --- | --- | --- | --- |
|
|
60
|
+
| `contact_created.json` | `Contact Created Sync` | `ContactCreate` | `event_type=ContactCreate, tenant_org=mlp, tenant_project=default` |
|
|
61
|
+
| `contact_changed.json` | `Contact Changed Sync` | `ContactUpdate` | `event_type=ContactChange` |
|
|
62
|
+
| `opportunity_created.json` | `Opportunity Created Sync` | `OpportunityCreate` | `event_type=OpportunityCreate` |
|
|
63
|
+
| `opportunity_changed.json` | `Opportunity Changed Sync` | `OpportunityUpdate` | `event_type=OpportunityChange` |
|
|
64
|
+
| `appointment_created.json` | `Appointment Created Sync` | `AppointmentCreate` | `event_type=AppointmentCreate` |
|
|
65
|
+
| `appointment_changed.json` | `Appointment Changed Sync` | `AppointmentUpdate` | `event_type=AppointmentChange` |
|
|
66
|
+
|
|
67
|
+
The 7th GHL workflow shown in the published list — **Pipeline Stage Changed
|
|
68
|
+
Sync** — carries the same opportunity payload shape as Opportunity Changed
|
|
69
|
+
Sync. The classifier aliases it onto `event_type=OpportunityChange`, so
|
|
70
|
+
`opportunity_changed.json` covers it (replay with `workflow.name` swapped to
|
|
71
|
+
verify).
|
|
72
|
+
|
|
73
|
+
### Real-payload shape and quirks
|
|
74
|
+
|
|
75
|
+
- **Custom fields are flat top-level keys, not a `customFields[]` array.**
|
|
76
|
+
Real GHL workflow webhooks emit every property field as a top-level body
|
|
77
|
+
key by display name (`"Closer": "..."`, `"Average Electric Bill": "245"`,
|
|
78
|
+
`"Shade?": "minimal"`). The `customFields[]` array shape only appears on
|
|
79
|
+
REST API responses (`fixtures/api/`), not on webhook bodies. Most
|
|
80
|
+
property keys come through as empty strings even when unset.
|
|
81
|
+
- **Cross-domain spillage is normal.** Contact webhooks carry deal-tracking
|
|
82
|
+
fields (`Setter`, `Closer`, `Total Contract Price`); opportunity webhooks
|
|
83
|
+
carry property fields (`Average Electric Bill`, `Shade?`); appointment
|
|
84
|
+
webhooks carry both. Don't assume Contact-side keys imply contact intent.
|
|
85
|
+
- **HVAC twin keys.** Many fields have `(HVAC)` variants
|
|
86
|
+
(`Closer` + `Closer (HVAC)`, `Setter Name` + `Setter Name (HVAC)`,
|
|
87
|
+
`# Touches` + `# Touches HVAC`). Both ship even when only one branch is
|
|
88
|
+
active.
|
|
89
|
+
- **Numeric values can be raw JSON numbers**, not always strings
|
|
90
|
+
(e.g. `"Outbound Dials": 8`, `"# Touches": 3`).
|
|
91
|
+
- `customData` carries `{org, project, type}` — `type` is one of
|
|
92
|
+
`"Contact"` / `"Opportunity"` / `"Appointment"`.
|
|
93
|
+
- Top-level `attributionSource: {}` is typically empty; real attribution
|
|
94
|
+
lives under `contact.attributionSource` and `contact.lastAttributionSource`.
|
|
95
|
+
- `appoinmentStatus` (GHL typo) is the canonical key on appointment
|
|
96
|
+
payloads. `appointment_changed.json` carries both `appoinmentStatus` and
|
|
97
|
+
`appointmentStatus` with conflicting values to exercise typo precedence.
|
|
98
|
+
- `pipleline_stage` (GHL typo) — `opportunity_changed.json` uses it
|
|
99
|
+
instead of `pipeline_stage` to exercise handler/cart fallback
|
|
100
|
+
(ghl.ts:1308, 1313, 1392).
|
|
101
|
+
- Naive vs offset timestamps — `appointment_created.json` uses
|
|
102
|
+
`-04:00`-offset times; `appointment_changed.json` uses naive
|
|
103
|
+
`"2026-05-15T10:00:00"` (no offset) so `parseGhlTime` falls into its
|
|
104
|
+
`fromZonedTime` branch.
|
|
105
|
+
- `tags` on workflow webhooks is a comma-separated CSV string (with
|
|
106
|
+
possible spaces, apostrophes, special chars); v2-native shape is a JSON
|
|
107
|
+
array.
|
|
108
|
+
|
|
109
|
+
API fixtures (`fixtures/api/`) keep the structured `customFields[]` array
|
|
110
|
+
shape — that's the format the GHL REST API actually returns. The webhook
|
|
111
|
+
flattening happens server-side inside GHL's workflow engine.
|
|
112
|
+
|
|
113
|
+
## API fixtures (`fixtures/api/`)
|
|
114
|
+
|
|
115
|
+
Filename is derived from URL path + selected query keys (see `native/mock.jai`).
|
|
116
|
+
|
|
117
|
+
### Mock key derivation
|
|
118
|
+
|
|
119
|
+
1. Strip leading `/`, replace remaining `/` with `_`, drop the query string.
|
|
120
|
+
2. If query has `skip` + `limit`, append `_pageN` where `N = skip/limit + 1`.
|
|
121
|
+
3. If query has `startTime` + `endTime`, append `_window`.
|
|
122
|
+
4. Other query params (e.g. `model=contact|opportunity` on
|
|
123
|
+
`customFields`) **do not** affect the key — a single fixture serves all
|
|
124
|
+
variants of those query shapes.
|
|
125
|
+
|
|
126
|
+
| Fixture | Endpoint | Notes |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `users_.json` | `GET /users/` | 3 users matching the `Setter`/`Closer` names in the webhook fixtures. |
|
|
129
|
+
| `opportunities_pipelines.json` | `GET /opportunities/pipelines` | One pipeline (`pip_solar`) with 5 stages. |
|
|
130
|
+
| `locations_loc_test_customFields.json` | `GET /locations/loc_test/customFields` | Union of contact-model and opportunity-model fields (mock dispatcher conflates the `?model=` query). |
|
|
131
|
+
| `contacts__page1.json` | `GET /contacts/?skip=0&limit=100` | Alice + Bob with full scalars, `attributionSource`, `customFields[]`. |
|
|
132
|
+
| `contacts__page2.json` | `GET /contacts/?skip=100&limit=100` | Empty terminator. |
|
|
133
|
+
| `contacts_ctc_alice_001.json` | `GET /contacts/ctc_alice_001` | Single-contact envelope `{contact: {...}}`. |
|
|
134
|
+
| `opportunities_search_page1.json` | `GET /opportunities/search?skip=0&limit=100` | One opp with custom fields and assignment metadata. |
|
|
135
|
+
| `opportunities_search_page2.json` | `GET /opportunities/search?skip=100&limit=100` | Empty terminator. |
|
|
136
|
+
| `opportunities_opp_001.json` | `GET /opportunities/opp_001` | Single-opp envelope `{opportunity: {...}}`. |
|
|
137
|
+
| `calendars_.json` | `GET /calendars/` | One calendar with team members. |
|
|
138
|
+
| `calendars_events_window.json` | `GET /calendars/events?calendarId=…&startTime=…&endTime=…` | One event matching `apt_001`'s **created** state, so an API-backfill replay sees the same starting point as the webhook stream's first appointment fixture. |
|
|
139
|
+
| `calendars_blocked-slots_window.json` | `GET /calendars/blocked-slots?userId=…&startTime=…&endTime=…` | Empty `{slots: []}` so the task has a fixture instead of `mock_missing:`. |
|
|
140
|
+
|
|
141
|
+
## Replay loop (smoke target — harness still pending)
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
GHL_MOCK_DIR=$(pwd)/cartridges/core/crm/adapters/gohighlevel/tests/fixtures \
|
|
145
|
+
GHL_PIT_TOKEN=test GHL_LOCATION_ID=loc_test \
|
|
146
|
+
./console &
|
|
147
|
+
for f in cartridges/core/crm/adapters/gohighlevel/tests/fixtures/webhooks/*.json; do
|
|
148
|
+
curl -fsS -X POST -H 'Content-Type: application/json' --data-binary "@$f" \
|
|
149
|
+
"http://localhost:8080/api/ingest/endpoint/receive?e=mylocalpro-ghl"
|
|
150
|
+
done
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Assertion targets:
|
|
154
|
+
- One `Payload` row per webhook fixture.
|
|
155
|
+
- One `Execution` per `Payload`.
|
|
156
|
+
- Classifier outputs match the table in "Webhook fixtures" above.
|
|
157
|
+
- After running the API-fetch path against the same `GHL_MOCK_DIR`, the
|
|
158
|
+
resulting CRM entity graph is congruent with the webhook-replay state
|
|
159
|
+
(Alice's contact + Alice's opp at `ps_proposal_sent` + `apt_001` showed).
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
{
|
|
2
|
+
"# Touches": "",
|
|
3
|
+
"# Touches HVAC": "",
|
|
4
|
+
"% Offset (X)": 111,
|
|
5
|
+
"Annual Production kWh (X,XXX)": 5562,
|
|
6
|
+
"Appointment Outcome": "Pending Hot",
|
|
7
|
+
"Appointment Time": "Wednesday, April 29, 2026 6:30 PM",
|
|
8
|
+
"Appointment Time (HVAC)": "",
|
|
9
|
+
"Appointment Type": "Zoom",
|
|
10
|
+
"Appointment Type (HVAC)": "",
|
|
11
|
+
"Assign Closer": [
|
|
12
|
+
"Assign Closer"
|
|
13
|
+
],
|
|
14
|
+
"Assign Closer HVAC": "",
|
|
15
|
+
"Average Electric Bill": "$100-$199",
|
|
16
|
+
"Battery Included": "",
|
|
17
|
+
"Cash Price (XX,XXX) (IF CASH)": "",
|
|
18
|
+
"City": "Montpelier",
|
|
19
|
+
"City (HVAC)": "",
|
|
20
|
+
"Closer": "Ryan Aiello",
|
|
21
|
+
"Closer (HVAC)": "",
|
|
22
|
+
"Confidence": "2 - Medium Chance of Closing",
|
|
23
|
+
"Credit Score": "",
|
|
24
|
+
"Current Cooling Method": "",
|
|
25
|
+
"Current Heating Method": "",
|
|
26
|
+
"Current Insulation Level": "",
|
|
27
|
+
"Customer Sounds...": "Young",
|
|
28
|
+
"Customer Sounds...(HVAC)": "",
|
|
29
|
+
"Date Sold": "",
|
|
30
|
+
"Date Sold HVAC": "",
|
|
31
|
+
"Discovery Call Disposition": "Appointment Set",
|
|
32
|
+
"Discovery Call Disposition (HVAC)": "",
|
|
33
|
+
"Do You Own Your Home?": "Yes, I own my home",
|
|
34
|
+
"Error Message": "",
|
|
35
|
+
"Financing Options": "",
|
|
36
|
+
"Financing Options HVAC": "",
|
|
37
|
+
"HVAC Experiment Exit Reason": "",
|
|
38
|
+
"Home Photos": [
|
|
39
|
+
"https://services.leadconnectorhq.com/documents/download/UZpGbZPYX2quVZSi2SZE"
|
|
40
|
+
],
|
|
41
|
+
"Home Photos 2": "",
|
|
42
|
+
"Home Sq Footage": "",
|
|
43
|
+
"House No.": "",
|
|
44
|
+
"How Much Shade Does Your Roof Get?": "",
|
|
45
|
+
"How long does the sun shine on your roof?": "All Day Sun",
|
|
46
|
+
"Installer": "",
|
|
47
|
+
"Installer HVAC": "",
|
|
48
|
+
"Insulation Type ": "",
|
|
49
|
+
"Knowledge Level of Solar Appears...": "Low",
|
|
50
|
+
"Last Call Audio": "",
|
|
51
|
+
"Last Call Recording": "",
|
|
52
|
+
"Lead Generation Source": "",
|
|
53
|
+
"Lead Generation Source HVAC": "",
|
|
54
|
+
"Lead Mentioned...": [
|
|
55
|
+
"Spouse"
|
|
56
|
+
],
|
|
57
|
+
"Lead Mentioned...(HVAC)": "",
|
|
58
|
+
"Master Sheet Row ID": 17864,
|
|
59
|
+
"Monthly Electricity Bill (XXX)": 150,
|
|
60
|
+
"Name on Contract": "",
|
|
61
|
+
"Name on Contract HVAC": "",
|
|
62
|
+
"Net Cost (XX,XXX) (IF CASH)": "",
|
|
63
|
+
"Outbound Dials": 15,
|
|
64
|
+
"Parties Present": "1 Legger",
|
|
65
|
+
"Parties Present (Sold)": "",
|
|
66
|
+
"Parties Present (Sold) HVAC": "",
|
|
67
|
+
"Personality Type": "Accommodator",
|
|
68
|
+
"Personality Type (HVAC)": "",
|
|
69
|
+
"Preferred Mount Type": "Roof Mount",
|
|
70
|
+
"Property Type": "Multi-Family Home",
|
|
71
|
+
"Property Type (HVAC)": "",
|
|
72
|
+
"Proposal Used": "",
|
|
73
|
+
"RECs or SMART Monthly (XX) (IF ME NH MA)": "",
|
|
74
|
+
"RECs or SMART Total (XX) (IF ME NH MA)": "",
|
|
75
|
+
"Roof Age": "16-20 Years Old",
|
|
76
|
+
"Roof Included": "",
|
|
77
|
+
"Roof Quote": [
|
|
78
|
+
"Shingle"
|
|
79
|
+
],
|
|
80
|
+
"Roof Replacement Needed?": "Yes",
|
|
81
|
+
"Roof/Land Space": "Average Space for Panels",
|
|
82
|
+
"Sale Difficulty": "",
|
|
83
|
+
"Sale Difficulty HVAC": "",
|
|
84
|
+
"Service Needed": "",
|
|
85
|
+
"Setter": "",
|
|
86
|
+
"Setter Name": "Jessica",
|
|
87
|
+
"Setter Name (HVAC)": "",
|
|
88
|
+
"Setter Notes": "This is a duplex that they own. Kira's partner, Murphy, is actually the homeowner and will be on the call as well. ",
|
|
89
|
+
"Setter Notes (HVAC)": "",
|
|
90
|
+
"Shade?": "Partial Shade",
|
|
91
|
+
"Solar Monthly Payment (XXX)": 304,
|
|
92
|
+
"Sold Notes": "",
|
|
93
|
+
"Sold Notes HVAC": "",
|
|
94
|
+
"State": "VT",
|
|
95
|
+
"State (HVAC)": "",
|
|
96
|
+
"State Sold In": "",
|
|
97
|
+
"State Sold In HVAC": "",
|
|
98
|
+
"State You Live In": "",
|
|
99
|
+
"Staying with Electric Company (XXX,XXX)": 121823,
|
|
100
|
+
"Submit Appointment Form": "Submit",
|
|
101
|
+
"Submit HVAC Appointment Form": "",
|
|
102
|
+
"System Size (Zones)": "",
|
|
103
|
+
"System Size KW's": "",
|
|
104
|
+
"System Size kW (X.XX)": 5.28,
|
|
105
|
+
"System Type": "",
|
|
106
|
+
"Total Contract Price": "",
|
|
107
|
+
"Total Contract Price HVAC": "",
|
|
108
|
+
"Total Payment/Month Net of RECs (XXX)": "",
|
|
109
|
+
"Total Rooms ": "",
|
|
110
|
+
"Town": "",
|
|
111
|
+
"Tree Work Included": "",
|
|
112
|
+
"Tree Work?": "Likely Needed - Willing",
|
|
113
|
+
"Turn Ai OFF/ON": "",
|
|
114
|
+
"Type of Roof": "Shingle",
|
|
115
|
+
"Usable Roof Faces": "Mostly South Facing",
|
|
116
|
+
"Utility": "Green Mountain Power (VT)",
|
|
117
|
+
"Utility Bill": "",
|
|
118
|
+
"Utility Bill 2": "",
|
|
119
|
+
"Website Form": "",
|
|
120
|
+
"What Is Your Average Monthly Electric Bill?": "$400 - $499",
|
|
121
|
+
"Which Service(s) Are You Interested In?": "",
|
|
122
|
+
"Working or Retired?": "Working",
|
|
123
|
+
"Zoom Link": "https://us02web.zoom.us/j/83484521687",
|
|
124
|
+
"Zoom Link (HVAC)": "",
|
|
125
|
+
"address1": "17 Sibley Ave, Montpelier, VT 05602",
|
|
126
|
+
"attributionSource": {},
|
|
127
|
+
"city": "Montpelier",
|
|
128
|
+
"contact": {
|
|
129
|
+
"attributionSource": {
|
|
130
|
+
"adGroupId": null,
|
|
131
|
+
"adId": null,
|
|
132
|
+
"adName": null,
|
|
133
|
+
"fbc": "fb.1.1772568579605.IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
134
|
+
"fbclid": "IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
135
|
+
"fbp": "fb.1.1772568579610.524761681361398700",
|
|
136
|
+
"gaClientId": null,
|
|
137
|
+
"gaSessionId": null,
|
|
138
|
+
"gbraid": null,
|
|
139
|
+
"gclid": null,
|
|
140
|
+
"ip": "2600:100f:b226:dc7c:ecbe:c143:3c48:b409",
|
|
141
|
+
"medium": "survey",
|
|
142
|
+
"mediumId": "lPGmW4iCTWouMmuDkms0",
|
|
143
|
+
"sessionSource": "Social media",
|
|
144
|
+
"url": "https://vtcleanenergy.org/check-your-roof-page-vt?fbclid=IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
145
|
+
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Mobile/15E148 Safari/604.1",
|
|
146
|
+
"utmContent": null,
|
|
147
|
+
"utmKeyword": null,
|
|
148
|
+
"utmMatchtype": null,
|
|
149
|
+
"utmMedium": null,
|
|
150
|
+
"utmSource": null,
|
|
151
|
+
"utmTerm": null,
|
|
152
|
+
"wbraid": null
|
|
153
|
+
},
|
|
154
|
+
"lastAttributionSource": {
|
|
155
|
+
"adGroupId": null,
|
|
156
|
+
"adId": null,
|
|
157
|
+
"adName": null,
|
|
158
|
+
"fbc": "fb.1.1772568579605.IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
159
|
+
"fbclid": "IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
160
|
+
"fbp": "fb.1.1772568579610.524761681361398700",
|
|
161
|
+
"gaClientId": null,
|
|
162
|
+
"gaSessionId": null,
|
|
163
|
+
"gbraid": null,
|
|
164
|
+
"gclid": null,
|
|
165
|
+
"ip": "2600:100f:b226:dc7c:ecbe:c143:3c48:b409",
|
|
166
|
+
"medium": "survey",
|
|
167
|
+
"mediumId": "lPGmW4iCTWouMmuDkms0",
|
|
168
|
+
"referrer": null,
|
|
169
|
+
"sessionSource": "Social media",
|
|
170
|
+
"url": "https://vtcleanenergy.org/survey-vt?fbclid=IwdGRleAQUH1BleHRuA2FlbQIxMQBzcnRjBmFwcF9pZAo2NjI4NTY4Mzc5AAEem3JRuxAiSshp7zpiBgcp-8GApyz9WVa2uWHRab2O0gsc9x4-Zvic620cJkU_aem_3lbo13nfSuVXA1K2B520QA",
|
|
171
|
+
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Mobile/15E148 Safari/604.1",
|
|
172
|
+
"utmContent": null,
|
|
173
|
+
"utmKeyword": null,
|
|
174
|
+
"utmMatchtype": null,
|
|
175
|
+
"utmMedium": null,
|
|
176
|
+
"utmSource": null,
|
|
177
|
+
"utmTerm": null,
|
|
178
|
+
"wbraid": null
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"contact_id": "O1gdLf79slaWFAkGtaXp",
|
|
182
|
+
"contact_source": "Solar Survey Final VT",
|
|
183
|
+
"contact_type": "lead",
|
|
184
|
+
"country": "US",
|
|
185
|
+
"customData": {
|
|
186
|
+
"org": "mylocalpro",
|
|
187
|
+
"project": "crm-automation",
|
|
188
|
+
"type": "Contact"
|
|
189
|
+
},
|
|
190
|
+
"date_created": "2026-03-03T20:11:38.850Z",
|
|
191
|
+
"email": "murphydoyen@gmail.com",
|
|
192
|
+
"first_name": "Kira",
|
|
193
|
+
"full_address": "17 Sibley Ave, Montpelier, VT 05602, Montpelier ",
|
|
194
|
+
"full_name": "Kira Powell",
|
|
195
|
+
"last_name": "Powell",
|
|
196
|
+
"lead_partner_id": "",
|
|
197
|
+
"location": {
|
|
198
|
+
"address": "22 Old Village Rd Sturbridge MA 01566",
|
|
199
|
+
"city": "Sturbridge",
|
|
200
|
+
"country": "US",
|
|
201
|
+
"fullAddress": "22 Old Village Rd Sturbridge MA 01566, Sturbridge MA 01566",
|
|
202
|
+
"id": "1JYeHLJ6v9NBJIidkSIU",
|
|
203
|
+
"name": "My Local Pro",
|
|
204
|
+
"postalCode": "01566",
|
|
205
|
+
"state": "MA"
|
|
206
|
+
},
|
|
207
|
+
"phone": "+19257686539",
|
|
208
|
+
"tags": "new lead,vt,vtfbmlsp,valid-phone,appointment booked",
|
|
209
|
+
"timezone": "America/New_York",
|
|
210
|
+
"triggerData": {},
|
|
211
|
+
"user": {
|
|
212
|
+
"email": "ryan.aiello@mylocalpro.com",
|
|
213
|
+
"extension": "",
|
|
214
|
+
"firstName": "Ryan",
|
|
215
|
+
"lastName": "Aiello",
|
|
216
|
+
"phone": "+15166602273"
|
|
217
|
+
},
|
|
218
|
+
"workflow": {
|
|
219
|
+
"id": "c8b2e9d7-24f8-4e19-a4e4-208e80a0e62b",
|
|
220
|
+
"name": "Contact Changed Sync"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
{
|
|
2
|
+
"# Touches": "",
|
|
3
|
+
"# Touches HVAC": "",
|
|
4
|
+
"% Offset (X)": "",
|
|
5
|
+
"Annual Production kWh (X,XXX)": "",
|
|
6
|
+
"Appointment Outcome": "Unqualified",
|
|
7
|
+
"Appointment Time": "Wednesday, March 4, 2026 8:30 AM",
|
|
8
|
+
"Appointment Time (HVAC)": "",
|
|
9
|
+
"Appointment Type": "",
|
|
10
|
+
"Appointment Type (HVAC)": "",
|
|
11
|
+
"Assign Closer": [
|
|
12
|
+
"Assign Closer"
|
|
13
|
+
],
|
|
14
|
+
"Assign Closer HVAC": "",
|
|
15
|
+
"Average Electric Bill": "",
|
|
16
|
+
"Battery Included": "",
|
|
17
|
+
"Cash Price (XX,XXX) (IF CASH)": "",
|
|
18
|
+
"City": "Madison",
|
|
19
|
+
"City (HVAC)": "",
|
|
20
|
+
"Closer": "Dennis Mason",
|
|
21
|
+
"Closer (HVAC)": "",
|
|
22
|
+
"Confidence": "",
|
|
23
|
+
"Credit Score": "",
|
|
24
|
+
"Current Cooling Method": "",
|
|
25
|
+
"Current Heating Method": "",
|
|
26
|
+
"Current Insulation Level": "",
|
|
27
|
+
"Customer Sounds...": "",
|
|
28
|
+
"Customer Sounds...(HVAC)": "",
|
|
29
|
+
"Date Sold": "",
|
|
30
|
+
"Date Sold HVAC": "",
|
|
31
|
+
"Discovery Call Disposition": "",
|
|
32
|
+
"Discovery Call Disposition (HVAC)": "",
|
|
33
|
+
"Do You Own Your Home?": "Yes, I own my home",
|
|
34
|
+
"Error Message": "",
|
|
35
|
+
"Financing Options": "",
|
|
36
|
+
"Financing Options HVAC": "",
|
|
37
|
+
"HVAC Experiment Exit Reason": "",
|
|
38
|
+
"Home Photos": [
|
|
39
|
+
"https://services.leadconnectorhq.com/documents/download/u6MD1ZVlILZsqUBWEToQ"
|
|
40
|
+
],
|
|
41
|
+
"Home Photos 2": "",
|
|
42
|
+
"Home Sq Footage": "",
|
|
43
|
+
"House No.": "",
|
|
44
|
+
"How Much Shade Does Your Roof Get?": "NO SHADE",
|
|
45
|
+
"How long does the sun shine on your roof?": "Morning Hours",
|
|
46
|
+
"Installer": "",
|
|
47
|
+
"Installer HVAC": "",
|
|
48
|
+
"Insulation Type ": "",
|
|
49
|
+
"Knowledge Level of Solar Appears...": "",
|
|
50
|
+
"Last Call Audio": "",
|
|
51
|
+
"Last Call Recording": "",
|
|
52
|
+
"Lead Generation Source": "",
|
|
53
|
+
"Lead Generation Source HVAC": "",
|
|
54
|
+
"Lead Mentioned...": "",
|
|
55
|
+
"Lead Mentioned...(HVAC)": "",
|
|
56
|
+
"Master Sheet Row ID": "",
|
|
57
|
+
"Monthly Electricity Bill (XXX)": "",
|
|
58
|
+
"Name on Contract": "",
|
|
59
|
+
"Name on Contract HVAC": "",
|
|
60
|
+
"Net Cost (XX,XXX) (IF CASH)": "",
|
|
61
|
+
"Outbound Dials": 38,
|
|
62
|
+
"Parties Present": "",
|
|
63
|
+
"Parties Present (Sold)": "",
|
|
64
|
+
"Parties Present (Sold) HVAC": "",
|
|
65
|
+
"Personality Type": "",
|
|
66
|
+
"Personality Type (HVAC)": "",
|
|
67
|
+
"Preferred Mount Type": "",
|
|
68
|
+
"Property Type": "",
|
|
69
|
+
"Property Type (HVAC)": "",
|
|
70
|
+
"Proposal Used": "",
|
|
71
|
+
"RECs or SMART Monthly (XX) (IF ME NH MA)": "",
|
|
72
|
+
"RECs or SMART Total (XX) (IF ME NH MA)": "",
|
|
73
|
+
"Roof Age": "",
|
|
74
|
+
"Roof Included": "",
|
|
75
|
+
"Roof Quote": "",
|
|
76
|
+
"Roof Replacement Needed?": "",
|
|
77
|
+
"Roof/Land Space": "",
|
|
78
|
+
"Sale Difficulty": "",
|
|
79
|
+
"Sale Difficulty HVAC": "",
|
|
80
|
+
"Service Needed": "",
|
|
81
|
+
"Setter": "Trevor",
|
|
82
|
+
"Setter Name": "",
|
|
83
|
+
"Setter Name (HVAC)": "",
|
|
84
|
+
"Setter Notes": "CMP & 3rd party solar - 130. Old shingle roof - knows he needs a re-roof. Also knows he needs that big maple removed. Open to both re-roof and tree removal. South facing house and garage. Also has a big open yard. ",
|
|
85
|
+
"Setter Notes (HVAC)": "",
|
|
86
|
+
"Shade?": "",
|
|
87
|
+
"Solar Monthly Payment (XXX)": "",
|
|
88
|
+
"Sold Notes": "",
|
|
89
|
+
"Sold Notes HVAC": "",
|
|
90
|
+
"State": "ME",
|
|
91
|
+
"State (HVAC)": "",
|
|
92
|
+
"State Sold In": "",
|
|
93
|
+
"State Sold In HVAC": "",
|
|
94
|
+
"State You Live In": [
|
|
95
|
+
"ME"
|
|
96
|
+
],
|
|
97
|
+
"Staying with Electric Company (XXX,XXX)": "",
|
|
98
|
+
"Submit Appointment Form": "Submit",
|
|
99
|
+
"Submit HVAC Appointment Form": "",
|
|
100
|
+
"System Size (Zones)": "",
|
|
101
|
+
"System Size KW's": "",
|
|
102
|
+
"System Size kW (X.XX)": "",
|
|
103
|
+
"System Type": "",
|
|
104
|
+
"Total Contract Price": "",
|
|
105
|
+
"Total Contract Price HVAC": "",
|
|
106
|
+
"Total Payment/Month Net of RECs (XXX)": "",
|
|
107
|
+
"Total Rooms ": "",
|
|
108
|
+
"Town": "",
|
|
109
|
+
"Tree Work Included": "",
|
|
110
|
+
"Tree Work?": "",
|
|
111
|
+
"Turn Ai OFF/ON": "",
|
|
112
|
+
"Type of Roof": "",
|
|
113
|
+
"Usable Roof Faces": "",
|
|
114
|
+
"Utility": "",
|
|
115
|
+
"Utility Bill": "",
|
|
116
|
+
"Utility Bill 2": "",
|
|
117
|
+
"Website Form": "",
|
|
118
|
+
"What Is Your Average Monthly Electric Bill?": "$200 - $299",
|
|
119
|
+
"Which Service(s) Are You Interested In?": "",
|
|
120
|
+
"Working or Retired?": "",
|
|
121
|
+
"Zoom Link": "207-640-2933",
|
|
122
|
+
"Zoom Link (HVAC)": "",
|
|
123
|
+
"address1": "1497 E Madison Rd",
|
|
124
|
+
"attributionSource": {},
|
|
125
|
+
"city": "MADISON",
|
|
126
|
+
"contact": {
|
|
127
|
+
"attributionSource": {
|
|
128
|
+
"adGroupId": null,
|
|
129
|
+
"adId": null,
|
|
130
|
+
"adName": null,
|
|
131
|
+
"campaign": null,
|
|
132
|
+
"fbc": "fb.1.1729689299067.IwY2xjawGF1h5leHRuA2FlbQEwAAEdZV-X5KLrpifepApblb3ACNP8MmUdYRZtLEfhvFB9Z6fLVzlteTo--peJ_aem_lhMfmbuDOb5CGV8MeAgStg",
|
|
133
|
+
"fbclid": "IwY2xjawGF1h5leHRuA2FlbQEwAAEdZV-X5KLrpifepApblb3ACNP8MmUdYRZtLEfhvFB9Z6fLVzlteTo--peJ_aem_lhMfmbuDOb5CGV8MeAgStg",
|
|
134
|
+
"fbp": "fb.1.1729689299073.654586709248751541",
|
|
135
|
+
"gaClientId": null,
|
|
136
|
+
"gclid": null,
|
|
137
|
+
"ip": "2605:bcc0:830:7a70::503f",
|
|
138
|
+
"medium": "survey",
|
|
139
|
+
"mediumId": "bLUHkOfPuvrfGIzboF4Q",
|
|
140
|
+
"referrer": "https://l.facebook.com",
|
|
141
|
+
"sessionSource": "Social media",
|
|
142
|
+
"url": "https://mecleanenergy.org/check-your-roof-me?fbclid=IwY2xjawGF1h5leHRuA2FlbQEwAAEdZV-X5KLrpifepApblb3ACNP8MmUdYRZtLEfhvFB9Z6fLVzlteTo--peJ_aem_lhMfmbuDOb5CGV8MeAgStg",
|
|
143
|
+
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
|
|
144
|
+
"utmContent": null,
|
|
145
|
+
"utmKeyword": null,
|
|
146
|
+
"utmMatchtype": null,
|
|
147
|
+
"utmMedium": null,
|
|
148
|
+
"utmSource": null,
|
|
149
|
+
"utmTerm": null
|
|
150
|
+
},
|
|
151
|
+
"lastAttributionSource": {
|
|
152
|
+
"adGroupId": null,
|
|
153
|
+
"adId": null,
|
|
154
|
+
"adName": null,
|
|
155
|
+
"fbc": "fb.1.1776380317423.IwY2xjawROSOtleHRuA2FlbQIxMABicmlkETFkN2NvRVJCVEdwRDBkandKc3J0YwZhcHBfaWQQMjIyMDM5MTc4ODIwMDg5MgABHp0KZbAuP0kjXhDNMDaAmJkutaVKmMGjihj2k5xZg3eMurqUf-LbabBgIOdq_aem_q0LDZkMlTpc1miEhLEKbxA",
|
|
156
|
+
"fbclid": "IwY2xjawROSOtleHRuA2FlbQIxMABicmlkETFkN2NvRVJCVEdwRDBkandKc3J0YwZhcHBfaWQQMjIyMDM5MTc4ODIwMDg5MgABHp0KZbAuP0kjXhDNMDaAmJkutaVKmMGjihj2k5xZg3eMurqUf-LbabBgIOdq_aem_q0LDZkMlTpc1miEhLEKbxA",
|
|
157
|
+
"fbp": "fb.1.1776380317430.57446333976653447",
|
|
158
|
+
"gaClientId": null,
|
|
159
|
+
"gaSessionId": null,
|
|
160
|
+
"gbraid": null,
|
|
161
|
+
"gclid": null,
|
|
162
|
+
"ip": "2603:7083:75f0:30e0:f445:d46a:1d9d:c214",
|
|
163
|
+
"medium": "survey",
|
|
164
|
+
"mediumId": "LK64EEG1sbtNUjBq9rmW",
|
|
165
|
+
"referrer": "https://l.facebook.com",
|
|
166
|
+
"sessionSource": "Social media",
|
|
167
|
+
"url": "https://www.statecleanenergy.org/survey?fbclid=IwY2xjawROSOtleHRuA2FlbQIxMABicmlkETFkN2NvRVJCVEdwRDBkandKc3J0YwZhcHBfaWQQMjIyMDM5MTc4ODIwMDg5MgABHp0KZbAuP0kjXhDNMDaAmJkutaVKmMGjihj2k5xZg3eMurqUf-LbabBgIOdq_aem_q0LDZkMlTpc1miEhLEKbxA",
|
|
168
|
+
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
|
|
169
|
+
"utmContent": null,
|
|
170
|
+
"utmKeyword": null,
|
|
171
|
+
"utmMatchtype": null,
|
|
172
|
+
"utmMedium": null,
|
|
173
|
+
"utmSource": null,
|
|
174
|
+
"utmTerm": null,
|
|
175
|
+
"wbraid": null
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"contact_id": "BCvZQFoTTVaNBhsVz0MA",
|
|
179
|
+
"contact_source": "MEFB3 MLSP",
|
|
180
|
+
"contact_type": "lead",
|
|
181
|
+
"country": "US",
|
|
182
|
+
"customData": {
|
|
183
|
+
"org": "mylocalpro",
|
|
184
|
+
"project": "crm-automation",
|
|
185
|
+
"type": "Contact"
|
|
186
|
+
},
|
|
187
|
+
"date_created": "2024-10-23T13:16:15.535Z",
|
|
188
|
+
"email": "waggroof925@gmail.com",
|
|
189
|
+
"first_name": "FRANK",
|
|
190
|
+
"full_address": "1497 E Madison Rd, MADISON MAINE 04950",
|
|
191
|
+
"full_name": "FRANK WAGG",
|
|
192
|
+
"last_name": "WAGG",
|
|
193
|
+
"lead_partner_id": "",
|
|
194
|
+
"location": {
|
|
195
|
+
"address": "22 Old Village Rd Sturbridge MA 01566",
|
|
196
|
+
"city": "Sturbridge",
|
|
197
|
+
"country": "US",
|
|
198
|
+
"fullAddress": "22 Old Village Rd Sturbridge MA 01566, Sturbridge MA 01566",
|
|
199
|
+
"id": "1JYeHLJ6v9NBJIidkSIU",
|
|
200
|
+
"name": "My Local Pro",
|
|
201
|
+
"postalCode": "01566",
|
|
202
|
+
"state": "MA"
|
|
203
|
+
},
|
|
204
|
+
"phone": "+12074319604",
|
|
205
|
+
"postal_code": "04950",
|
|
206
|
+
"state": "MAINE",
|
|
207
|
+
"tags": "new lead,mlpskynet,over 48 hours old,3-10 days old (warm leads)",
|
|
208
|
+
"timezone": "America/New_York",
|
|
209
|
+
"triggerData": {},
|
|
210
|
+
"user": {
|
|
211
|
+
"email": "susan.hunt@mylocalpro.com",
|
|
212
|
+
"firstName": "Susan",
|
|
213
|
+
"lastName": "Hunt"
|
|
214
|
+
},
|
|
215
|
+
"workflow": {
|
|
216
|
+
"id": "c8b2e9d7-24f8-4e19-a4e4-208e80a0e62b",
|
|
217
|
+
"name": "Contact Changed Sync"
|
|
218
|
+
}
|
|
219
|
+
}
|