
CEO & Co-founder of Visivo
BI That Integrates with dbt Workflows for Seamless Analytics
Discover how integrating BI tools with dbt workflows creates seamless analytics pipelines with consistent metrics and automated updates.

dbt™ has revolutionized data transformation by bringing software engineering practices to SQL. According to the dbt State of Analytics Engineering, 85% of data teams now use dbt™ for transformations. But many organizations struggle to connect their dbt™-transformed data to business intelligence tools effectively. When BI tools integrate seamlessly with dbt™ workflows, magic happens: metrics stay consistent, changes propagate automatically, and the entire analytics stack works as one cohesive system.
Introduction to dbt and Its Role
dbt™ (data build tool) has become the de facto standard for data transformation in the modern data stack. According to a widely-cited CrowdFlower survey, data scientists spend about 80% of their time on data preparation and cleaning - dbt™ helps automate and standardize this work. It allows data teams to transform raw data into analytics-ready datasets using SQL, while providing version control, testing, and documentation capabilities that were previously impossible with traditional ETL tools. Learn more at docs.getdbt.com.
At its core, dbt™ transforms data within your warehouse using SQL SELECT statements. Instead of extracting data, transforming it externally, and loading it back (ETL), dbt™ operates entirely within the warehouse (ELT), leveraging the warehouse's computational power. For comprehensive BI-as-code practices, see our guide on dbt BI as code integration:
-- models/marts/finance/monthly_revenue.sql
\{\{
config(
materialized='table',
tags=['finance', 'monthly']
)
\}\}
WITH monthly_orders AS (
SELECT
DATE_TRUNC('month', order_date) AS month,
SUM(order_amount) AS gross_revenue,
SUM(discount_amount) AS discounts,
COUNT(DISTINCT customer_id) AS unique_customers
FROM {{ ref('stg_orders') }}
WHERE order_status = 'completed'
GROUP BY 1
)
SELECT
month,
gross_revenue,
discounts,
gross_revenue - discounts AS net_revenue,
unique_customers,
(gross_revenue - discounts) / NULLIF(unique_customers, 0) AS revenue_per_customer
FROM monthly_orders
dbt™ brings structure, testing, and documentation to what was previously ad-hoc SQL scattered across various tools. According to McKinsey Global Institute, data-driven organizations are 23x more likely to acquire customers - consistent metrics from dbt™ enable this data-driven approach. It creates a single source of truth for business logic that can be version controlled, tested, and deployed systematically.
Value of BI-dbt Integration
When BI tools properly integrate with dbt, the benefits compound exponentially. Instead of two separate systems that occasionally sync, you get a unified analytics platform where changes flow seamlessly from transformation to visualization.
Consistent Metric Definitions: The biggest challenge in analytics is ensuring everyone uses the same definitions. When finance calculates revenue one way and sales calculates it another, trust erodes. dbt-integrated BI tools solve this by referencing dbt models directly:
# Visivo dashboard referencing dbt models
dashboards:
- name: executive_dashboard
metrics:
- name: monthly_revenue
source: dbt.marts.finance.monthly_revenue
column: net_revenue
description: "{{ dbt.get_column_description('monthly_revenue', 'net_revenue') }}"
- name: customer_count
source: dbt.marts.customers.customer_summary
column: active_customers
description: "{{ dbt.get_column_description('customer_summary', 'active_customers') }}"
Automatic Documentation Sync: dbt's rich documentation becomes available in your BI tool:
# dbt schema.yml
models:
- name: monthly_revenue
description: "Monthly revenue metrics including gross, net, and per-customer calculations"
columns:
- name: net_revenue
description: "Total revenue after discounts and refunds"
tests:
- not_null
- positive_value
# This documentation appears automatically in the BI tool
Lineage and Impact Analysis: Understanding how changes propagate becomes trivial when BI tools understand dbt's DAG (Directed Acyclic Graph):
# Check impact before making changes
def analyze_dbt_change_impact(model_name):
downstream_models = dbt.get_downstream_models(model_name)
affected_dashboards = []
for model in downstream_models:
dashboards = visivo.get_dashboards_using_model(model)
affected_dashboards.extend(dashboards)
return {
"affected_models": downstream_models,
"affected_dashboards": affected_dashboards,
"affected_users": get_dashboard_users(affected_dashboards)
}
How Integration Works
Successful dbt-BI integration requires thoughtful architecture and the right technical connections:
Using dbt Output Artifacts: dbt generates rich metadata that BI tools can consume:
# Read dbt manifest for model metadata
import json
with open('target/manifest.json') as f:
manifest = json.load(f)
# Extract model information
for model_id, model_data in manifest['nodes'].items():
if model_data['resource_type'] == 'model':
model_name = model_data['name']
model_description = model_data['description']
model_columns = model_data['columns']
# Register model in BI tool
bi_tool.register_data_source(
name=model_name,
description=model_description,
schema=model_columns,
freshness=model_data.get('freshness'),
tests=model_data.get('tests')
)
API Integration: Modern BI tools can query dbt Cloud's API for real-time information:
# BI tool configuration
integrations:
dbt_cloud:
account_id: ${DBT_ACCOUNT_ID}
api_key: ${DBT_API_KEY}
sync_settings:
- sync_documentation: true
- sync_tests: true
- sync_freshness: true
- sync_lineage: true
webhooks:
- on_dbt_run_complete: refresh_dashboards
- on_dbt_test_failure: alert_dashboard_users
Aligned Deployment Pipelines: Coordinate dbt runs with BI updates:
# GitHub Actions workflow
name: Analytics Pipeline
on:
push:
branches: [main]
jobs:
transform:
name: Run dbt transformations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run dbt
run: |
dbt deps
dbt run
dbt test
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dbt-artifacts
path: target/
update_bi:
name: Update BI dashboards
needs: transform
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v2
with:
name: dbt-artifacts
- name: Update dashboard metadata
run: |
visivo sync --from-dbt-manifest target/manifest.json
- name: Refresh dashboards
run: |
visivo refresh --all-dashboards
- name: Validate dashboards
run: |
visivo test --check-dbt-references
Achieving Seamless Analytics
When dbt and BI tools work in harmony, analytics becomes truly seamless:
Automatic Change Propagation: Changes in dbt models automatically update dashboards:
# Automatic update flow
dbt_model_change:
trigger: git_push
pipeline:
- stage: dbt_run
action: |
dbt run --models {{ changed_models }}
dbt test --models {{ changed_models }}
- stage: update_bi_metadata
action: |
visivo metadata refresh --models {{ changed_models }}
- stage: refresh_affected_dashboards
action: |
affected_dashboards=$(visivo lineage get-dashboards --models {{ changed_models }})
visivo refresh --dashboards ${affected_dashboards}
- stage: notify_users
action: |
visivo notify --message "Dashboards updated with latest data model changes"
Unified Testing Framework: Test data quality and dashboard accuracy together:
# Integrated testing
tests:
# dbt tests ensure data quality
dbt_tests:
- unique:
column: customer_id
model: dim_customer
- relationships:
from: fct_orders.customer_id
to: dim_customer.customer_id
# BI tests ensure dashboards work
dashboard_tests:
- name: revenue_dashboard_loads
dashboard: executive_revenue
assertions:
- all_charts_render: true
- load_time: < 3000ms
- name: metrics_match_source
dashboard: executive_revenue
assertion: |
dashboard.total_revenue ==
query("SELECT net_revenue FROM dbt.marts.finance.monthly_revenue").sum()
Consistent Development Experience: Developers work with a unified toolchain:
# Developer workflow
# 1. Create new metric in dbt
echo "
SELECT
customer_id,
COUNT(*) as order_count,
AVG(order_value) as avg_order_value
FROM {{ ref('fct_orders') }}
GROUP BY customer_id
" > models/marts/customers/customer_order_summary.sql
# 2. Test the model
dbt run --models customer_order_summary
dbt test --models customer_order_summary
# 3. Automatically available in BI tool
visivo develop
# New model appears in data source list
# Can immediately use in dashboards
# 4. Deploy together
git add .
git commit -m "Add customer order summary metric"
git push # Triggers integrated deployment
Real-time Freshness Monitoring: Know exactly how fresh your dashboard data is:
# Freshness configuration
freshness_monitoring:
sources:
- name: dbt.marts.finance
freshness: {{ dbt.source_freshness('finance') }}
- name: dbt.marts.customers
freshness: {{ dbt.source_freshness('customers') }}
display:
show_on_dashboard: true
location: top_right
format: "Last updated: {timestamp} ({age})"
alerts:
- condition: age > 2 hours
severity: warning
- condition: age > 6 hours
severity: critical
action: page_on_call
Organizations with integrated dbt-BI workflows report:
- Zero metric discrepancies between reports
- Significantly faster dashboard development
- Dramatic reduction in "why are these numbers different?" investigations
- 100% traceable data lineage from source to dashboard
The future of analytics is integrated. When dbt handles transformation and BI tools handle visualization as part of one cohesive system, the result is analytics that's consistent, reliable, and trustworthy. The days of disconnected transformation and visualization are over—modern teams demand and deserve seamless integration.