Conversations model
The conversation model represents threaded discussions and communications — emails, chat threads, calls — that feed sentiment analysis, needle mover detection, and the account timeline. A conversation entry on the timeline shows the subject, sentiment, and a link back to the source.
Managed models from messaging connections
Many workspaces get a Conversation model automatically when you connect a supported messaging integration — for example Intercom, Slack, or Microsoft Teams.
- Add the connection from Data connections.
- Authorize and complete any required setup.
- Under Configuration → Data models, confirm the Conversation model for that connection.
- Refresh and validate on an account with recent conversations.
HubSpot: configuring email conversations
HubSpot email engagements are the most common source for conversation models. FunnelStory syncs them using the HubSpot v3 CRM API scoped to your deal companies, so only emails from accounts you manage are included.
If the HubSpot connection's Sync Emails option is on, FunnelStory already imports these emails as threaded conversations, so skip this model; configuring both imports every email twice.
Prerequisites
- A connected HubSpot data connection.
- The Accounts and Users models must be configured first. The email conversation query resolves
account_idthrough the sender's email address matched tocontacts_v2, which requires contacts to be synced.
Using Claude (recommended)
The fastest way to configure HubSpot email conversations is to ask Claude via the MCP server:
"Configure a HubSpot email conversation model"
Claude reads the data model guide, previews the query against your data, and creates the model in the right order. See Configure HubSpot models with Claude for a full walkthrough.
Manual configuration
Add a Conversation model with the HubSpot connection and the following query:
WITH engs AS (
SELECT
engagements.id,
engagements.timestamp,
engagements.data->'engagement'->>'bodyPreview' AS text,
engagements.data->'metadata'->>'subject' AS subject,
engagements.data->'metadata'->'from'->>'email' AS from_email,
engagements.data->'engagement'->>'portalId' AS portal_id,
contacts_v2.properties->>'associatedcompanyid' AS company_id
FROM engagements
JOIN contacts_v2
ON LOWER(engagements.data->'metadata'->'from'->>'email') = LOWER(contacts_v2.email)
WHERE engagements.type IN ('INCOMING_EMAIL', 'EMAIL')
AND engagements.data->'engagement'->>'bodyPreview' IS NOT NULL
AND engagements.data->'engagement'->>'bodyPreview' != ''
AND engagements.data->'metadata'->'from'->>'email' IS NOT NULL
AND contacts_v2.properties->>'associatedcompanyid' IS NOT NULL
AND contacts_v2.properties->>'associatedcompanyid' != ''
GROUP BY engagements.id, engagements.timestamp, engagements.data,
contacts_v2.properties->>'associatedcompanyid'
)
SELECT
engs.id AS engagement_id,
engs.company_id,
engs.timestamp,
engs.subject,
json_object('type', 'email', 'engagement_id', engs.id, 'source', 'hubspot') AS key,
json_object('title', engs.subject) AS metadata,
json_object('text', engs.text) AS encrypted_data,
'<fs_analyze>' || engs.text AS sentiment,
'<fs_analyze>' || engs.text AS text_analysis,
'<fs_analyze>' || engs.text AS label_analysis
FROM engs
ORDER BY engs.timestamp DESC
Mappings:
| Column | Property |
|---|---|
company_id | account_id |
engagement_id | conversation_id |
timestamp | timestamp |
timestamp | created_at |
sentiment | sentiment |
text_analysis | text_analysis |
label_analysis | label_analysis |
subject | email_subject |
key | key |
metadata | metadata |
encrypted_data | encrypted_data |
The query joins email sender addresses to contacts_v2.email and uses the contact's associatedcompanyid to find the account. This means the sender must be a known HubSpot contact associated with a deal company. Emails from unknown contacts are excluded.
HubSpot notes
The HubSpot connection imports email engagements only, so a HubSpot notes model has nothing to read. Record account notes in FunnelStory instead (Adoption → Notes on the account), or bring them in from another source with a Note model.
Field reference
Model keys
| Property | Type | Description |
|---|---|---|
account_id | string | Account associated with the conversation. |
conversation_id | string | Stable ID for the thread in the source system. |
Default properties
| Property | Type | Description |
|---|---|---|
created_at | timestamp | When the conversation started or was opened. |
sentiment | float | Optional aggregate sentiment score. Pass <fs_analyze> + the text to have FunnelStory compute it automatically. |
Optional properties
| Property | Type | Description |
|---|---|---|
key | json | Structured key for deduplication: {"type": "email", "engagement_id": "...", "source": "hubspot"}. |
metadata | json | Extra display data shown in the timeline tooltip: {"title": "...", "link": "..."}. |
encrypted_data | json | Full text content stored encrypted: {"text": "..."}. |
text_analysis | json | Structured NLP output. Pass <fs_analyze> + text to trigger automatic analysis. |
label_analysis | json | Labels or topics extracted from content. Pass <fs_analyze> + text to trigger automatic labeling. |
email_subject | string | Subject line for email-sourced conversations. |
participants | json | List of participants for meeting or chat conversations. |
Related
- Note model — for notes from other sources
- Support tickets
- Meetings
- Data models overview