Quick start
Install and configure the Grovs Web SDK in your project.
Install the SDK, configure it on page load and open your first link. Takes about ten minutes.
Copy one prompt into Claude Code, Cursor or Copilot and it does these steps in your project.
Add the Grovs Web SDK 2.1 to this web app (example app: Medly). 1. Install the grovs package 2.1.0 (npm install grovs). 2. Call Grovs.configure with apiKey, testEnvironment, onDeeplink and onError once, as early as possible, on the client only (never during server rendering). Read the key from GROVS_API_KEY through the existing env setup. Set testEnvironment to true only in development. 3. In onDeeplink, route the payload to the existing router. 4. Call Grovs.setUserIdentifier with the signed-in user's ID after sign-in. 5. If the site sends a Content-Security-Policy, report whether script-src allows inline scripts (HTML in-app messages need them). 6. List what you changed and which origins to add as linked domains in the Grovs dashboard (SDK Setup → Web). Docs: https://docs.grovs.io/docs/sdk/web/quick-start.md
Upgrading? See 2.0 to 2.1 or 1.x to 2.0.
Requirements
- A browser. Importing during server rendering is safe, but configure on the client.
- Every origin your app runs on, including
http://localhost:<port>for development, registered as a linked domain in the Grovs dashboard. See Registering Domains.
Installation
npm install grovs --saveimport Grovs from "grovs";CommonJS
From require, the SDK is the default export, with named exports alongside:
const { default: Grovs, GrovsError } = require("grovs");Script tag
The IIFE build at dist/grovs.global.js exposes window.Grovs. Serve it from your own origin:
<script src="/assets/grovs.global.js"></script>
<script>
Grovs.configure({ apiKey: "your-api-key" });
</script>A public CDN works too. Pin an exact version and add a Subresource Integrity hash: a @2 range changes file on every patch release, which defeats SRI. Each version's release notes carry its integrity value.
TypeScript
Types ship with the package. You don't need @types/grovs.
Configuration
Call configure once, as early as possible. It resolves true once the SDK authenticates:
import Grovs from "grovs";
const ready = await Grovs.configure({
apiKey: "your-api-key",
testEnvironment: false,
onDeeplink: (payload) => {
// The page was opened from a Grovs link
console.log("deep link payload", payload);
},
onError: (code, message) => {
console.error("grovs error", code, message);
},
});Identify the user, if there is one:
Grovs.setUserIdentifier("user-42");
Grovs.setUserAttributes({ plan: "pro", seats: 5 });Both are safe before configure resolves.
Configuration options
| Option | Default | Description |
|---|---|---|
apiKey | required | Your project API key from the Grovs dashboard. |
testEnvironment | false | true targets the test environment (its own domain, links and data). false targets production. Use true only in development. |
baseURL | Grovs cloud | Domain of a self-hosted backend, for example "https://sdk.example.com". The SDK appends the API path. |
autoTrackScreenViews | true | Fire screen views on single-page-app route changes. See Events & Screen Tracking. |
cookieDomain | host-only | Set to span subdomains, for example ".example.com". |
requireConsent | false | Store and send nothing until grantConsent() is called. See Privacy & Consent. |
appVersion | SDK version | Your app's version, reported with the device fingerprint. |
debugLevel | "error" | "info", "warn" or "error". |
smartBanner | true | Show the dashboard's smart banner on mobile browsers. false turns it off. |
messagesTheme | none | Deprecated and ignored: the messages inbox was removed in 2.1. |
onDeeplink | none | Called with the payload when the page was opened from a link. |
onError | none | Called on every SDK failure with a GrovsError code and a message. |
configure rejects if apiKey is missing. It resolves false in these cases:
requireConsentistrueand consent isn't granted. Nothing is sent.- It's called during server rendering. Nothing is sent.
- Authentication fails transiently (no connection, timeout, 429, 5xx). The SDK retries in the background on
onlineand every 30 seconds, up to three times. - Authentication fails permanently (bad key, unlinked origin). The SDK stops; fix the cause and call
configureagain. - A later
configurecall supersedes it.
Calling configure again with different settings replaces the client. With the same settings on an authenticated client, it keeps the client and takes the new callbacks. A second call for the same project on one page load doesn't emit a second app_open, so React strict mode's double invocation is safe.
Linked domains. The SDK sends its origin (for example https://app.example.com), and the backend matches it exactly against your linked domains. A mismatch fails with "This Web app is not configured". The error contains the exact string sent; copy it into the dashboard.
Server-side rendering
Importing during SSR is safe. On the server, configure is a no-op that logs and reports networkRequestFailed through onError, once per call. Call it on the client instead, in useEffect, onMounted or equivalent.
Next steps
- Receive deep link payloads →
- Generate smart links →
- Track events and screens →
- Show in-app messages →
- Set up the smart banner →
- Gate collection on user consent →
See also
- How to Integrate an npm package: installing the package with npm
- Registering Domains for SDK Integration: register every origin where the SDK runs
- SDK configuration issues: common setup and initialization problems
- Frequently asked questions