Labs4Change

Looker Explore Best Practices: Labels, Joins, and Field Organization

How to design Looker Explores that business users actually understand. Covers labeling conventions, join best practices, field grouping, and documentation patterns.

Your Explores are the interface between your data model and your business users. A well-designed Explore makes self-service analytics possible. A poorly designed one generates a flood of Slack messages asking "which field do I use?"

Here's how to get them right.


Start With the Business User's Workflow

Before writing any LookML, ask: what questions will people ask this Explore? An Explore called order_items with 200 ungrouped fields is unusable. An Explore called "Customer Orders" with fields organized by Finance, Shipping, and Product categories — that's self-service.

explore: order_items {
  label: "Customer Orders"
  description: "Start here for order-level analysis. Includes customer demographics, product details, and shipping status."
  group_label: "Sales"

  join: customers {
    type: left_outer
    relationship: many_to_one
    sql_on: ${order_items.customer_id} = ${customers.id} ;;
  }
}

The description tells users when to use this Explore. The group_label organizes it in the menu. Both are skipped in 90% of the Looker instances we audit.


Labels: When to Use Them and When Not To

Most fields don't need labels. If the field name is already clear — order_id, created_date, status — adding a label just creates maintenance overhead.

Use labels when:

  • The database column name is abbreviated or cryptic
  • You need to align with business terminology
  • The auto-generated label is misleading
dimension: usr_typ_cd {
  label: "User Type"  # Needed — database name is cryptic
}

dimension: order_id {
  # No label needed — field name is already clear
}

Same rule applies to view labels:

view: itm_dtl {
  label: "Item Detail"  # Needed — view name is abbreviated
}

view: customers {
  # No label needed — view name is clear
}

Field Grouping With group_label

Once an Explore has more than 20-30 fields, grouping becomes essential. Group by business domain, not by data type.

dimension: price {
  group_label: "Order Finance"
  label: "Item Price"
}

dimension: cost {
  group_label: "Order Finance"
  label: "Item Cost"
}

dimension: margin {
  group_label: "Order Finance"
  label: "Item Margin"
  type: number
  sql: ${price} - ${cost} ;;
}

This puts all financial fields together in the Explore sidebar. Users find what they need without scrolling through 100 fields.

Common grouping patterns:

  • Order Finance, Order Status, Order Dates
  • Customer Demographics, Customer Activity, Customer Lifetime
  • Product Details, Product Categories, Product Metrics

Join Best Practices

Always Declare Relationships Correctly

This is the single most impactful join setting in Looker. Get it wrong and your measures will be incorrect — and users won't know.

explore: orders {
  join: customers {
    type: left_outer
    relationship: many_to_one  # Many orders belong to one customer
    sql_on: ${orders.customer_id} = ${customers.id} ;;
  }

  join: order_items {
    type: left_outer
    relationship: one_to_many  # One order has many items
    sql_on: ${orders.id} = ${order_items.order_id} ;;
  }
}

If you declare many_to_one when the actual relationship is one_to_many, Looker won't warn you — it'll just produce wrong numbers.

Every Joined View Needs a Primary Key

Without a primary key, Looker can't properly deduplicate rows. Every view in a join must have one:

view: orders {
  dimension: order_id {
    primary_key: yes
    type: number
    sql: ${TABLE}.order_id ;;
  }
}

For tables without a natural primary key, create a composite key:

view: order_items {
  dimension: composite_key {
    primary_key: yes
    hidden: yes
    sql: ${order_id} || '-' || ${item_id} ;;
  }
}

Field Sets for Drill Paths

Field sets define what users see when they click a value to drill down. Without them, Looker shows all fields — which is overwhelming.

set: order_details {
  fields: [
    order_id,
    created_date,
    status,
    total_amount,
    customer_name
  ]
}

measure: total_revenue {
  type: sum
  sql: ${amount} ;;
  drill_fields: [order_details*]
}

Now when a user clicks a revenue number, they see a focused table of order details — not every field in the Explore.


Documentation That Actually Helps

Field Descriptions

Write descriptions that explain business meaning, not just data type:

# Bad
dimension: days_since_signup {
  description: "Number type field"
}

# Good
dimension: days_since_signup {
  description: "Days since customer first signed up. Customers with 0-30 days are considered 'New'. Used in retention cohort analysis."
  type: number
  sql: DATE_DIFF(CURRENT_DATE, ${signup_date}, DAY) ;;
}

Explore Descriptions

Tell users when to use this Explore, what data it includes, and what key filters to apply:

explore: sales {
  description: "Use for analyzing sales performance. Includes customer demographics and product details. Filter by date range first — unfiltered queries are expensive. Key filters: order_date, product_category, region."
}

Let dbt Handle Descriptions

If you use dbt, write your field descriptions there — they flow automatically through BigQuery to Looker:

# In dbt schema.yml
models:
  - name: orders
    description: "Table containing all order information"
    columns:
      - name: order_id
        description: "Unique identifier for each order"
      - name: status
        description: "Current status: Processing, Shipped, or Delivered"

Don't duplicate these descriptions in LookML. Only add Looker-specific context if needed (like drill behavior or filter recommendations).


Common Mistakes We See in Audits

  1. No descriptions on any Explore — users have no idea which one to use
  2. Wrong relationship declarations — measures return incorrect values
  3. Missing primary keys — joins produce duplicated rows
  4. No field grouping — 100+ ungrouped fields in the sidebar
  5. Labels on every field — maintenance nightmare with no benefit
  6. No drill paths defined — users can't explore data interactively
  7. Overly broad Explores — one Explore with 30 joins that answers every question (slowly)

A Checklist for Every Explore

Before deploying a new Explore, verify:

  • label and description are set
  • group_label organizes it in the menu
  • All joins have correct relationship types
  • All joined views have primary_key defined
  • Fields are organized with group_label
  • Key measures have drill_fields
  • Descriptions explain business meaning, not data types
  • The Explore is tested with real user queries

Get the LookML Best Practices Guide + AI Skill

Our complete guide covers project structure, explores, permissions, caching, and more — plus a Claude skill that audits your LookML automatically.


Labs4Change has trained 16,000+ analytics engineers on Looker. Book a free LookML audit — we'll review your Explores, joins, and field organization in 30 minutes.