Sales Lab · BI connectors
Pipe Sales Lab into your warehouse.
Two read-only Postgres views, RLS-scoped to your company. Point anything that speaks JDBC at them. No ETL job to run.
Get your credentials
Open /admin/api-tokens and create a token with scope warehouse:read. The token maps to a read-only Postgres role; we’ll DM you the host + port after you create it.
Looker
LookML model — one connection, both views.
# In looker.yml or your admin → connections UI:
# host: warehouse.saleslab.cloud
# port: 5432
# user: rls_<your_token>
# database: saleslab
# SSL: require
connection: "saleslab"
include: "*.view.lkml"
view: warehouse_session_scores {
sql_table_name: public.warehouse_session_scores ;;
dimension: session_id { primary_key: yes }
dimension: user_id {}
dimension_group: scored { type: time; sql: ${TABLE}.scored_at ;; }
measure: avg_overall { type: average; sql: ${TABLE}.overall_score ;; }
}Tableau
Generic ODBC / Postgres connector.
Tableau → Connect → PostgreSQL Server: warehouse.saleslab.cloud Port: 5432 Database: saleslab Username: rls_<your_token> Password: <your_token> Require SSL: yes Drag warehouse_session_scores onto the canvas. Drag warehouse_skill_progress next to it; join on user_id + a date range. Optional: publish the workbook to Tableau Cloud with embedded credentials so the RLS scoping carries through.
Snowflake
External table over Postgres FDW or scheduled COPY.
-- Option A: foreign table (preferred — live data) CREATE OR REPLACE EXTERNAL TABLE warehouse_session_scores AT LOCATION = '@saleslab/warehouse_session_scores' FILE_FORMAT = (TYPE = PARQUET) AUTO_REFRESH = TRUE; -- Option B: scheduled COPY via Airbyte / Fivetran -- Source: Postgres -- Host: warehouse.saleslab.cloud -- Port: 5432 -- Tables: warehouse_session_scores, warehouse_skill_progress -- Cron: every 15 minutes
dbt
Sources file — point models at our views as sources.
# models/sources.yml
sources:
- name: saleslab
schema: public
database: saleslab
tables:
- name: warehouse_session_scores
identifier: warehouse_session_scores
description: One row per finalized scorecard.
- name: warehouse_skill_progress
identifier: warehouse_skill_progress
description: One row per skill snapshot.
# In your downstream model:
# select user_id, avg(overall_score) as avg_score
# from {{ source('saleslab', 'warehouse_session_scores') }}
# group by 1Schema
warehouse_session_scores
session_id uuid primary key user_id uuid company_id uuid overall_score int verdict text # 'pass', 'review', 'fail' discovery_score real objection_handling_score real control_score real scored_at timestamptz
warehouse_skill_progress
user_id uuid company_id uuid opening real rapport real discovery real active_listening real objection_handling real value_articulation real control_of_call real tone_pace_confidence real next_step_close real staying_on_message real taken_at timestamptz