Product, billing and single-customer map
Only what changed, only allowed fields, with locks
Properties and associations in the CRM
Lists, tasks and alerts in the CRM itself
What it solves
- Reps and CSMs see usage, plan and payment without leaving the CRM.
- CRM lists and workflows start firing on real product behavior.
- The sync does not duplicate contacts or overwrite what the team filled in.
Business questions it answers
Ask your agent these questions once the case is live.
What you need
- Product database or events and billing connected to Nekt
- The single-customer map with each record's CRM id
- The list of properties the routine is allowed to write
What you get
- Usage, plan and payment properties kept current in the CRM
- Contact, company and deal associations to the product workspace
- A send log per record, with result and error
- CRM lists, tasks and alerts fed by product data
Where to activate
A trial with usage and no contact becomes a sales task; a paying customer with no login for 30 days becomes a CS task.
Plan, status and exit date in the support tool, so support knows who they are talking to.
CRM users and states become lookalike audiences and exclusion lists on the ad platforms.
The calculation is simple. The care goes into not duplicating, not overwriting and locking before writing. Start in dry-run mode, with few properties. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
Sales and CS live in the CRM, but usage, plan and payment status sit in the product database and in billing. The first sync tends to create duplicate contacts, overwrite fields the rep filled in and count internal users' activity as customer usage. Sometimes it brings down the CRM source itself. And the destination writes properties but does not create associations between objects.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
Build one output table per CRM object (company, contact, workspace as a custom object), with the CRM record id on every row. The id comes from the single-customer map, never from an on-the-fly name match. Contacts match by email, lowercased and trimmed.
Separate records that do not exist in the CRM yet (create) from those that do (update). The update routine never creates. The create routine first checks whether the email or domain already exists. Start creation with a small pilot (for example, 15 records) and check the record is still there a few seconds later: CRM anti-duplicate automations have deleted freshly created contacts.
Compare the calculated value with the current CRM value and send only the difference. Example: set active user to No only for people who are Yes in the CRM and became inactive in the product. Sending everything every day burns API quota, fires workflows for nothing and pollutes the property history.
Declare which properties the routine may write. Phone, email and tax ID are filled only when empty. Owner, stage and fields the team edits are never overwritten. Properties written by the routine get their own prefix (for example, lake_ or product_), so nobody edits them by hand.
Remove internal, support and service users (by role, email domain or list), test accounts and demo accounts from the calculation. A user enabled in a company with no current package or subscription is not an active user.
Plan, subscription status (active, past_due, canceled, trialing), MRR and first payment date come from billing, consolidated per customer and not per subscription. With several subscriptions, a declared priority rule picks the status. The first payment date is the date of the first paid charge, not the billing cycle date. Send the data's reference date along with it.
Write indicators the team actually uses (active users in 7 and 30 days, days since last login, modules in use, customer tier), not one field per event or feature. Picklist values are translated and come from a closed list. HubSpot caps a property at 512,000 bytes, and the contacts source fails above 10,000 nested fields; after 3 consecutive failures, it disables itself.
The Nekt destination writes properties by object id, but it does not associate contact to workspace, company to workspace or deal to workspace. Do that in a notebook that compares expected associations with existing ones and creates only the missing ones, with the association label. Run a dry run first: in a real case, two weeks of dry run showed hundreds of associations to create and more than a hundred contacts that did not even exist yet.
The routine checks the target portal or account before writing (sandbox in testing, the expected id in production) and stops if it does not match. It also checks volume: a catalog below the expected minimum or an unusual number of changes means broken source data, and the routine stops instead of deleting options or blanking fields. Every send goes to a log with record, value, result and error. API keys live in the secrets vault, never in code.
Include inactive and deleted accounts in the send, so status and exit date are updated in the CRM and in the support tool. Otherwise CS keeps seeing as active someone who already canceled.
What goes to the CRM, and where it comes from
Properties written by the routine, with their own prefix and a reference date.
Definitions
Pitfalls that already happened
A CRM anti-duplicate automation deleted contacts the routine had just created, and the batch looked successful.
Create a pilot and check the record still exists a few seconds later.
Too many contact properties pushed past the 10,000 nested-field limit; extraction failed three times and the source disabled itself without warning.
Few properties, a review of unused ones and a source failure alert.
Without separating create from update, every run recreated people whose email differed only in letter case.
Lowercase email and a create routine that checks for existence.
Deleted companies were left out of the send and stayed active in the support tool.
Send inactive and deleted accounts with the exit date.
Users of a service run by the team itself worked inside customers' accounts and counted as their active users.
Exclude by user role, as well as email domain and test accounts.
CRM and other tool tokens were written inside notebooks, visible to anyone who opened or versioned the code.
Store them in the Nekt secrets vault and read them with nekt.load_secret.
Acceptance test
The case is done when every item passes.
- For a sample of 20 accounts, plan, status and active users in the CRM match billing and the product on the reference date.
- A second run with no change at the source sends zero records.
- The update routine creates no contacts, and created contacts match the create batch plan.
- No internal, support or test user is counted among active users.
- Every expected association exists in the CRM, and the log has no unhandled error.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
Product usage in the CRM - Properties written by the routine have the prefix <prefix> and carry the data's reference date. The CRM value may lag the product by up to 1 day. - Active user = customer user with a login or event in the last 30 days, excluding internal, support, service and test accounts, in a company with a current plan. - Payment status comes from billing, consolidated per customer: active, past_due, canceled, trialing. Past_due is not canceled. - First payment date = first paid charge with an amount above zero, not the billing cycle date. - The routine never overwrites owner, stage or team-edited fields. Phone, email and tax ID are filled only when empty. - Contact, company and deal associations to the workspace are created by a dedicated routine; a record without an association is not a customer without usage. - If the CRM value differs from the product, the source of truth is the product or billing, not the CRM. Client exceptions: - <client>: users with role <role> are internal and do not count as active. - <client>: customer tier by cumulative volume: <bands>.
Build the "Product usage in the CRM" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/saas/uso-do-produto-no-crm.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
A spreadsheet fed by Nekt is the single source read by an automation (for example, n8n) that distributes to several tools.
Customer tier by cumulative volume (for example, by TPV) sent to the CRM and to the team's task tool.
In self-service, one row per email with total paid and the status of the latest subscription, written to the contact.