Kommo + Domo: enterprise BI sales dashboard with CRM data
Domo is an enterprise cloud BI platform: 1000+ ready-made connectors (Salesforce, Google Ads, Shopify), DataSet API for custom sources, live dashboards, and Domo Apps for interactive tools. It is used in enterprise companies where data from multiple sources needs to be consolidated into a single dashboard for leadership. Unlike Grafana or Metabase, Domo is positioned as a no-SQL BI for business users with less technical depth required. There is no native Kommo connector in Domo — we break down the integration via the DataSet API.
Domo vs Tableau vs Grafana for sales analytics
| Parameter | Domo | Tableau | Grafana |
|---|---|---|---|
| Target audience | Business users, enterprise | Data analysts | DevOps, engineers |
| SQL requirements | Minimal | Moderate | High |
| Ready-made connectors | 1000+ | 100+ | 50+ |
| DataSet API (push) | Yes | Via REST API | Yes (InfluxDB/Postgres) |
| Live dashboards | Yes | Yes | Yes |
| Price | Enterprise (from ~$83/user/month) | from $70/user/month | Open-source (self-host) |
| Native Kommo | No | No | No |
Domo is chosen by enterprise companies where BI dashboards are consumed by management without a technical background and data comes from 5+ different sources.
Architecture: Kommo -> Domo DataSet
The Domo DataSet API allows creating a DataSet and pushing rows to it via HTTP. For Kommo: a cron job running every hour exports deals and contacts -> replaces data in the Domo DataSet -> Domo automatically updates dashboards.
Kommo API -> Python cron -> Domo DataSet API (replace/append)
↓
Domo Dashboard (auto-refresh)
Domo OAuth 2.0 and DataSet API
Domo uses OAuth 2.0 client credentials flow. The client is created in Domo -> Admin -> OAuth Apps -> New Client.
import requests
from datetime import datetime, timezone
DOMO_CLIENT_ID = "your_client_id"
DOMO_CLIENT_SECRET = "your_client_secret"
DOMO_BASE = "https://api.domo.com"
def get_domo_token() -> str:
resp = requests.post(
f"{DOMO_BASE}/oauth/token",
params={
"grant_type": "client_credentials",
"scope": "data",
},
auth=(DOMO_CLIENT_ID, DOMO_CLIENT_SECRET),
)
resp.raise_for_status()
return resp.json().get("access_token", "")
def get_domo_headers() -> dict:
token = get_domo_token()
return {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
def create_domo_dataset(name: str, columns: list) -> str:
# columns: [{"name": "deal_id", "type": "LONG"}, ...]
# types: STRING, LONG, DOUBLE, DECIMAL, DATE, DATETIME
payload = {
"name": name,
"schema": {"columns": columns},
}
resp = requests.post(
f"{DOMO_BASE}/v1/datasets",
headers=get_domo_headers(),
json=payload,
)
resp.raise_for_status()
return resp.json().get("id", "")
def replace_domo_dataset(dataset_id: str, csv_data: str):
# Full data replacement (not append) - for hourly sync
headers = get_domo_headers()
headers["Content-Type"] = "text/csv"
resp = requests.put(
f"{DOMO_BASE}/v1/datasets/{dataset_id}/data",
headers=headers,
params={"updateMethod": "REPLACE"},
data=csv_data.encode("utf-8"),
)
resp.raise_for_status()
def append_domo_dataset(dataset_id: str, csv_data: str):
# Add rows without replacement - for event-based updates
headers = get_domo_headers()
headers["Content-Type"] = "text/csv"
resp = requests.put(
f"{DOMO_BASE}/v1/datasets/{dataset_id}/data",
headers=headers,
params={"updateMethod": "APPEND"},
data=csv_data.encode("utf-8"),
)
resp.raise_for_status()
Kommo -> Domo export: main sync
import csv, io
DEALS_DATASET_ID = "your_deals_dataset_id"
CONTACTS_DATASET_ID = "your_contacts_dataset_id"
DEAL_COLUMNS = [
{"name": "deal_id", "type": "LONG"},
{"name": "deal_name", "type": "STRING"},
{"name": "stage", "type": "STRING"},
{"name": "pipeline", "type": "STRING"},
{"name": "price", "type": "DOUBLE"},
{"name": "responsible", "type": "STRING"},
{"name": "created_at", "type": "DATETIME"},
{"name": "closed_at", "type": "DATETIME"},
{"name": "is_won", "type": "LONG"},
{"name": "is_lost", "type": "LONG"},
{"name": "contact_email", "type": "STRING"},
{"name": "contact_name", "type": "STRING"},
{"name": "source", "type": "STRING"},
]
def export_kommo_to_domo():
leads = get_all_kommo_leads() # paginated API traversal
buf = io.StringIO()
writer = csv.DictWriter(buf, fieldnames=[c["name"] for c in DEAL_COLUMNS])
writer.writeheader()
for lead in leads:
contact = get_kommo_contact_for_lead(lead["id"])
writer.writerow({
"deal_id": lead["id"],
"deal_name": lead.get("name", ""),
"stage": get_stage_name(lead.get("status_id")),
"pipeline": get_pipeline_name(lead.get("pipeline_id")),
"price": lead.get("price") or 0,
"responsible": get_user_name(lead.get("responsible_user_id")),
"created_at": format_dt(lead.get("created_at")),
"closed_at": format_dt(lead.get("closed_at")),
"is_won": 1 if lead.get("status_id") == WON_STATUS_ID else 0,
"is_lost": 1 if lead.get("closed_at") and lead.get("status_id") != WON_STATUS_ID else 0,
"contact_email": get_contact_email(contact) if contact else "",
"contact_name": contact.get("name", "") if contact else "",
"source": get_custom_field(lead, SOURCE_FIELD_ID) or "",
})
replace_domo_dataset(DEALS_DATASET_ID, buf.getvalue())
# Run via cron every hour
# 0 * * * * python sync_kommo_domo.py
Domo DataFusion: combining with other sources
The key advantage of Domo is combining Kommo data with data from Google Ads, Stripe, and HubSpot via DataFusion (JOIN without SQL):
- Kommo deals DataSet + Google Ads campaigns DataSet -> acquisition cost by source
- Kommo deals DataSet + Stripe charges DataSet -> cohorts by payment plan
- Kommo contacts DataSet + HubSpot contacts DataSet -> duplicates across systems
DataFusion is configured in the Domo UI via drag-and-drop JOIN without writing code.
Real case
Enterprise B2B (US, 50 employees, Kommo + Domo + Salesforce):
- Before: revenue data in Kommo, ad data in Google Ads, financials in QuickBooks. Weekly Excel report for the CFO was assembled manually in 4–5 hours.
- After: Kommo -> Domo DataSet (hourly), Google Ads -> Domo (native connector), QuickBooks -> Domo (native). DataFusion JOIN in Domo -> single dashboard. CFO sees live CAC, pipeline velocity, revenue breakdown without Excel.
- Additionally: Domo Alert — if conversion rate drops below 15% -> push notification to CFO and Head of Sales.
Who should use this
- Enterprise companies with multiple data sources (CRM + ad platforms + ERP + billing)
- CFOs and Heads of Sales who need live dashboards without technical involvement
- Companies where Domo is already the corporate BI standard
- Teams where Kommo data needs to be combined with data outside the CRM via DataFusion
Frequently asked questions
Domo Connector vs DataSet API — which to use for Kommo?
Domo has ready-made connectors for Salesforce, HubSpot, and Pipedrive. There is no ready connector for Kommo. The only path is the DataSet API (HTTP push). Create a DataSet with the required schema -> push CSV every hour via cron. This is standard practice for systems without a native connector.
Domo DataSet: REPLACE vs APPEND — when to use which?
REPLACE fully replaces DataSet data on each sync. APPEND adds rows. For Kommo deals, REPLACE with a full dump of all deals is recommended — this guarantees accuracy when data changes (stage, budget, responsible user change). APPEND makes sense only for immutable events (activity log, call log).
How do you keep the OAuth 2.0 token current?
The Domo access_token lives for 1 hour. Pattern: call get_domo_token() before each batch request, do not cache for longer than 55 minutes. For long operations (large DataSet) — refresh the token within the process via a requests.Session with automatic retry.
Can Domo Alerts be configured on Kommo data?
Yes. In Domo -> Alerts you can set a condition on any DataSet metric: “if average time in the ‘Negotiation’ stage > 14 days -> notify the manager”. Notifications via email, Slack, or Domo Buzz. Configured in the UI without code.
Summary
- Auth: OAuth 2.0 client credentials,
POST /oauth/tokenwith scopedata - DataSet created once:
POST /v1/datasetswith column schema - Data push:
PUT /v1/datasets/{id}/datawith CSV, updateMethod=REPLACE (hourly cron) - DataFusion: JOIN Kommo DataSet with Google Ads, Stripe, QuickBooks in Domo UI
- Domo Alerts: metric-based notifications without code
If you have Kommo and Domo and want to see CRM data in an enterprise BI dashboard — describe which sources are already connected to Domo. Exceltic.dev will configure the DataSet sync in 1–2 business days.