Connect Snowflake¶
Connect a customer-authored calibration view in Snowflake using a dedicated service user and key-pair authentication. You choose the source data and define the session counts. Squoosh reads only the three-column result you provide.
Beta: awaiting live-account validation
This connector has not been validated against a live account. It is at the authentication stage, with fixture-tested snapshot parsing. It is not eligible for automatic snapshot refresh or shopper calibration until live validation is complete. Connecting it does not yet change how your AI shoppers behave.
What the connection does¶
Squoosh verifies access by querying dimension, bucket, and sessions from your configured view with LIMIT 1. A snapshot read runs one SELECT with LIMIT 10001, retrieves every required result partition, and refuses results above 10,000 rows. It never discovers or guesses your warehouse schema.
The view must represent the last 28 full UTC days by default, excluding today. If your view uses another window, enter its actual length in Days represented by the view. This is a customer declaration: Squoosh cannot verify your SQL date filter. Every snapshot carries the warning window_declared_by_customer and reports that declaration, even when a caller requests a different window.
Connect Snowflake¶
1. Prepare a service user and warehouse¶
Ask a Snowflake administrator to perform these steps. In Snowsight, open Workspaces and create a SQL file, or use a SQL worksheet in the legacy Worksheets experience. Use a role with the relevant object-management privileges. Users can be reviewed under Governance & security → Users & roles. Use SQL to create the passwordless service user. Workspaces, User management.
Generate an RSA key locally, keeping the private key private:
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
In Snowflake, create a dedicated role, service user and small warehouse. Replace the public-key placeholder with the contents of rsa_key.pub, without its BEGIN/END lines. Never paste the private key into SQL. Assigning the public key requires OWNERSHIP or MODIFY PROGRAMMATIC AUTHENTICATION METHODS on the user. Key-pair authentication.
CREATE ROLE SQUOOSH_READER;
CREATE USER SQUOOSH_SVC TYPE = SERVICE
DEFAULT_ROLE = SQUOOSH_READER
DEFAULT_WAREHOUSE = SQUOOSH_WH;
ALTER USER SQUOOSH_SVC SET RSA_PUBLIC_KEY = '<public-key-body>';
GRANT ROLE SQUOOSH_READER TO USER SQUOOSH_SVC;
CREATE WAREHOUSE SQUOOSH_WH
WAREHOUSE_SIZE = 'XSMALL'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
GRANT USAGE ON WAREHOUSE SQUOOSH_WH TO ROLE SQUOOSH_READER;
If your account or user enforces a network policy, have your administrator arrange access for Squoosh's egress before connecting. The SQL API follows Snowflake network policies; this connector does not provide PrivateLink support. SQL API introduction.
2. Create the calibration view¶
Create the view in a database and schema you control. The following is an illustrative schema to adapt, not a discovery query: replace YOUR_DB.YOUR_SCHEMA.YOUR_SESSION_SOURCE and its column references with your own. It assumes one row per session, SESSION_STARTED_AT_UTC as a UTC TIMESTAMP_NTZ, canonical device/channel labels, ISO country codes, and a boolean CONVERTED indicating whether that session converted.
All dimensions and the conversion total use the same filtered session population and UTC bounds. COUNT(DISTINCT SESSION_ID) avoids counting multiple orders as multiple converted sessions.
CREATE OR REPLACE VIEW ANALYTICS.REPORTING.SQUOOSH_CALIBRATION AS
WITH bounds AS (
SELECT DATE_TRUNC('DAY', CONVERT_TIMEZONE('UTC', CURRENT_TIMESTAMP()))::TIMESTAMP_NTZ
AS until_utc
), windowed AS (
SELECT SESSION_ID, DEVICE_CATEGORY, COUNTRY_ISO2, CHANNEL_GROUP, CONVERTED
FROM YOUR_DB.YOUR_SCHEMA.YOUR_SESSION_SOURCE
CROSS JOIN bounds
WHERE SESSION_STARTED_AT_UTC >= DATEADD('DAY', -28, until_utc)
AND SESSION_STARTED_AT_UTC < until_utc
)
SELECT 'device' AS dimension, DEVICE_CATEGORY AS bucket,
COUNT(DISTINCT SESSION_ID) AS sessions
FROM windowed GROUP BY DEVICE_CATEGORY
UNION ALL
SELECT 'geo', COUNTRY_ISO2, COUNT(DISTINCT SESSION_ID)
FROM windowed GROUP BY COUNTRY_ISO2
UNION ALL
SELECT 'channel', CHANNEL_GROUP, COUNT(DISTINCT SESSION_ID)
FROM windowed GROUP BY CHANNEL_GROUP
UNION ALL
SELECT 'conversion', 'total', COUNT(DISTINCT SESSION_ID)
FROM windowed WHERE CONVERTED = TRUE;
GRANT USAGE ON DATABASE ANALYTICS TO ROLE SQUOOSH_READER;
GRANT USAGE ON SCHEMA ANALYTICS.REPORTING TO ROLE SQUOOSH_READER;
GRANT SELECT ON VIEW ANALYTICS.REPORTING.SQUOOSH_CALIBRATION TO ROLE SQUOOSH_READER;
The database and schema must already exist. The role creating the view needs access to its source data; the Squoosh role needs only USAGE on the enclosing database/schema and SELECT on the view.
The resulting template is the same dimension,bucket,sessions contract as CSV / Excel import:
| Dimension | Bucket | Sessions |
|---|---|---|
device |
mobile, desktop, or tablet |
Non-negative whole session count |
geo |
ISO country code, such as US, or explicit other |
Non-negative whole session count |
channel |
Direct, Organic Search, Paid Search, Social, Email, or Referral |
Non-negative whole session count |
conversion |
total |
Converted-session count for the same population and window |
Omit dimensions you cannot supply. The conversion row is optional; omit it if your warehouse cannot count converted sessions reliably. Repeated dimension/bucket pairs are summed. Each count and the total across rows must fit JavaScript's safe integer range. At least 80% of device mass must map to mobile, desktop or tablet. NUMBER strings such as 600 and 600.0 are accepted; fractions, negative counts and nulls are rejected.
3. Enter the connection details¶
In Squoosh, open Integrations → Snowflake → Connect and enter:
| Field | Value |
|---|---|
| Account identifier | Organization-account form, obtained with SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME();. No URL, periods, region suffix or PrivateLink hostname. |
| Snowflake user (LOGIN_NAME) | The service user's login name, normally SQUOOSH_SVC. |
| RSA private key | Entire unencrypted rsa_key.p8 PEM, including BEGIN/END lines. This is the only secret field. |
| Warehouse | Exact case-sensitive name, normally SQUOOSH_WH. |
| View database | ANALYTICS for the example above. |
| View schema | REPORTING for the example above. |
| Role | SQUOOSH_READER, or leave blank to use the user's DEFAULT_ROLE. |
| Calibration view | SQUOOSH_CALIBRATION by default. |
| Days represented by the view | 28 for the example above. Change both the view's date bounds and this declaration together. |
Database, schema and view are separate identifier components, each matching ^[A-Za-z_][A-Za-z0-9_$]{0,127}$. Squoosh quotes them exactly as typed. Unquoted Snowflake names are normally stored uppercase, so enter uppercase for the example. Quotation marks, semicolons, comment markers, spaces and dots within a component are rejected. Warehouse, role and login name also use this simple-name subset in this beta.
Squoosh signs a short-lived JWT for each verification or snapshot operation. The private key is never sent to Snowflake; only the signed bearer travels to the account's SQL API. The account/user JWT claims are uppercase, while URL underscores become hyphens. SQL API authentication.
What Squoosh reads and never reads¶
Squoosh reads only the configured view's DIMENSION, BUCKET, SESSIONS columns and the SQL API's statement status and result metadata. It never requests raw session events, order records, payment details, other tables, or a schema inventory. Do not put personal information or credentials in bucket labels. It does not write warehouse data; it submits SELECT statements and may cancel its own unfinished statement.
All served dimensions are classified as self-reported, because your SQL defines the counts. Device, geography and channel are omitted when absent. A conversion row requires a positive session denominator from device rows, otherwise geography, otherwise channel. A real zero conversion count remains zero; missing conversions or missing session evidence produce a warning and no conversion rate. Small samples remain subject to Squoosh's shared calibration floor.
Limits and caveats¶
- Warehouse costs apply to verification and snapshots. A read may auto-resume the warehouse, with a 60-second billing minimum per start. Results can also incur cloud-services usage. The descriptor requests at least one hour between snapshot refreshes; manual checks can still incur costs. Warehouse overview, SQL API introduction.
- 30-second total deadline. Authentication, submission, polling and result retrieval share this budget. The last second is reserved for best-effort cancellation. An explicit server statement timeout also limits execution; cancellation cannot be guaranteed after a transport failure that returns no handle.
- No scan-cost guarantee.
LIMIT 10001bounds the result, not bytes scanned by the view. Use an efficiently aggregated view and a dedicated small warehouse. - Completeness is required. More than 10,000 rows or 100 result partitions is rejected, never clipped into a partial calibration. Missing rows or inconsistent metadata also fail the read.
- Key-pair mode only. No encrypted PEM/passphrase, PAT, OAuth, PrivateLink or legacy region-qualified account locator support in this beta.
- Live validation remains outstanding. Account normalization, exact error bodies and later-partition gzip/envelopes must be confirmed against a real account before promotion beyond authentication stage.
Troubleshooting¶
| Problem | What to do |
|---|---|
| Invalid identifier before connecting | Enter separate simple database/schema/view components without quotes or dots. Match stored case. |
| 401, code 394300 | Use LOGIN_NAME, and confirm the service user has the correct public key. |
| 401, code 394304 | Compare DESCRIBE USER SQUOOSH_SVC → RSA_PUBLIC_KEY_FP with the public key derived from your private key. |
| 401, code 394307 | Check the organization-account identifier. Org-account JWT normalization still requires live confirmation in this beta. |
| 403 / missing scope | Check SQL API access, network policy, USAGE privileges and SELECT on the view. |
| Missing view during verification | Create the view or correct database, schema, view case and grants. Snowflake can use the same message for missing objects and insufficient permissions. |
| Warehouse configuration error | Match SHOW WAREHOUSES, grant USAGE and check AUTO_RESUME. |
| No data or invalid rows | Populate the three required columns with canonical labels and non-negative whole counts. |
| Unsupported window / result too large | Correct the day declaration, or aggregate to no more than 10,000 rows. Squoosh does not silently reduce the window. |
| Timeout | Optimize the view and check warehouse availability. Squoosh attempts to cancel unfinished work and reports no partial snapshot. |
| No conversion rate | Include a real conversion,total row and a positive session denominator from the same UTC population/window. |
| 429 / service unavailable | Retry later with backoff. Snowflake publishes no fixed numeric SQL API rate limit. |
Related¶
- CSV / Excel import: the shared calibration template.
- GA4 BigQuery export: another warehouse connection.
- Snowflake SQL API reference.
- Key-pair troubleshooting.