
Agentic Salesforce to Snowflake ELT: From One Prompt to a Governed Pipeline
How Bruin CLI, Bruin MCP, Bruin Cloud, and agent skills can build and maintain a Salesforce to Snowflake ELT pipeline across bronze, silver, and gold layers.
A short setup guide for getting Adjust raw exports landing in a GCS bucket, plus the parameters you should be sending to Adjust to get attribution right.

Sabri Karagonen
Data & Product

Every time we onboard a new company at Bruin, or every time an existing company ships a new game, someone has to set up Adjust's raw data export to GCS. The steps don't change. The pitfalls don't either. So here's the version I wish I could just send people.
Before any of the steps below: if you don't already have a unified GCP project for data (something like {company}-data), create one. The Adjust bucket, the BigQuery warehouse, and the dashboards on top all belong in there together. Most companies ship more than one game eventually, and a single data project means cross-game reporting is a regular SQL query instead of a cross-project IAM exercise. If you already have one, use that.
1. Create a service account in GCloud. Adjust will use this to write files into your bucket.
adjust-export. Skip the optional "grant access" step, you'll grant access on the bucket directly in step 2.In GCloud, one service account per company is enough. If you've already done this for a previous game at the same company, reuse it, you don't need a new one per game. Create a new one only if you want each game's data isolated from the others.
2. Create a GCS bucket and grant Storage Admin to that service account. The naming convention we use is {company_name}-adjust-{game}. One bucket per game, because Adjust writes everything to the bucket root, there is no subfolder option. That also means when you have three games and need to wipe one, you don't take the others with it.
This bucket gets read once. Bruin (or whatever pipeline you've wired up) imports each file into BigQuery shortly after Adjust drops it, then the file just sits in GCS as a raw archive. That's exactly the access pattern Nearline is priced for, about half the per-GB-month storage cost of Standard, in exchange for a small retrieval fee that pays for itself in well under a month.
The 30-day minimum storage charge does not bite here, since you're not deleting files. Coldline is cheaper still but locks you in for 90 days, which is more commitment than you need on a fresh bucket. If you want to push savings further later on, add a lifecycle rule that bumps files to Coldline after 90 days.
3. Go to Adjust and create a raw data export. Select all the event triggers and all the placeholders. Every checkbox, every column. Having unnecessary columns is better than losing data. If you skip a column today and need it in two months, there is no backfill. That data is gone.
4. Paste the service account JSON into the Adjust export screen and save.
Attribution is a probability game. Every ID you give Adjust is one more match key it can use to tie an install or an event to the right user, the right device, the right campaign. So send everything you have.
This one change, sending the IDs you already have, often moves attribution rate by a few percentage points. There is no good reason not to.
Adjust drops files into the bucket hourly. Multiple files per hour, not one. There is no _SUCCESS marker, no manifest, nothing that tells you "this hour is done."
Two consequences for anyone consuming the GCS bucket downstream:
Once the Adjust export is live, do not change the configuration. Don't add a placeholder, don't remove one, don't toggle an event trigger. Here's why.
When you change the config, Adjust changes the file path. Not at the end, in the middle. BigQuery external tables only support a single * wildcard, so you cannot paper over a path that varies in two places. And because the export format is CSV, you also cannot lean on Parquet's schema evolution to absorb a column-order change.
So the order of operations matters. Turn on every event trigger and every placeholder in Adjust up front, then leave it alone. Adding a column you'll never query is free. Reshuffling the path two months later is not.
Pick a game. Make the bucket, name it {company_name}-adjust-{game}, attach a service account with Storage Admin, and paste the JSON into Adjust with every checkbox ticked. Audit which IDs your app already has and start sending the ones you aren't sending yet. Then leave the config alone.

How Bruin CLI, Bruin MCP, Bruin Cloud, and agent skills can build and maintain a Salesforce to Snowflake ELT pipeline across bronze, silver, and gold layers.

Most AI data analysts live in Slack or a browser. Bruin runs in WhatsApp too. Here is why field, sales, and ops teams prefer asking their data questions there, what it takes to make it actually work, and how to roll it out safely.
Can you just use ChatGPT, Claude, or a coding agent like Codex to analyze your company data? Here is the honest difference between a general AI model and a purpose-built AI data analyst, why a model alone is not enough, and what it takes to get trustworthy answers from live company data.