> ## Documentation Index
> Fetch the complete documentation index at: https://docs.permutive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Google BigQuery

> Stream first-party event data to Google BigQuery via routing and import audience data for cohort building and activation

export const NoBadge = () => {
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.5rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: '#F7D0E2',
    color: '#1A1A1A',
    fontWeight: '500'
  }}>
      No
    </span>;
};

export const YesBadge = () => {
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.5rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: '#C7E8F9',
    color: '#1A1A1A',
    fontWeight: '500'
  }}>
      Yes
    </span>;
};

export const BadgeRowCenter = ({label, children}) => {
  return <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '0.5rem'
  }}>
      <span style={{
    fontSize: '0.625rem',
    color: '#6b7280',
    textTransform: 'uppercase',
    fontWeight: '500',
    letterSpacing: '0.05em'
  }}>
        {label}
      </span>
      {children}
    </div>;
};

export const BadgeRow = ({label, children}) => {
  return <div style={{
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    marginBottom: '0.5rem'
  }}>
      <span style={{
    fontSize: '0.625rem',
    color: '#6b7280',
    textTransform: 'uppercase',
    fontWeight: '500',
    letterSpacing: '0.05em'
  }}>
        {label}
      </span>
      {children}
    </div>;
};

export const BadgeContainer = ({children}) => {
  return <div style={{
    display: 'flex',
    gap: '0.25rem',
    flexWrap: 'wrap',
    justifyContent: 'flex-end',
    minWidth: '0',
    flex: '1'
  }}>
      {children}
    </div>;
};

