Google Cloud Storage
The Google Cloud Storage loader imports data files from a GCS bucket into your warehouse. Zeotap lists the files under a bucket prefix, parses each one, and loads the rows into a table you can model, segment, and activate.
Prerequisites
- A Google Cloud Storage bucket containing your data files.
- A Google Cloud service account with read access to the bucket (the Storage Object Viewer role, which grants
storage.objects.getandstorage.objects.list). - A JSON key for that service account.
- A connected warehouse to load the data into.
Authentication
Zeotap authenticates with a service-account JSON key.
- In the Google Cloud Console, go to IAM & Admin → Service Accounts and create (or select) a service account.
- Grant it the Storage Object Viewer role on the bucket you want to read.
- Open the service account, go to Keys → Add Key → Create new key, choose JSON, and download the key file.
- In Zeotap, add a new Google Cloud Storage loader and paste the full contents of the JSON key into the Service Account JSON field.
The key is stored encrypted and is only used to read objects from the configured bucket.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
| Service Account JSON | Secret | Yes | The full service-account key JSON (must have type: service_account). |
| Bucket | Text | Yes | The GCS bucket name (without the gs:// prefix). |
| Prefix | Text | No | Object name prefix to filter which files are read (e.g. exports/2024/). Leave blank to read the whole bucket. |
| File Format | Select | Yes | The format of the files: CSV, JSON (newline-delimited), Parquet, or Avro. |
| Incremental Cursor | Select | No | For incremental syncs, how new files are detected: File name (default) or Last modified time. Ignored for full-refresh syncs. See Sync Behavior. |
All files under the prefix that match the selected format are loaded into a single table.
Supported Formats
| Format | Notes |
|---|---|
| CSV | The first row is treated as the header. Values are loaded as text. Matches .csv and .csv.gz. |
| JSON | Newline-delimited JSON (one JSON object per line, also called JSONL/NDJSON). Matches .json, .jsonl, .ndjson. A single large JSON array is not supported — use newline-delimited objects. |
| Parquet | Column names and types are read from the file’s embedded schema. Matches .parquet and .pq. |
| Avro | Object Container Files (OCF) with a record-type top-level schema. Matches .avro. |
For CSV and JSON, column types are loaded as text and the schema is inferred from the first file. For Parquet and Avro, the schema is read from the file itself, and Parquet column types are preserved.
Parquet files are read into memory in full (the format requires it), so a single Parquet object must be under 512 MB. Split larger datasets into multiple Parquet files under the prefix. CSV, JSON, and Avro stream and have no per-file size limit.
File Layout
- Place files for one logical dataset under a shared prefix (e.g.
exports/orders/) and point the loader at that prefix. - Every matching file under the prefix is combined into one table. The table’s columns are determined by the first file read — all files under the prefix are assumed to share the same schema. Columns present only in later files are dropped, and columns missing from a later file are loaded as
NULL. - Each loaded row includes a
_gcs_filecolumn recording the source object name, so you can trace rows back to their file.
Sync Behavior
The loader supports both full refresh and incremental syncs.
- Full refresh — each run truncates the target table and reads every matching file under the prefix. Use it when files are rewritten in place or the dataset is small.
- Incremental — each run loads only files that are new since the previous run and appends them. Pick how “new” is decided with the Incremental Cursor setting:
| Cursor | How it detects new files | Best for | Trade-offs |
|---|---|---|---|
| File name (default) | Files whose object name sorts lexicographically after the last file loaded. Already-processed keys are skipped server-side (via GCS StartOffset), so listing stays fast even as history grows. | Date- or sequence-partitioned exports where names always increase, e.g. exports/2026/07/16/part-000.json. | Requires fixed-width, always-increasing names. A counter that overflows its padding (part-999 → part-1000) sorts before the cursor and is silently skipped. Files written with an earlier-sorting name after a sync are missed. |
| Last modified time | Files whose last-modified timestamp is after the newest one loaded. | Any layout — catches renamed, backfilled, or edited files regardless of name, as long as their last-modified time is newer than the previous sync. | No naming assumptions, but there is no server-side time filter, so every run lists the whole prefix (cost grows with total object count). A backfilled file written with an older timestamp is at or before the watermark and is skipped. |
Each incremental run appends; it does not truncate. Switching a loader between the two cursor strategies (or from full refresh to incremental) triggers one reprocessing pass — the stored watermark from the other strategy is not reused — which may duplicate rows already loaded.
To keep the warehouse table current, schedule the loader and write new data to the prefix.
Troubleshooting
| Issue | Resolution |
|---|---|
| ”must be a service account key” | The pasted JSON is not a service-account key. Download a key of type service_account from the service account’s Keys tab. |
| Cannot access bucket | The service account lacks read access. Grant it the Storage Object Viewer role on the bucket. |
| No files found with prefix | No objects under the prefix match the selected format. Check the prefix value and confirm the files have the expected extension (.csv, .json, .parquet, .avro). |
| Wrong or missing columns (CSV) | The first row must be a header row. Confirm the file is delimited correctly and the header matches the data. |
| JSON rows skipped | Lines that are not valid JSON objects are skipped. Confirm the file is newline-delimited JSON (one object per line), not a single JSON array. |
| Type mismatches | CSV and JSON values are loaded as text. Cast or transform them in a downstream model. Parquet and Avro preserve their source types. |
Next Steps
- Create a Model over the loaded table.
- Build an Audience from the modeled data.