InfoSum
Deliver audience and customer data to an InfoSum data bunker for privacy-preserving data collaboration and clean-room activation. Zeotap normalizes identifiers per InfoSum’s specification, serializes each batch as a UTF-8 CSV file, PGP-encrypts the CSV with the InfoSum-provided public key, and drops the .csv.pgp file into your GCS bucket — InfoSum’s bunker then pulls, decrypts, and ingests the file inside its secure environment. Raw customer data never leaves your control.
Prerequisites
Before creating an InfoSum destination in Zeotap, collect the following from your InfoSum and GCS administrators:
- A Google Cloud Storage bucket that the InfoSum bunker is configured to read from
- The bucket name and the folder (path prefix) that InfoSum watches
- A GCP service account JSON key with the permissions listed under Required Permissions on that bucket
- The InfoSum PGP public key provided by your InfoSum representative (ASCII-armored)
- An InfoSum bunker already provisioned in your workspace
- The bucket must not have Requester Pays enabled
Authentication
Zeotap authenticates to the GCS bucket using a service account JSON key.
- In Google Cloud IAM, create or reuse a service account and grant it the permissions listed under Required Permissions on the bucket.
- Download the service account JSON key.
- Paste the full JSON into the Service Account JSON Key field when configuring the destination.
Zeotap only writes files to the agreed bucket; InfoSum decrypts and reads them from inside its bunker using the matching PGP private key.
Required Permissions
The service account needs the following IAM permissions on the target bucket:
| Permission | Used for |
|---|---|
storage.buckets.get | Reading bucket metadata. Used by the connection test and by the bucket check at the start of every sync run. |
storage.objects.create | Uploading the encrypted .csv.pgp files. |
Zeotap writes each file under a unique, timestamped object name and never overwrites or deletes objects in your bucket, so — unlike the general Cloud Storage destination — storage.objects.delete is not required.
No predefined roles/storage.object* role includes storage.buckets.get, so grant one of the following on the bucket:
-
Recommended — a custom role with exactly the two permissions above:
gcloud iam roles create signalsmithInfoSumWriter \ --project=YOUR_PROJECT_ID \ --title="Zeotap InfoSum Writer" \ --permissions=storage.buckets.get,storage.objects.create gcloud storage buckets add-iam-policy-binding gs://YOUR_BUCKET \ --member="serviceAccount:YOUR_SERVICE_ACCOUNT_EMAIL" \ --role="projects/YOUR_PROJECT_ID/roles/signalsmithInfoSumWriter" -
Predefined roles — Storage Object Creator (
roles/storage.objectCreator) plus Storage Legacy Bucket Reader (roles/storage.legacyBucketReader), both granted on the bucket.legacyBucketReadersuppliesstorage.buckets.get;objectCreatorsuppliesstorage.objects.create -
Storage Object User (
roles/storage.objectUser) on the bucket also works — it includesstorage.buckets.getandstorage.objects.create— but grants more than InfoSum needs (object read, list, and delete)
The Storage Object Creator (roles/storage.objectCreator) role alone is not sufficient: it does not include storage.buckets.get, so the connection test and every sync run fail with cannot access bucket.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
| Bucket | text | Yes | Name of the GCS bucket the InfoSum bunker reads from |
| Folder | text | Yes | Folder path (prefix) inside the bucket where Zeotap drops CSV files, e.g. zeotap/audiences/ |
| InfoSum PGP Public Key | textarea (secret) | Yes | ASCII-armored PGP public key provided by InfoSum; every file is encrypted with this key before upload |
Target Settings
| Field | Type | Required | Description |
|---|---|---|---|
| File Format | select | Yes | InfoSum requires UTF-8 CSV with a header row and comma column delimiter. This is the only supported option. |
Supported Operations
Sync Modes
| Mode | Supported | Description |
|---|---|---|
| Insert | Yes | Write the full current dataset as new .csv.pgp files on every run |
| Mirror | Yes | Write changed rows as new .csv.pgp files; removed rows are excluded |
| Upsert | — | Not applicable — InfoSum ingests immutable files |
| Update | — | Not applicable — InfoSum has no row-level update API |
| Snapshot | Yes | Write the complete current dataset as new files on every run — no delta, no _operation column |
Audience Sync Modes
| Mode | Supported | Description |
|---|---|---|
| Add | Yes | Deliver new and updated audience members as new files (departed members excluded) |
| Mirror | Yes | Deliver new and updated members; members who left the audience are excluded |
| Remove | — | Not applicable — InfoSum does not expose a membership-removal endpoint |
| Upsert | — | Not applicable for file-based delivery |
| Snapshot | Yes | Write the complete current membership as new files on every run — no delta, no _operation column |
Features
| Feature | Supported |
|---|---|
| Field Mapping | No |
| Schema Introspection | No |
Data Format
Each sync batch is written as a UTF-8 CSV that conforms to InfoSum’s ingestion requirements:
- Header row — column names are taken from the first row of the batch and sorted alphabetically for deterministic output
- Column delimiter — comma (
,) - Multi-value delimiter — pipe (
|) inside a single cell (must be configured on the InfoSum side to match) - Identifier normalization — Zeotap lowercases and trims every value in recognized identifier columns:
email,email_address,hashed_email,email_sha256,phone,phone_number,mobile,mobile_number,home_phone,aaid,idfa,mobile_id,advertising_id,cookie_id,zip,zip_code,zip5,zip9,postal_code,ip,ip_address,ipv4,ipv6. Phone numbers additionally have all whitespace stripped so E.164 values stay contiguous. IP addresses are parsed and re-emitted in their canonical lowercase form. - Raw identifiers preferred — InfoSum recommends sending raw, unhashed identifiers; the bunker performs hashing and salting internally. Sending a
hashed_emailcolumn is also supported.
Supported Identifiers
| Identifier | Formats InfoSum accepts |
|---|---|
| Raw, SHA-256 | |
| Phone | E.164 (home and mobile) |
| Mobile ID | AAID (Android), IDFA (iOS) |
| Postal Code | ZIP5, ZIP9 |
| Cookie ID | String |
| IP Address | IPv4, IPv6 |
How It Works
- Normalize — Zeotap lowercases and trims values in recognized identifier columns per InfoSum’s specification.
- Serialize — Rows are written as a UTF-8 CSV with a header row.
- Encrypt — The CSV is encrypted with the configured InfoSum PGP public key, producing an ASCII-armored PGP message.
- Upload — The file is uploaded to the configured bucket at
<folder>/<YYYY-MM-DD>/infosum_<mode>_<timestamp>.csv.pgp. - Ingest — The InfoSum bunker picks up the file, decrypts it with its matching private key, and ingests the rows inside the bunker’s secure environment.
Each sync batch produces exactly one encrypted file. The sync mode (insert, mirror, or add) is embedded in the file name so that the bunker operator can distinguish full-dataset drops (insert, and the first run of any mode) from incremental deliveries (mirror and add after the first run). Rows removed from the dataset or audience are never included in the files.
Rate Limits
Google Cloud Storage supports ~1,000 writes per second per object prefix, well above typical sync volumes. There is no InfoSum-side rate limit on file drops — the bunker ingests at its own cadence (typically every few minutes).
Individual objects are limited to 5 TiB by GCS, far above any realistic audience export.
Best Practices
- Send raw identifiers whenever possible — InfoSum performs hashing and salting internally, and raw data produces the highest match rate.
- Lowercase all key columns before the sync if you are pre-processing; Zeotap will also lowercase known identifier columns defensively.
- Use snapshot mode for audience syncs when the bunker needs the complete membership on every run;
mirrorandadddeliver only new and changed rows after the first run (departed members are excluded), so coordinate delta handling with your bunker operator if you rely on those modes. - Coordinate the folder path with your InfoSum representative — the bunker is configured to watch a specific prefix, and files dropped elsewhere in the bucket will be ignored.
- Rotate the GCS service account key periodically; update the JSON in Zeotap when you rotate.
- Keep the PGP public key up to date — if InfoSum rotates the bunker’s key pair, update the InfoSum PGP Public Key field before the next sync or decryption will fail on their side.
Troubleshooting
Connection test fails with “cannot access bucket”
The service account either doesn’t exist in the target project or lacks storage.buckets.get on the bucket. This is the most common misconfiguration: the Storage Object Creator role does not include storage.buckets.get, so a create-only grant fails this check. Grant the permissions listed under Required Permissions — the simplest fix is to add Storage Legacy Bucket Reader (roles/storage.legacyBucketReader) alongside Storage Object Creator.
Connection test fails with “invalid pgp public key”
The value pasted into InfoSum PGP Public Key is not a valid ASCII-armored PGP key. Re-request the key from InfoSum and paste the full block including the -----BEGIN PGP PUBLIC KEY BLOCK----- / -----END PGP PUBLIC KEY BLOCK----- markers.
Connection test warns “pgp key has no encryption-capable subkey”
The provided PGP key has no subkey marked for encryption. Ask InfoSum to issue an encryption-capable key (most OpenPGP tools generate one by default).
Sync succeeds but InfoSum reports no data ingested
Verify the Folder path exactly matches the prefix the bunker is configured to watch. A common mistake is a missing or extra trailing slash — both audiences and audiences/ produce the same GCS path so either is fine on Zeotap’s side, but InfoSum may require the exact form.
Records rejected by InfoSum
InfoSum normalizes values on ingest and rejects rows with malformed identifiers. Check that phone numbers are in E.164 format, postal codes are 5 or 9 digits, and that no identifier column contains empty or whitespace-only values.
Upload fails with “permission denied”
The service account does not have storage.objects.create on the bucket at the moment of upload. Grant it via the custom role or Storage Object Creator as described under Required Permissions, directly or through a group that holds it.