export const ProductRequiredBadge = ({product}) => {
  const getBadgeStyle = product => {
    switch (product) {
      case 'Core Platform':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      case 'Routing':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      case 'Contextual':
        return {
          background: '#CB88FC',
          color: '#1A1A1A'
        };
        --purple;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(product);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {product}
    </span>;
};

export const SdkRequiredBadge = ({required}) => {
  const getBadgeStyle = required => {
    switch (required) {
      case 'Yes':
        return {
          background: '#C7E8F9',
          color: '#1A1A1A'
        };
        --blue;
      case 'No':
        return {
          background: '#F7D0E2',
          color: '#1A1A1A'
        };
        --pink;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(required);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {required}
    </span>;
};

export const CapabilityBadge = ({capability}) => {
  const getBadgeStyle = capability => {
    switch (capability) {
      case 'Event Collection':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Cohort Activation':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Campaign Optimization':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Identity Signal':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Contextual Signal':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Connectivity':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Routing':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      case 'Data Collaboration':
        return {
          background: '#EFDFC8',
          color: '#1A1A1A'
        };
        --clay;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(capability);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500',
    whiteSpace: 'nowrap'
  }}>
      {capability}
    </span>;
};

export const EnvironmentBadge = ({environment}) => {
  const getBadgeStyle = environment => {
    switch (environment) {
      case 'Web':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'iOS':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'Android':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'CTV':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      case 'API Direct':
        return {
          background: '#F9C1A8',
          color: '#1A1A1A'
        };
        --peach;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(environment);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500',
    whiteSpace: 'nowrap'
  }}>
      {environment}
    </span>;
};

export const DirectionBadge = ({direction}) => {
  const getBadgeStyle = direction => {
    switch (direction) {
      case 'Bidirectional':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      case 'Destination':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      case 'Source':
        return {
          background: '#FA8784',
          color: '#1A1A1A'
        };
        --tomato;
      default:
        return {
          background: '#A7B3D9',
          color: '#1A1A1A'
        };
        --haze;
    }
  };
  const style = getBadgeStyle(direction);
  return <span style={{
    display: 'inline-block',
    padding: '0.125rem 0.375rem',
    borderRadius: '0.25rem',
    fontSize: '0.625rem',
    background: style.background,
    color: style.color,
    fontWeight: '500'
  }}>
      {direction}
    </span>;
};

<Card title="">
  <div style={{ display: 'flex', alignItems: 'center', marginBottom: '1rem' }}>
    <div style={{ width: '32px', height: '32px', marginRight: '0.75rem', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
      <img src="https://mintcdn.com/permutive/pNhz39ducTVcQczh/images/integrations/logos/bigquery.svg?fit=max&auto=format&n=pNhz39ducTVcQczh&q=85&s=e6948133e1d72f598df509c2989d3766" alt="Google BigQuery" style={{ maxWidth: '32px', maxHeight: '32px', display: 'block' }} width="512" height="512" data-path="images/integrations/logos/bigquery.svg" />
    </div>

    <h3 style={{ margin: 0, fontSize: '1.125rem', fontWeight: '600' }}>Google BigQuery</h3>
  </div>

  <div style={{ marginBottom: '1rem' }}>
    <BadgeRowCenter label="Direction">
      <DirectionBadge direction="Bidirectional" />
    </BadgeRowCenter>

    <BadgeRowCenter label="Environment">
      <BadgeContainer>
        <EnvironmentBadge environment="Web" />

        <EnvironmentBadge environment="iOS" />

        <EnvironmentBadge environment="Android" />

        <EnvironmentBadge environment="CTV" />

        <EnvironmentBadge environment="API Direct" />
      </BadgeContainer>
    </BadgeRowCenter>

    <BadgeRowCenter label="Capability">
      <BadgeContainer>
        <CapabilityBadge capability="Connectivity" />

        <CapabilityBadge capability="Routing" />
      </BadgeContainer>
    </BadgeRowCenter>

    <BadgeRowCenter label="SDK Required">
      <SdkRequiredBadge required="No" />
    </BadgeRowCenter>

    <BadgeRowCenter label="Product(s) Required">
      <BadgeContainer>
        <ProductRequiredBadge product="Core Platform" />

        <ProductRequiredBadge product="Routing" />
      </BadgeContainer>
    </BadgeRowCenter>
  </div>

  <p style={{ margin: 0, fontSize: '0.875rem', color: '#6b7280', lineHeight: '1.5' }}>
    Google BigQuery enables publishers to analyze large datasets for audience insights, campaign performance, and ad optimization.
  </p>
</Card>

<CardGroup cols={2}>
  <Card title="Setup" href="#setup" icon="gear" />

  <Card title="Troubleshooting" href="#troubleshooting" icon="wrench" />
</CardGroup>

## Overview

The BigQuery integration enables publishers to leverage Permutive's bi-directional data capabilities with their BigQuery data warehouse. This integration operates in two modes:

**Routing (Destination)**: Stream first-party event data from Permutive to BigQuery. Read more in [Routing](/products/connectivity/routing) documentation.

<Note>
  Routing capability requires the Routing package in addition to Core Platform. Contact your Customer Success Manager to enable Routing.
</Note>

**Connectivity (Source)**: Import audience data from your BigQuery warehouse into Permutive for cohort building and activation across your publisher inventory.

Key Routing capabilities include:

* Automatic schema generation and updates for new event types and properties
* Day-partitioned tables for efficient querying
* Support for all Permutive event data including user events, identities, and segment metadata
* Self-service setup through the Permutive Dashboard

## Environment Compatibility

| Environment    | Supported    | Notes |
| -------------- | ------------ | ----- |
| **Web**        | <YesBadge /> | --    |
| **iOS**        | <YesBadge /> | --    |
| **Android**    | <YesBadge /> | --    |
| **CTV**        | <YesBadge /> | --    |
| **API Direct** | <YesBadge /> | --    |

## Prerequisites

For **Routing (exporting data to BigQuery)**:

* **Google Cloud Platform project**: An active GCP project where BigQuery will store your data
* **BigQuery API enabled**: The BigQuery API must be enabled on your GCP project (enabled by default for new projects)
* **IAM permissions**: Ability to grant IAM roles to service accounts at the project level in Google Cloud Console
* **Project-level access**: Permissions to add service accounts with the BigQuery User role to your GCP project

<Warning>
  Do NOT manually create the BigQuery dataset before configuring the integration. Permutive will automatically create the dataset during setup. If you manually create the dataset, you must grant the Permutive service account the **BigQuery Data Owner** role instead of BigQuery User.
</Warning>

## Setup

<Tabs>
  <Tab title="Routing Streaming Setup">
    ### Overview

    BigQuery Routing enables self-service setup through the Permutive Dashboard. The setup involves configuring a BigQuery destination in the Dashboard and granting a Permutive service account the **BigQuery User** role at the project level in your GCP IAM settings. Permutive automatically creates the dataset and tables -- no manual dataset creation is required.

    ### Prerequisites

    * An active Google Cloud Platform project with the BigQuery API enabled
    * Your GCP **Project ID**, a unique dataset name, and your preferred data location (**US** or **EU**)
    * Permissions to grant IAM roles to service accounts at the project level in Google Cloud Console

    <Warning>
      Do NOT manually create the BigQuery dataset before configuring the integration. If you do, you must grant the Permutive service account the **BigQuery Data Owner** role instead of BigQuery User.
    </Warning>

    For complete setup steps, see [Setting up BigQuery Routing](/guides/connectivity/routing/setting-up-bigquery-routing).

    ### What Happens After Setup

    Once routing is active:

    1. **Tables are created automatically** for each event type (e.g., `Pageview_events`, `VideoView_events`)
    2. **Events stream in near real-time** with approximately 5-minute latency
    3. **Schemas update automatically** when you add new event types or properties
    4. **Daily partitions** organize data by event date for efficient querying
  </Tab>

  <Tab title="Connectivity Setup">
    ### Overview

    Connecting BigQuery as a source allows you to import audience data into Permutive for cohort building and activation. The setup involves granting Permutive's service account (`connection@permutive.com`) the **BigQuery Data Viewer** role on your dataset, then creating a connection in the Permutive Dashboard with your GCP Project ID and Dataset name.

    ### Prerequisites

    * A Google Cloud Platform (GCP) account with BigQuery enabled
    * Access to manage IAM permissions on your BigQuery dataset
    * Knowledge of your GCP Project ID and Dataset name

    For the complete setup guide with detailed instructions, see [Connecting to BigQuery](/guides/connectivity/sources/connecting-to-bigquery).

    ### Create an Import

    Once your connection is active, go to **Connectivity > Imports** and click **Create Import**, then select your BigQuery connection.

    For more details on configuring imports, see [Imports](/products/connectivity/imports).
  </Tab>
</Tabs>

## Data Types

The BigQuery Routing integration creates the following tables in your dataset to store different types of data:

<AccordionGroup>
  <Accordion title="Event Tables">
    Permutive creates separate tables for each event type. Tables are named `{event_name}_events` and contain daily partitions based on event date.

    Example tables:

    * `Pageview_events`
    * `VideoView_events`
    * `AffiliateLinkClick_events`

    **Schema**:

    <ResponseField name="time" type="TIMESTAMP">
      Event timestamp in UTC
    </ResponseField>

    <ResponseField name="event_id" type="STRING">
      Unique identifier for the event
    </ResponseField>

    <ResponseField name="user_id" type="STRING">
      Permutive user identifier
    </ResponseField>

    <ResponseField name="session_id" type="STRING" nullable>
      Session identifier
    </ResponseField>

    <ResponseField name="view_id" type="STRING" nullable>
      Page view identifier
    </ResponseField>

    <ResponseField name="segments" type="ARRAY<INTEGER>">
      Array of segment IDs the user belongs to at the time of the event
    </ResponseField>

    <ResponseField name="properties" type="RECORD">
      Event-specific properties stored as a JSON record. Schema varies by event type and is automatically updated when new properties are added.
    </ResponseField>

    <ResponseField name="workspace_id" type="STRING" nullable>
      Workspace identifier
    </ResponseField>
  </Accordion>

  <Accordion title="Identities Table">
    Stores identity resolution data. The table is named `identities` and contains daily partitions.

    **Schema**:

    <ResponseField name="time" type="TIMESTAMP" required>
      Timestamp when the identity was captured
    </ResponseField>

    <ResponseField name="event_type" type="STRING">
      Type of identity event
    </ResponseField>

    <ResponseField name="permutive_id" type="STRING" required>
      Permutive user identifier
    </ResponseField>

    <ResponseField name="id" type="STRING" required>
      External identity value
    </ResponseField>

    <ResponseField name="tag" type="STRING" required>
      Identity tag or namespace
    </ResponseField>

    <ResponseField name="workspace_id" type="STRING">
      Workspace identifier
    </ResponseField>
  </Accordion>

  <Accordion title="Segment Metadata">
    Stores segment definitions and metadata. Permutive creates two objects:

    * **Table**: `segment_metadata_snapshots` - Raw snapshots of segment metadata
    * **View**: `segment_metadata` - Deduplicated view of the latest segment metadata

    **Schema**:

    <ResponseField name="number" type="INT64" required>
      Segment ID number
    </ResponseField>

    <ResponseField name="name" type="STRING" required>
      Segment name
    </ResponseField>

    <ResponseField name="tags" type="ARRAY<STRING>">
      Array of tags associated with the segment
    </ResponseField>

    <ResponseField name="metadata" type="STRING">
      JSON string containing segment configuration and metadata
    </ResponseField>

    <ResponseField name="workspace_id" type="STRING">
      Workspace identifier
    </ResponseField>

    <Note>
      Use the `segment_metadata` view for queries to automatically get deduplicated, up-to-date segment information.
    </Note>
  </Accordion>
</AccordionGroup>

**Key Characteristics**:

* **Automatic Schema Management**: New event types and properties are automatically added to tables without manual intervention
* **Partitioning**: Event and identity tables are partitioned by day for efficient querying and cost optimization

## Troubleshooting

<AccordionGroup>
  <Accordion title="Integration Status Shows 'Failed'">
    **Cause**: The Permutive service account was not granted the correct permissions, or permissions were granted after clicking "Confirm account access granted".

    **Solution**:

    1. Verify the service account has been granted the **BigQuery User** role at the PROJECT level in the [Google Cloud IAM console](https://console.cloud.google.com/iam-admin/iam)
    2. Ensure you selected the correct GCP project
    3. If permissions were granted incorrectly, you will need to restart the integration configuration from the beginning
    4. Contact [Support](mailto:support@permutive.com) if the issue persists after verifying permissions
  </Accordion>

  <Accordion title="Dataset Already Exists Error">
    **Cause**: A dataset with the same name already exists in your BigQuery project.

    **Solution**:

    * **Option 1 (Recommended)**: Use a different dataset name that doesn't already exist in your project
    * **Option 2**: If you must use an existing dataset, grant the Permutive service account the **BigQuery Data Owner** role at the dataset level (not just BigQuery User at project level)
  </Accordion>

  <Accordion title="Service Account Permission Denied">
    **Cause**: Your organization's IAM policies may restrict adding external service accounts, or permissions were not granted at the correct level.

    **Solution**:

    1. Check with your GCP administrator about organization policies that may block external service accounts
    2. Ensure the **BigQuery User** role was granted at the PROJECT level, not the dataset level
    3. Verify your user account has permissions to grant IAM roles in the GCP project
    4. If organization policies block external service accounts, work with your security team to add an exception for `@permutive-routing-production.iam.gserviceaccount.com` domains
  </Accordion>
</AccordionGroup>

## Changelog

<Info>
  No changes listed yet. For detailed changelog information, visit our [Changelog](https://changelog.permutive.com/).
</Info>
