Available for work — Book a 30-minute call

CRM Account Ownership Migration

A programme to move a healthcare business's entire marketing and CRM stack out of an agency-controlled sub-account into an account it owns outright. A read-only audit established exactly what existed — and reduced the apparent rebuild from 141 automations to the ~33 that were actually live. The central finding shaped everything that followed: the platform's API can copy data but not automation logic, so workflows, funnels and forms had to be rebuilt by hand. Custom PowerShell tooling handled discovery, dry-run and execute migrations with full ID mapping, and schema-parity verification. The coupled automation layer was migrated by duplicating each workflow and repointing the copy — leaving the live originals untouched, so rollback was simply "don't switch".

Role
Built and shipped
Sector
Massage therapy
Status
In progress at last evidence — critical path is external (telephony registration and DNS)
Stack
GoHighLevel API v2, n8n, PowerShell, Cliniko, Twilio, Meta

The problem

The client's entire marketing and CRM system lived inside a sub-account controlled by a third-party agency. They could have been locked out at any time and had no way to take a snapshot of their own business. There was no cooperation to rely on, so everything had to be discoverable read-only, through the API, without touching anything.

What was built

Nine PowerShell tools covering discovery, export, comparison and push, with dry-run and execute modes and full ID mapping; five core advisory documents; sixteen migration sub-documents; and a duplicate-and-repoint strategy for the automation layer.

The audit came first, and it was the most valuable single output. It returned precise numbers: 141 automations but only 36 published, 61 custom fields, 114 tags, 9 pipelines, 4 calendars, 6 forms, and 12 funnels of which exactly one was genuinely the client's. The rest was agency template clutter.

That reframed the entire project. The real rebuild is roughly 33 live automations and one funnel — not 141 and 12. That is the difference between an impossible project and a scoped five-to-seven-week one.

The hard part

The platform's API copies data but not automation logic. Contacts, opportunities and custom fields migrate cleanly. Workflows, funnels and forms cannot be exported at all — they have to be rebuilt by hand in the new account. Discovering that early, and telling the client plainly, is what made the plan honest.

The second decision was the automation layer. Six n8n workflows were coupled to the old account. Rather than repointing the live workflows — which would have meant a hard cutover with no way back — each workflow was duplicated and the copy repointed at the new account, leaving the originals untouched and running. Rollback became "don't switch", which is the cheapest rollback there is.

What can be verified

  • Audit figures as above
  • four contact-export snapshots and four opportunity exports captured, each with ID maps and skipped-record reports
  • schema comparison run twice
  • four of six workflow duplicates fully repointed and validating clean, one complete bar optional hardening, one deliberately left dormant because its original had zero executions
  • a documented, gated plan whose critical path is external dependencies, not build capacity.

The workflows

An n8n graph titled as a repointed duplicate: a schedule and manual trigger read future appointments from a practice-management API, flatten and filter them, then loop each one through a patient lookup, a two-stage CRM contact search, and either an update to the matched contact or a skipped-log entry, with a summary row appended to a sheet. (select to enlarge)
One of the repointed workflows. There is no single graph that is this project - the work was moving ten of these onto a new CRM account, and each one carries the [NEW GHL] prefix that marks it as the migrated copy. The prefix itself is in the cropped title strip, along with the client name. Select the image to enlarge it — a graph this wide is not legible on a phone.
An n8n graph: a schedule or manual trigger reads past appointments from a practice-management API, groups them to find each patient’s last attended date, then loops through patient lookup, a CRM contact search, and an update writing that date onto the matched contact. (select to enlarge)
A second repointed workflow, writing each patient’s last visit date onto the CRM contact. Same shape, same [NEW GHL] prefix, different field. Select the image to enlarge it — a graph this wide is not legible on a phone.
An n8n graph running every fifteen minutes: it builds a sync window, fetches individual appointments, normalises them, and for each one reads the patient, appointment type and practitioner before building a payload and posting it to a CRM webhook, then commits a cursor. (select to enlarge)
A third, syncing one service line into the new CRM. Its title strip named two of the client’s own treatment products, so on this one the crop is doing real work rather than housekeeping. Select the image to enlarge it — a graph this wide is not legible on a phone.

On numbers: every figure above is an artefact count or a measured technical value. No business-outcome metric, whether time saved, revenue or conversion, was captured on these engagements, so none is claimed.

On status: reflects repository evidence and platform backups, not a live systems check.

Book a 30-min call