# Best Practices

## Recommended setup

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Join Opportunities with Pipelines</strong></td><td>The Opportunities entity returns pipeline IDs, not names. Add Pipelines as a second source in the same data flow and use a Join transformation on `pipelineId` to make your reports human-readable.</td></tr><tr><td><strong>Use Append for multi-account reporting</strong></td><td>If you manage multiple GoHighLevel sub-accounts, create one data flow per account and use Append to stack them into a single destination sheet or table. Add a custom column to tag each row with the account name.</td></tr><tr><td><strong>Join Contacts with Opportunities</strong></td><td>Opportunities don't include contact details like email or lead source. Join on `contactId` to enrich your deal data with contact-level attributes for deeper sales analysis.</td></tr></tbody></table>

## Data refresh and scheduling

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Always run manually first</strong></td><td>A successful manual run is required before you can set up a schedule. Use the first run to verify row counts and check that custom fields are appearing as expected before automating.</td></tr><tr><td><strong>Match refresh frequency to your reporting needs</strong></td><td>Sales dashboards updated throughout the day benefit from 15-minute or hourly refreshes (Business plan). Weekly revenue or invoice reports don't need frequent syncs — daily is usually enough and keeps API usage lower.</td></tr></tbody></table>

## Performance optimization

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Filter Appointments and Tasks by Contact ID</strong></td><td>If you only need data for specific contacts, enter their Contact IDs in the parameter field. This fetches far fewer records than pulling all appointments or tasks across the account.</td></tr><tr><td><strong>Don't run overlapping flows for the same account</strong></td><td>Running multiple data flows against the same GoHighLevel account at the same time increases the risk of hitting GHL's API rate limits. Stagger your schedules by at least a few minutes.</td></tr></tbody></table>

## Common pitfalls

{% hint style="danger" %}
Custom fields are only available for Contacts, Opportunities, and Companies. If you build formulas or transformations expecting custom fields from other objects (like Tasks), those fields won't appear — the GoHighLevel API doesn't expose them.
{% endhint %}

{% columns %}
{% column %}
**Do**

* Join Opportunities + Pipelines to get readable pipeline names
* Use Contact IDs to scope Appointments and Tasks to specific records
* Verify row counts on the first manual run before scheduling
* Store formula logic somewhere outside Coupler.io — there is no version history or formula recovery if changes are lost
  {% endcolumn %}

{% column %}
**Don't**

* Expect custom fields from objects other than Contacts, Opportunities, or Companies
* Run multiple flows against the same GHL account at the same time
* Assume a timestamp offset is a data bug — check timezone settings first
* Connect at sub-account level if you need cross-account reporting
  {% endcolumn %}
  {% endcolumns %}
