# BigQuery: insert row

The **BigQuery: insert row** Point template streams one row into a BigQuery table through the streaming insert API.

Like Google Sheets: add row, this point authenticates through the Google account connected once for the whole account — there's no token field on the point itself.

## Before you start

Connect a Google account under **Settings > 3rd-party integrations > Google** — the same connection [Google Sheets: add row](/product/customer-journey/journey-elements/integrations/google-sheets-add-row/) uses.

<Aside type="note">
This is not the **Google BigQuery** card on that page. That one is the [BigQuery integration](/product/integrations/google-bigquery-integration/): it streams every message event of an application into a fixed schema on a service account key. This point writes one row you define, at the step you place it on, and takes no key of its own.
</Aside>

<Aside type="caution">
If you connected Google before BigQuery support was added, reconnect it once. A connection keeps the permissions it was granted with, so an older one can write to Sheets but not to BigQuery, and the point fails with a `403`.
</Aside>

Two things also need to be in place on the Google Cloud side, or the request fails:
* The dataset and the table have to exist already — this point writes rows, it never creates a table.
* The connected Google account needs the **BigQuery Data Editor** role (or any role granting `bigquery.tables.updateData`) on that dataset.

## Configure the point

1. Drag **BigQuery: insert row** from the **Integrations** section of the left panel onto the canvas.
2. Double-click the point and enter a **Step Name**.
3. In **Project ID**, enter the Google Cloud project ID — the id, not the display name, for example `my-analytics-prod`.
4. In **Dataset**, enter the dataset name.
5. In **Table**, enter the table name.
6. In **Columns**, add the column name mapped to the value to write — see [key/value fields](/product/customer-journey/journey-elements/integrations/#configuring-list-and-keyvalue-fields). Every column you list has to exist in the table's schema.
7. Click **Save**.

## Reading a failed request

Open [Calls log](/product/customer-journey/journey-elements/channels/webhook/#calls-log) in the point's drawer and check the response:

* **401** — the Google connection is missing or expired; reconnect it under **Settings > 3rd-party integrations**.
* **403 with `accessDenied: Streaming insert is not allowed in the free tier`** — the project has no billing account attached. Streaming inserts, which is what this point uses, are not part of the BigQuery sandbox; enable billing on the project and the same request goes through.
* **403 with `accessDenied` or `insufficientPermissions`** — the connection was granted before BigQuery support was added (reconnect it), or the Google account has no write access to the dataset.
* **403 with `quotaExceeded` or `rateLimitExceeded`** — the project's streaming insert quota is spent; nothing to reconnect, the journey has to send less or the quota has to be raised in Google Cloud.
* **404** — the project, dataset, or table name doesn't match anything.

<Aside type="caution">
A row BigQuery rejects — an unknown column, a value that doesn't fit the column's type — comes back as **200 with an `insertErrors` body**, not as an error status. The traveler moves on as if the write succeeded. The first such message is written into the `bigquery_insert_error` traveler attribute, so you can branch on it with a [Condition split](/product/customer-journey/journey-elements/flow-controls/segment-split/) right after this point, and the full body is in the Calls log.
</Aside>

A failed request drops the traveler from the journey — see [Errors and failed requests](/product/customer-journey/journey-elements/integrations/#errors-and-failed-requests).