Installation
Installing the Zeotap Native App takes about five to ten minutes of operator time plus a couple of minutes of SPCS warm-up while the compute pool pulls container images. The flow has five user-visible steps, all surfaced in the in-app Snowsight setup wizard:
- Install from Marketplace.
- Grant the two required External Access Integrations (EAIs) from the application’s Configure tab.
- Run a single proxy-identity SQL block as ACCOUNTADMIN.
- Click Register with Zeotap in the setup wizard’s Step 4.
- Open the claim URL and sign in.
The application creates and owns its own warehouse (ZEOTAP_ADMIN_WH), so there is no consumer warehouse to bind and no GRANT USAGE ON WAREHOUSE step. You can resize that warehouse later from the setup app’s Warehouse settings card or from SQL.
A note on
<APP_NAME>. When you install from the Marketplace, Snowflake asks you to pick a database name for the application. The Marketplace default for the Zeotap Composable CDP listing isZEOTAP_COMPOSABLE_CDP. Throughout these pages<APP_NAME>stands in for whatever name you chose — replace it with that value when copying SQL into a worksheet. The in-app Streamlit setup wizard renders every SQL block with the correct value already substituted; using the wizard is the recommended path. Identifiers prefixed withZEOTAP_(such asZEOTAP_PROXY_USER,ZEOTAP_ADMIN_WH,ZEOTAP_SF_EAI) are brand-scoped account-level objects created by the install script — they are NOT the application name and you should keep them exactly as written.
Prerequisites
- A Snowflake account in a region where Snowpark Container Services (SPCS) is available.
- ACCOUNTADMIN access — or a role that can create users, roles, and the proxy keypair. The application supplies the host:port allow-lists for both required EAIs through the Snowsight Permissions SDK consent flow, so EAI provisioning itself does not require external network-rule SQL.
- The Zeotap listing visible in your Snowflake Marketplace. Request access from your Zeotap account team if not.
You’ll wire Zeotap up to the databases it should read from after the install is claimed — see Sources.
1. Install from Marketplace
In Snowsight, find Zeotap in the Marketplace and click Get. Snowflake creates an Application object in your account from the Zeotap Application Package.
-- Equivalent SQL (Snowsight runs this for you when you click "Get")
CREATE APPLICATION <APP_NAME>
FROM APPLICATION PACKAGE zeotap_pkg
USING VERSION v1;The application requests three account-level privileges in its manifest. You approve each on first launch:
| Privilege | Why it is needed |
|---|---|
CREATE COMPUTE POOL | Create the dedicated SPCS compute pool that runs the long-running services. |
BIND SERVICE ENDPOINT | Expose the control-plane HTTPS endpoint on the SPCS public ingress so the Zeotap cloud reverse-proxy can reach this install. |
CREATE WAREHOUSE | Create ZEOTAP_ADMIN_WH, the application-owned warehouse used for control-plane queries and worker job runs (XSMALL by default; resizable from the setup app). |
After the application is created, Snowsight drops you into the application’s setup page.
2. Grant the required EAI references in the Configure tab
The application declares two required EAI references in its manifest:
| Reference | Purpose | Allow-listed hosts |
|---|---|---|
zeotap_sf_api_access | Outbound HTTPS to the Zeotap cloud for one-time cloud registration and ongoing reverse-proxy traffic. | composable.zeotap.com:443, events.zeotap.com:443 |
sendgrid_api_access | Outbound HTTPS to SendGrid for workspace invites and transactional email. | api.sendgrid.com:443 |
In Snowsight, open Apps → <APP_NAME> → Configure. Each manifest reference is listed with a Grant button. Click Grant next to both required references. Snowsight calls the application’s CONFIGURE_REFERENCE_CALLBACK to fetch the host:port allow-list declared in the manifest, then creates the matching External Access Integration in your account and binds it as a reference on the application. There is no SQL to copy and no network rule to author by hand.
You do not need to bind a warehouse here. The application provisions its own warehouse (ZEOTAP_ADMIN_WH) automatically.
Once the CREATE COMPUTE POOL privilege is granted, the application’s setup script auto-invokes PROVISION_SERVICES. SPCS creates the dedicated compute pool, the application-owned warehouse, and the five long-running services (control plane, event forwarder, Postgres, Redis, worker-image registry). Container images pull on first launch — this takes about two minutes. Watch progress with:
SHOW SERVICES IN APPLICATION <APP_NAME>;
SELECT * FROM <APP_NAME>.APP_DATA.APP_VERSION;When the services show READY, the application is ready for the next stage.
3. Run the proxy-identity SQL block
The Zeotap cloud reverse-proxy authenticates against your Snowflake account as a dedicated service user signed with an RSA keypair minted inside the application. Snowflake does not let an application create users, alter users, or grant account-level roles on the consumer’s behalf — those statements have to run as ACCOUNTADMIN. This is the only consumer-side SQL the install requires.
Open the in-app setup wizard (Apps → <APP_NAME> → Open) — Step 3 renders the exact SQL with brand identifiers already substituted for your install. Copy the block into a Snowsight worksheet and run it as ACCOUNTADMIN.
-- 3a. Proxy service user + role + application-role grant.
-- 3b. Mint the RSA-2048 keypair inside the application and register
-- the public half on the proxy user. The private key never leaves
-- Snowflake — it stays in APP_DATA.CLOUD_CREDENTIALS until the
-- SPCS control-plane service ships it to the cloud during Step 4.
CREATE USER IF NOT EXISTS ZEOTAP_PROXY_USER
TYPE = SERVICE
DEFAULT_ROLE = ZEOTAP_PROXY_ROLE
COMMENT = 'Cloud-proxy service user for Zeotap Native App reverse-proxy';
CREATE ROLE IF NOT EXISTS ZEOTAP_PROXY_ROLE;
GRANT ROLE ZEOTAP_PROXY_ROLE TO USER ZEOTAP_PROXY_USER;
GRANT APPLICATION ROLE <APP_NAME>.APP_PUBLIC TO ROLE ZEOTAP_PROXY_ROLE;
EXECUTE IMMEDIATE $$
DECLARE
pubkey STRING;
BEGIN
pubkey := (CALL <APP_NAME>.APP_DATA.GENERATE_PROXY_KEYPAIR(
'ZEOTAP_PROXY_USER', 'ZEOTAP_PROXY_ROLE'));
EXECUTE IMMEDIATE
'ALTER USER ZEOTAP_PROXY_USER SET RSA_PUBLIC_KEY = ''' || :pubkey || '''';
RETURN 'keypair registered';
END;
$$;What the block does, in order:
- Creates
ZEOTAP_PROXY_USERas aTYPE = SERVICEuser. Service users skip password rotation and disallow interactive sign-in, so the only auth factor is the registered RSA key. - Creates
ZEOTAP_PROXY_ROLE, grants the role to the proxy user, and grants the application role<APP_NAME>.APP_PUBLICto the proxy role. That’s the only privilege the proxy role carries — it can only call into the Zeotap application sandbox. - Calls
GENERATE_PROXY_KEYPAIR, which mints an RSA-2048 keypair inside Snowflake’s Python runtime, persists the private key inAPP_DATA.CLOUD_CREDENTIALS, and returns the base64 public key. - Registers the public key on the proxy user with
ALTER USER ... SET RSA_PUBLIC_KEY.
The block is idempotent and safe to re-run. A re-run mints a fresh keypair and registers the new public half on the existing user — useful for rotation or recovery after a transient failure. The block preserves the cloud-side register_secret across rotations, so re-registration in Step 4 stays authenticated.
This step requires ACCOUNTADMIN (or any role with CREATE USER, CREATE ROLE, and OWNERSHIP on the proxy user and role) because Snowflake does not allow applications to create users or run ALTER USER ... SET RSA_PUBLIC_KEY on the consumer’s behalf.
4. Register with the Zeotap cloud
In the setup wizard (Apps → <APP_NAME> → Open), click Register with Zeotap on Step 4. The button calls APP_DATA.REQUEST_REGISTRATION(<your-email>), which enqueues a single-row request in APP_DATA.REGISTRATION_REQUEST.
A goroutine inside the SPCS control-plane service watches that table. When the request lands it gathers the install’s identity, signs the body with the keypair from CLOUD_CREDENTIALS, and performs the outbound HTTPS POST to the cloud over the zeotap_sf_api_access EAI (the same EAI you approved in Step 2). The cloud responds with a one-time claim URL; the service writes it to APP_DATA.CLOUD_REGISTRATION and flips the request row to completed. The wizard polls both tables and surfaces the claim URL as soon as it appears — typically within three to six seconds.
If the wizard shows Re-register with cloud in the Step 4 card, the registration already succeeded. Click it to re-run the handshake idempotently — useful after rotating the keypair, recovering from a transient failure, or moving to a new SPCS ingress URL.
The earlier REGISTER_WITH_CLOUD stored procedure was removed in favour of this SPCS-service-driven path. Snowflake’s marketplace review only accepts EAIs provisioned through the Permissions SDK consent flow, which binds USAGE through manifest references rather than directly on the integration object. Stored procedures with EXTERNAL_ACCESS_INTEGRATIONS = (<literal EAI name>) fail at call time under that model, but SPCS service specs accept EXTERNAL_ACCESS_INTEGRATIONS = (REFERENCE('zeotap_sf_api_access')). Routing registration through the SPCS service is what makes the install marketplace-compliant.
5. Open the claim URL and sign in
Once the claim URL appears, click Claim now in the setup wizard — or open the URL directly. It points at https://composable.zeotap.com/login/snowflake?app=<install-id>. The app=<install-id> query parameter is how the cloud UI knows to bind this browser session to your install.
Sign in with email, Google, or your configured SSO IdP. Zeotap binds the install to a workspace and drops you on the dashboard. The sidebar now shows a native-app selector next to the workspace picker — switch between cloud Zeotap and this install at any time.
The browser UI is live and reaches your in-account control plane through the authenticated reverse proxy. You can now add Snowflake sources — see Sources for the per-database GRANT script the UI generates — and configure destinations from the in-product wizard.
Resizing the warehouse
The application created ZEOTAP_ADMIN_WH (XSMALL, AUTO_SUSPEND = 60s) for its control-plane queries and worker job runs. The setup app has a Warehouse settings card that reads the current size from APP_DATA.GET_WAREHOUSE_INFO() and exposes a dropdown for resizing. Pick a new size and click Resize — the application runs APP_DATA.SET_WAREHOUSE_SIZE(...) against the dropdown selection.
You can also call the proc directly:
CALL <APP_NAME>.APP_DATA.SET_WAREHOUSE_SIZE('MEDIUM');Valid sizes: XSMALL, SMALL, MEDIUM, LARGE, XLARGE, XXLARGE, XXXLARGE, X4LARGE, X5LARGE, X6LARGE. The proc validates the size in-process; an invalid value returns an error string and leaves the warehouse untouched.
Because the application owns the warehouse, you do not need to issue any external ALTER WAREHOUSE statements.
Adding destinations
The two required EAIs cover only the Zeotap cloud and SendGrid. Each destination family (Meta CAPI, Google Ads, Salesforce, Slack, Klaviyo, and so on) has its own EAI requirement.
Configure tab (recommended). Snowsight → Apps → <APP_NAME> → Configure lists every destination-family EAI reference declared in the application manifest. Click Grant next to each destination you want to enable. Snowsight reads the host:port allow-list from CONFIGURE_REFERENCE_CALLBACK and provisions the EAI for you. No SQL required.
In-product wizard. When you add a destination from the Zeotap UI, the wizard checks whether the destination type’s EAI is bound; if not, it prompts you to grant it from the Configure tab before continuing with credential entry.
Per-destination SQL. As a fallback, the setup app’s destination grid renders a copy-paste CREATE NETWORK RULE + CREATE EAI + GRANT USAGE + REGISTER_REFERENCE_CALLBACK + ATTACH_EAI block for each family with brand identifiers substituted. Each section is independent — paste only the families you need. Use this when the Configure-tab consent flow is unavailable in your region.
See Destinations for the full EAI catalog and the bring-your-own-EAI flow for connectors outside the catalog.
Stored procedure reference
The application exposes fourteen procedures in the APP_DATA schema (all granted USAGE to the application role APP_PUBLIC). The ones you may invoke directly are:
| Procedure | What it does |
|---|---|
PROVISION_SERVICES() | Creates the compute pool, ZEOTAP_ADMIN_WH, and the five long-running services. Auto-invoked at install/upgrade time; idempotent. |
SET_WAREHOUSE_SIZE(size STRING) | Resize ZEOTAP_ADMIN_WH. Validates the size before running ALTER WAREHOUSE. |
GET_WAREHOUSE_INFO() | Returns JSON with name, size, and state for the application-owned warehouse. |
GENERATE_PROXY_KEYPAIR(user, role) | Mints the RSA keypair, persists the private key in APP_DATA.CLOUD_CREDENTIALS, returns the base64 public key. Called from the Step 3 SQL block. |
REQUEST_REGISTRATION(operator_email STRING) | Enqueues a cloud-registration request that the SPCS control-plane service processes via its zeotap_sf_api_access EAI binding. |
GET_INSTANCE_INFO() | Returns JSON with the install’s id, status, and SPCS public ingress URL. Useful for support triage. |
GET_LOGS(service, container, num_lines) | Wraps SYSTEM$GET_SERVICE_LOGS for the application’s own services. |
ATTACH_EAI(eai_name, services) | Attaches an EAI to running services via ALTER SERVICE. Used by the destination wizard and BYO-EAI flows. |
RESTRICT_EAI(eai_name, allowed_hosts) | Narrows an attached EAI’s allow-list to a specific set of hosts. |
The remaining five procedures (CONFIGURE_REFERENCE_CALLBACK, REGISTER_REFERENCE_CALLBACK, GRANT_CALLBACK, GET_SECRET, LOG_USAGE_EVENT) are invoked by Snowsight or by the application’s own services; you should not need to call them by hand.
The earlier REGISTER_WITH_CLOUD, GET_CUSTOMER_WAREHOUSE_NAME, and GET_BOUND_EAI_NAME procedures were removed when the install moved off the consumer-warehouse binding and onto the SPCS-service-driven cloud handshake.
Common pitfalls
- The setup wizard’s Step 4 button is greyed out. The wizard requires Steps 1–3 to read Done first. Re-check that both required EAIs are bound (Configure tab) and that
APP_DATA.CLOUD_CREDENTIALShas aproxy_userrow (the Step 3 SQL block populates it). - Registration request stuck in
requested. The SPCS control-plane service performs the cloud handshake within a few seconds. If the request row stays atrequestedfor more than thirty seconds, check that thezeotap_sf_api_accessEAI binding is still active in Configure and thatSHOW SERVICES IN APPLICATION <APP_NAME>reportszeotap_control_planeasREADY. - Registration fails with a connection error. Most often the EAI consent grant has not propagated, or the SPCS control plane is restarting after an image upgrade. Click Register again to retry; the request row’s
errorcolumn has the specific message. my.salesforce.comrejected at network-rule creation. That’s the shared root, not a real host. Replace with your instance host (e.g.acme.my.salesforce.com) before running the Salesforce section of the destination SQL, or use the in-product wizard which prompts for the instance host.blob.core.windows.netrejected. Same problem — replace with<account>.blob.core.windows.netbefore running the Azure section.- Compute pool quota exceeded. Native Apps need a fresh compute pool and your account has a per-account compute-pool count limit. Drop unused pools or contact Snowflake support to raise the limit.
If the install hits a state these notes don’t cover, see Troubleshooting.