How to Add Product Analytics to a Desktop App (No SDK Required)
Most product-analytics advice quietly assumes you can drop a client-side SDK into your app. But a lot of software can't — or shouldn't. Desktop applications, thick engineering clients, tools with strict privacy or offline requirements: for these, "just install the SDK" isn't an option. The good news is that an SDK was never the only way to get data into Amplitude. If your app can't use one, you send events server-side instead — and if your usage data already lands in a warehouse like Snowflake, most of the work is already done.
The short version: You don't need a client-side SDK to get product analytics. When an app can't use one — a desktop application, a thick client, or a case with strict privacy or offline constraints — you can send events to Amplitude through its HTTP API, fed from wherever your usage data already lands, often a data warehouse like Snowflake. The flow is: the app emits usage data to your cloud, that data lands in the warehouse, and a job formats it into Amplitude events and POSTs them to the HTTP Batch API. You give up automatic event capture, but you gain a clean, fully-defined event stream and complete control over the pipeline.
Why some apps can't use an SDK
Client-side SDKs are built for web and mobile apps that run in an environment the SDK understands and can phone home from. Plenty of products don't fit that mold:
- Desktop applications — native software (think a GIS, CAD, or engineering tool) where embedding and maintaining an analytics SDK is impractical or unsupported.
- Privacy- or security-constrained software — where you can't ship a third-party SDK that beacons out from the client.
- Offline-first tools — where the app isn't reliably connected, so real-time client tracking doesn't work anyway.
- Legacy or thick clients — where the engineering cost of instrumenting the client outweighs the benefit.
In all of these, the usage signals still exist — they're just captured somewhere other than a browser. The task is getting them to Amplitude.
The core idea: send events server-side
Amplitude accepts events through its HTTP API (and, for volume, the HTTP Batch API), completely independent of any SDK. Instead of the client reporting its own events, you send them from your own systems: you construct each event as JSON — an event type, a user or device identifier, a timestamp, and any event properties — and POST it to Amplitude. Amplitude doesn't care whether that call came from a browser SDK or your backend; a well-formed event is a well-formed event.
That reframes the whole problem. You're no longer asking "how do I instrument this app?" You're asking "where does this app's usage data already live, and how do I forward it?"
The architecture: from the app to Amplitude via Snowflake
For a lot of desktop and server-side products, the answer to "where does the data live?" is a data warehouse. A typical pipeline looks like this:
- The app emits usage data to your cloud backend as people use it (feature usage, actions, sessions).
- That data lands in your cloud (for example, Azure) and flows into a warehouse — commonly Snowflake — which becomes your source of truth for raw usage.
- A job transforms and forwards it: it reads new rows from Snowflake, maps them to your Amplitude event schema, and POSTs them in batches to Amplitude's HTTP Batch API.
Amplitude then treats those events exactly like any others — funnels, retention, cohorts, and dashboards all work normally. The connection between the warehouse and Amplitude is the one well-trodden part of this; if you want the nuts and bolts of that hop, our practical guide to integrating Snowflake data with Amplitude covers it.
A real example: a desktop GIS with no SDK
This isn't hypothetical. Blue Marble's Global Mapper is a desktop GIS application with no analytics SDK — exactly the situation above. Rather than force an SDK into the desktop client, usage data flows from the app through Azure into Snowflake, and from there into Amplitude via the HTTP Batch API. On top of that pipeline sits a deliberate, 73-event tracking plan, so what reaches Amplitude is a clean, intentional event stream rather than raw exhaust. The result is full product analytics on a desktop app that, by the SDK-first playbook, "couldn't" be tracked. (The full build is written up in the Blue Marble case study.)
What you have to get right
Server-side tracking is powerful, but it moves the responsibility for quality onto you. Four things matter most:
- A real tracking plan. With no SDK auto-capturing anything, every event is one you deliberately define and send. That's more upfront work — and a blessing in disguise, because it forces the clean event design most SDK setups skip. Decide your events, names, and properties before you pipe anything.
- Identity. You need a stable user (or device) identifier attached to every event so Amplitude can stitch a person's activity together. Because you control the pipeline, you set this deliberately from the identifier your app already uses.
- Schema consistency and batching. Map warehouse rows to a consistent event schema, batch them to respect the API's rate limits, and handle retries — this is a data pipeline, so treat it like one.
- Historical backfill. A nice side benefit: because the history already sits in Snowflake, you can backfill past events into Amplitude, rather than starting from zero the way a freshly-installed SDK does.
The trade-offs
Going SDK-free costs you automatic capture — there's no library silently logging pageviews and clicks, so anything you didn't define, you don't get. For most warehouse-first teams that's a feature, not a bug: you end up with only meaningful, intentional events instead of noise. The other trade is latency — a batch pipeline is near-real-time, not instant — which is a non-issue for the product analysis this approach is built for. In exchange, you own the pipeline end to end and can treat your warehouse as the single source of truth that feeds everything.
When this approach is the right one
Reach for warehouse-to-Amplitude tracking when your app can't take an SDK (desktop, thick client, offline, privacy-constrained), when your usage data already lands in a warehouse, or when you want a single deliberately-defined event stream rather than auto-captured exhaust. If your app is a standard web or mobile client, the SDK is still the simpler path — but "no SDK" has never meant "no analytics."
Need product analytics on an app the SDK-first playbook can't reach?
Piping events from a warehouse to Amplitude cleanly — the tracking plan, the identity model, the schema mapping — is a data-integration job worth getting right the first time. Our Data Mapping & Integration engagement is built for exactly this: connecting your sources to Amplitude so a no-SDK app gets analytics as reliable as any web app's.
Frequently asked questions
Can you use Amplitude without an SDK?
Yes. Amplitude accepts events through its HTTP API (and HTTP Batch API for volume) completely independently of any SDK. You construct events as JSON — event type, user/device ID, timestamp, properties — and send them from your own systems, which is how apps that can't run a client-side SDK still get full analytics.
How do you track a desktop app in Amplitude?
Send events server-side rather than from the client. Usage data from the desktop app flows to your cloud and into a data warehouse (like Snowflake), and a job maps that data to your Amplitude event schema and posts it to the HTTP Batch API. From Amplitude's perspective, the events behave like any others.
How does the Snowflake-to-Amplitude pipeline work?
New usage rows land in Snowflake, a transformation job maps them to your defined Amplitude events, and those events are sent in batches to Amplitude's HTTP Batch API. Snowflake acts as the source of truth for raw usage, and Amplitude becomes the product-analytics layer on top.
What are the downsides of server-side tracking without an SDK?
You lose automatic event capture, so every event must be deliberately defined and sent — more upfront work, but cleaner data. There's also a small latency trade (batch pipelines are near-real-time, not instant). In return you get full control of the pipeline and only intentional, meaningful events.
Can you backfill historical data this way?
Yes, and it's a real advantage. Because your usage history already lives in the warehouse, you can send past events into Amplitude to build history from day one — rather than starting from zero as you would with a newly installed SDK.

.png)
.png)


