# Get contacts for an organisation Source: https://docs.snitcher.com/api-reference/contacts/get-contacts-for-an-organisation https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/contacts # Reveal an email for an organisation contact Source: https://docs.snitcher.com/api-reference/contacts/reveal-an-email-for-an-organisation-contact https://app.snitcher.com/api/docs?api-docs.json put /v1/workspaces/{workspaceUuid}/contacts/{contactUuid}/reveal-email # Clear a custom field value on an organisation Source: https://docs.snitcher.com/api-reference/custom-field-values/clear-a-custom-field-value-on-an-organisation https://app.snitcher.com/api/docs?api-docs.json delete /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/custom-fields/{key} # List custom field values for an organisation Source: https://docs.snitcher.com/api-reference/custom-field-values/list-custom-field-values-for-an-organisation https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/custom-fields # Set a custom field value on an organisation Source: https://docs.snitcher.com/api-reference/custom-field-values/set-a-custom-field-value-on-an-organisation https://app.snitcher.com/api/docs?api-docs.json put /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/custom-fields/{key} # Set multiple custom field values on an organisation Source: https://docs.snitcher.com/api-reference/custom-field-values/set-multiple-custom-field-values-on-an-organisation https://app.snitcher.com/api/docs?api-docs.json patch /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/custom-fields Set one or more custom field values in a single request (at most 50 per request). Unknown field keys are created automatically, with their type inferred from the value — so an integration does not have to pre-create fields. Values are validated against each field's type, and for select/status/multi-select fields against the field's defined options; an unusable value, an off-list option, or a bad key returns a 422 naming the offending key. Validation covers the whole payload before anything is written, so a rejected key never leaves earlier keys half-applied. Every value must be non-empty: sending an empty array does not clear a multi-select — use the DELETE custom-fields/{key} endpoint to remove a value. # Create a custom field definition Source: https://docs.snitcher.com/api-reference/custom-fields/create-a-custom-field-definition https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces/{workspaceUuid}/custom-fields # Delete a custom field definition Source: https://docs.snitcher.com/api-reference/custom-fields/delete-a-custom-field-definition https://app.snitcher.com/api/docs?api-docs.json delete /v1/workspaces/{workspaceUuid}/custom-fields/{key} # Get a custom field definition Source: https://docs.snitcher.com/api-reference/custom-fields/get-a-custom-field-definition https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/custom-fields/{key} # List custom field definitions Source: https://docs.snitcher.com/api-reference/custom-fields/list-custom-field-definitions https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/custom-fields # Update a custom field definition Source: https://docs.snitcher.com/api-reference/custom-fields/update-a-custom-field-definition https://app.snitcher.com/api/docs?api-docs.json patch /v1/workspaces/{workspaceUuid}/custom-fields/{key} # Add a tag to an organisation Source: https://docs.snitcher.com/api-reference/organisations/add-a-tag-to-an-organisation https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/tags # Get an organisation Source: https://docs.snitcher.com/api-reference/organisations/get-an-organisation https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid} # List organisations Source: https://docs.snitcher.com/api-reference/organisations/list-organisations https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/organisations # List organisations using advanced filters Source: https://docs.snitcher.com/api-reference/organisations/list-organisations-using-advanced-filters https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces/{workspaceUuid}/organisations # Remove a tag from an organisation Source: https://docs.snitcher.com/api-reference/organisations/remove-a-tag-from-an-organisation https://app.snitcher.com/api/docs?api-docs.json delete /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/tags # List all segments in a workspace Source: https://docs.snitcher.com/api-reference/segments/list-all-segments-in-a-workspace https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/segments # Overview of the sessions in a date range Source: https://docs.snitcher.com/api-reference/sessions/overview-of-the-sessions-in-a-date-range https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/sessions Lists sessions within a date range. A date range is required: provide either `date` or `date_from` (optionally with `date_to`), otherwise the request fails with a 400. # Overview of the sessions of an organisation Source: https://docs.snitcher.com/api-reference/sessions/overview-of-the-sessions-of-an-organisation https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/sessions # Get the authenticated user's profile Source: https://docs.snitcher.com/api-reference/user/get-the-authenticated-users-profile https://app.snitcher.com/api/docs?api-docs.json get /v1/me # Create a new tag for a workspace Source: https://docs.snitcher.com/api-reference/workspaces/create-a-new-tag-for-a-workspace https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces/{uuid}/tags # Create a new workspace Source: https://docs.snitcher.com/api-reference/workspaces/create-a-new-workspace https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces # Delete a workspace Source: https://docs.snitcher.com/api-reference/workspaces/delete-a-workspace https://app.snitcher.com/api/docs?api-docs.json delete /v1/workspaces/{uuid} # Get details of a specific workspace Source: https://docs.snitcher.com/api-reference/workspaces/get-details-of-a-specific-workspace https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces/{uuid} # Get the user's workspaces Source: https://docs.snitcher.com/api-reference/workspaces/get-the-users-workspaces https://app.snitcher.com/api/docs?api-docs.json get /v1/workspaces # Invite a user to a workspace Source: https://docs.snitcher.com/api-reference/workspaces/invite-a-user-to-a-workspace https://app.snitcher.com/api/docs?api-docs.json post /v1/workspaces/{uuid}/users/invite # Update workspace details Source: https://docs.snitcher.com/api-reference/workspaces/update-workspace-details https://app.snitcher.com/api/docs?api-docs.json patch /v1/workspaces/{uuid} # Introduction Source: https://docs.snitcher.com/powered-by-snitcher/ip2company/introduction Turn any IP address into company intelligence with the Snitcher IP to Company API. Real-time company identification for B2B applications. **Please Note:** The IP to Company API is a standalone offering and is not included with our standard product plans. If you'd like to purchase or learn more, please answer a few quick questions so our team can reach out. ## What is IP to Company? **IP to Company is a real-time API that identifies which company an IP address belongs to.** Send us an IP address, and we'll return detailed firmographic data including company name, industry, size, location, and social profiles. Use it to enrich your application with company intelligence—personalize experiences, qualify leads, route support tickets, or power your own visitor identification features. ### Key Use Cases Customize landing pages, CTAs, and content based on the visitor's company, industry, or size—in real-time. Automatically append company data to form submissions, signups, or support tickets. Power your own dashboards with company identification for website analytics or CRM enrichment. Verify that business visitors are who they claim to be by matching IP data against company records. *** ## How It Works The API is simple: send an IP address, receive company data. ```mermaid theme={null} flowchart LR A[Your Application] -->|IP Address| B[IP to Company API] B -->|Company Data| A ``` ### Single Request, Rich Response ```bash theme={null} curl -X POST 'https://api.snitcher.com/company/find?ip=203.0.113.42' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Accept: application/json' ``` When we identify a company, you'll receive: | Data | Example | | ------------------ | ------------------------- | | **Company Name** | Acme Corporation | | **Domain** | acme.com | | **Industry** | Information Technology | | **Employee Range** | 50-200 employees | | **Annual Revenue** | $10M - $50M | | **Location** | San Francisco, CA, USA | | **LinkedIn** | linkedin.com/company/acme | The API returns a `type` field indicating whether the IP belongs to a `business`, `isp`, or other network type—so you can handle each case appropriately. ### Two Ways to Identify You can look up a company by **IP address**, or—if you also run [Radar](/powered-by-snitcher/radar/introduction)—by a visitor's **session ID** for a higher match rate. See the [Quickstart](/powered-by-snitcher/ip2company/quickstart#input-methods) for both input methods and when to use each. *** ## Why Snitcher? Our IP intelligence database is the same one that powers the Snitcher platform, trusted by thousands of B2B companies for visitor identification. * **Comprehensive coverage**: Continuously updated database of business IP ranges worldwide * **Fast response times**: Built for real-time use cases with low-latency responses * **Detailed firmographics**: Not just company name—get industry, size, revenue, location, and social profiles * **Simple integration**: RESTful API with straightforward authentication *** ## Getting Started Authentication, endpoints, and example requests Industry categories, company sizes, and country codes # Quickstart Source: https://docs.snitcher.com/powered-by-snitcher/ip2company/quickstart The Snitcher IP to Company API allows you to identify companies based on IP addresses, providing detailed business insights for B2B use cases. **Please Note:** The IP 2 Company API is a standalone offering and is not included with our standard product plans. If you'd like to purchase or learn more about IP 2 Company, please answer a few quick questions so our team can reach out. ## Authentication Authentication is done via the API key which will be provided to you separately. Requests are authenticated by passing your API key as a bearer token in an `Authorization` header. ```bash theme={null} curl --location --request POST 'https://api.snitcher.com/company/find?ip={IP}' \ --header 'Authorization: Bearer {key}' \ --header 'Accept: application/json' ``` ## Rate Limits * **600 requests per minute** Higher rate limits can be enabled on your account upon request. These are typically included within your contract terms. ## Input Methods You can identify a company in two ways. Pick the one that matches how you've integrated Snitcher: | Input | When to use | Endpoint | | -------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | **IP address** | You have the visitor's IP address and aren't running Radar. | `POST /company/find?ip={IP}` | | **Session ID** | You're also running [Radar](/powered-by-snitcher/radar/introduction) and have a visitor's `session_uuid`. | `POST /radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find` | **Running Radar? Prefer the session ID.** A session lookup resolves the visitor through Radar's fingerprinting model rather than the IP alone, which yields a higher match rate than a raw IP lookup. ### By IP Address Send the IP address as the `ip` query parameter. This is the default method described throughout this page. ```bash theme={null} curl --location --request POST 'https://api.snitcher.com/company/find?ip={IP}' \ --header 'Authorization: Bearer {key}' \ --header 'Accept: application/json' ``` ### By Session ID When you also run Radar, every visitor session has a `session_uuid`. Pass it to the Radar identification endpoint to identify the company behind that session. See [Receiving Events](/powered-by-snitcher/radar/receiving-events) for how session IDs are generated and delivered. ```bash theme={null} curl --location --request POST 'https://api.snitcher.com/radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find' \ --header 'Authorization: Bearer {key}' \ --header 'Content-Type: application/json' \ --data '{ "session_uuid": "42b7c5e0-76c0-4f8d-9b7c-6b8e1a2d3f45" }' ``` **Session IDs are short-lived.** By default this lookup only covers sessions from the **last 2 days**. To identify an older session, add the optional `since` field — an ISO 8601 date (UTC) naming the day the session took place. The date may be up to **30 days** in the past and cannot be in the future. Requests for a session that falls outside the queried window won't match. ```bash theme={null} curl --location --request POST 'https://api.snitcher.com/radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find' \ --header 'Authorization: Bearer {key}' \ --header 'Content-Type: application/json' \ --data '{ "session_uuid": "42b7c5e0-76c0-4f8d-9b7c-6b8e1a2d3f45", "since": "2026-05-11" }' ``` ## Endpoint The API endpoint is as follows: ``` https://api.snitcher.com/company/find?ip={IP} ``` ## Example Request Here is an example of a curl request to this endpoint: ```bash theme={null} curl --location --request POST 'https://api.snitcher.com/company/find?ip={IP}' \ --header 'Authorization: Bearer {key}' \ --header 'Accept: application/json' ``` ## Response Codes The Snitcher API uses standard HTTP status codes to indicate the success or failure of an API request. Below are examples of different responses you may encounter: ### HTTP 429 - Rate Limit Exceeded ```json theme={null} { "message": "Too Many Attempts." } ``` ### HTTP 403 - Quota Exceeded ```json theme={null} { "message": "You have exceeded your allowed quota. Please upgrade to a plan that allows more volume or wait for your billing cycle to reset." } ``` ### HTTP 202 - Enrichment Queued ```json theme={null} { "status": 202, "message": "Queued for enrichment. Please retry this request in a few seconds." } ``` ### HTTP 200 - Identified Company Response ```json theme={null} { "ip": "127.0.0.1", "fuzzy": true, "domain": "snitcher.com", "type": "business", "company": { "name": "Snitcher", "domain": "snitcher.com", "website": "https://snitcher.com", "industry": "Information Technology and Services", "founded_year": "2015", "employee_range": "2-10 employees", "annual_revenue": 2000000, "total_funding": null, "location": "Oude Enghweg 2, 1217 JC Hilversum, Netherlands", "description": "Snitcher supports B2B teams by identifying the company's anonymous website visitors work for.", "phone": "+1 (120) 261-5475", "geo": { "country": "Netherlands", "country_code": "NL", "state": "Noord-Holland", "state_code": "NH", "postal_code": "1217 JC", "city": "Hilversum", "street": "Oude Enghweg", "street_number": "2" }, "profiles": { "crunchbase": { "handle": "snitcher", "url": "https://crunchbase.com/organization/snitcher" }, "linkedin": { "handle": "snitcher", "url": "https://linkedin.com/companies/snitcher" } } }, "geoIP": { "country": "Netherlands", "country_code": "NL", "city": "Almere Stad", "state": "Flevoland" } } ``` ### **HTTP 404 - Non-Identified Response (ISP)** ```json theme={null} { "ip": "223.19.38.219", "fuzzy": false, "domain": null, "type": "isp", "geoIP": { "country": "Hong Kong", "country_code": "HK", "city": "Hong Kong", "state": "Hong Kong" } } ``` ## Checking Usage The API endpoint is as follows: ``` https://api.snitcher.com/company/usage ``` ### **HTTP 200 - Example Response** ```json theme={null} { "status": "trial", "credits": { "total": 100, "used": 0, "remaining": 100 }, "billing_cycle": { "starts_at": "2025-03-23T14:10:04.000000Z", "ends_at": "2025-04-23T14:10:04.000000Z" } } ``` # Identify company for a session Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/company/identify-company-for-a-session https://app.snitcher.com/api/radar/docs?api-radar-docs.json post /radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find Returns company information for the current visitor's session when available. Provide a session UUID when you want to restrict lookup to a specific session. # Create a tracking script filter Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/create-a-tracking-script-filter https://app.snitcher.com/api/radar/docs?api-radar-docs.json post /radar/operator/v1/tracking-scripts/{trackingScriptId}/filters # Delete a tracking script filter Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/delete-a-tracking-script-filter https://app.snitcher.com/api/radar/docs?api-radar-docs.json delete /radar/operator/v1/tracking-scripts/{trackingScriptId}/filters/{filterUuid} # Generate a tracking script Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/generate-a-tracking-script https://app.snitcher.com/api/radar/docs?api-radar-docs.json post /radar/operator/v1/tracking-scripts # Get a single tracking script Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/get-a-single-tracking-script https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/tracking-scripts/{trackingScriptId} Returns a single tracking script by ID # List tracking script filters Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/list-tracking-script-filters https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/tracking-scripts/{trackingScriptId}/filters # List tracking scripts Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/list-tracking-scripts https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/tracking-scripts Returns a paginated list of tracking scripts for the given workspace. Filtering by description or internal identifier is supported. # Replace tracking script filters Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/replace-tracking-script-filters https://app.snitcher.com/api/radar/docs?api-radar-docs.json put /radar/operator/v1/tracking-scripts/{trackingScriptId}/filters # Update a tracking script Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/tracking-scripts/update-a-tracking-script https://app.snitcher.com/api/radar/docs?api-radar-docs.json patch /radar/operator/v1/tracking-scripts/{trackingScriptId} # Get IP-to-Company (Reveal API) credit usage Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/usage/get-ip-to-company-reveal-api-credit-usage https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/company/usage Returns billable IP-to-Company usage for the current billing cycle, per tracking script. A unit is a distinct successful (HTTP 200) de-anonymisation deduped per (tracking script, monthly window) — the exact figure billing charges a credit for. Operators reconcile this per cycle to know which lookups were billed. # Get tracking script usage Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/usage/get-tracking-script-usage https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/usage Returns usage data for tracking scripts in the workspace # Get webhook configuration Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/webhooks/get-webhook-configuration https://app.snitcher.com/api/radar/docs?api-radar-docs.json get /radar/operator/v1/webhooks # Update webhook configuration Source: https://docs.snitcher.com/powered-by-snitcher/radar-api-reference/webhooks/update-webhook-configuration https://app.snitcher.com/api/radar/docs?api-radar-docs.json patch /radar/operator/v1/webhooks # Capturing Events Source: https://docs.snitcher.com/powered-by-snitcher/radar/capturing-events How Radar tracks pageviews, interactions, and custom behavior on your customers' sites. Radar's tracking script is designed to capture key user interactions automatically while giving you the tools to let your customers track what's unique to their sites. ## Automatic Event Capture Once installed on your customer's site, Radar automatically captures `$pageview` events. You can enable more advanced automatic event tracking by setting the appropriate [feature flags](/powered-by-snitcher/radar/configuration#feature-flags) in your configuration. ### Page Tracking (Enabled by Default) * **`$pageview`**: Fired every time a page is loaded or the URL hash changes. Includes details like the page URL, title, and referrer. When a user navigates away from a page, Radar captures engagement data (total time on page and engaged time) and includes it in the event as `$total_time_on_page` and `$engaged_time_on_page` properties. ### Form Tracking (`features.formTracking`) When you enable `formTracking`, Radar will automatically capture the following events on your customers' websites: * **`$form_start`**: Fired when a user first interacts with a form field (e.g., focus or input). Includes the form's ID. * **`$form_submit`**: Fired when a user successfully submits a form. The event includes the form's name, ID, and all non-sensitive field values. * **`$form_abandon`**: Fired when a user interacts with a form's fields but navigates away from the page without submitting. Radar automatically redacts data from fields that appear to be sensitive (e.g., fields with names like `password`, `credit_card`, `ssn`). ### Click & Download Tracking (`features.clickTracking`, `features.downloadTracking`) * **Click Tracking**: When you enable `clickTracking`, Radar automatically captures clicks on `` and ` ``` ## 3. Revoking Consent (CCPA Opt-Out) The `waitForConsent` flow above is the **opt-in** model used for regulations like GDPR, where tracking stays session-scoped until the user actively agrees. Regulations like the CCPA instead use an **opt-out** model: tracking is on by default, and the user has the right to withdraw consent at any time (for example, via a "Do Not Sell or Share My Personal Information" link). For this posture, leave `waitForConsent` at its default (`false`) so Radar identifies visitors normally, and call the `denyCookieConsent()` method when one of your customer's users opts out. ```javascript theme={null} // Your customer calls this when their user opts out or withdraws consent YourAppName.denyCookieConsent(); ``` Calling this function does three things: * It clears that end user's persisted identity — device ID, user traits, and session data — from both cookies and `localStorage`. * It drops Radar back to session-scoped storage, so the user is no longer recognized across sessions from that point forward. * It records the opt-out durably, so the choice survives page loads and future sessions and is not overridden by an automatic (CMP-reported) grant. The opt-out is reversible. If the user later opts back in, calling `giveCookieConsent()` clears the recorded opt-out and re-enables persistent storage. #### Example: Integrating an Opt-Out Control Here is a simple example of how your customer could wire a "Do Not Track" control to Radar. It mirrors the accept flow above. ```html HTML theme={null} ``` # Installation Source: https://docs.snitcher.com/powered-by-snitcher/radar/installation Get Radar up and running with custom branding for your customers. Installing Radar is a two-part process. First, you'll perform a **one-time setup** to brand the tracking infrastructure with your own domains. After that, you'll follow a simple workflow to **generate and deploy a unique tracker** for each of your customers. ## Prerequisites Before installing Radar, ensure you have: * A Snitcher account with Radar access. Contact support to enable it. * Your API key for accessing the Radar Operator API. *** ## Part 1: One-Time Branding Setup (Whitelabeling) This branding setup is highly recommended for a true whitelabel experience. However, it is **optional**. If you prefer to get started quickly without configuring custom domains, you can skip this section and use the default Snitcher-branded hosts in your loader script:

**CDN Host:** `cdn.snitcher.com`
**API Host:** `radar.snitcher.com`
To make Radar feel completely native to your product, you'll proxy its core services through your own branded domains. This is crucial for maintaining a seamless user experience and ensuring first-party data collection. The following guides walk through setting this up with **AWS CloudFront**, a common and reliable choice. This proxy serves the `radar.js` script from your domain, building trust and improving reliability. Log in to the **AWS Console**, navigate to **CloudFront**, and click **Create distribution**. You will be guided through a multi-step wizard. **Step 1: Get Started** * **Distribution name (optional):** Give your distribution a memorable name, like `YourApp Radar CDN`. * **Custom domain:** Enter your desired subdomain (e.g., `cdn.your-app.com`). Click **Next**. *** **Step 2: Specify Origin** * **Specify origin type:** Select **Other**. * **Custom origin:** Enter `cdn.snitcher.com`. * **Settings:** Keep the defaults. Select **Use recommended origin settings** and **Use recommended cache settings**. These defaults are optimized for custom origins and will handle caching, allowed methods (`GET`, `HEAD`), and protocol policies (`Redirect HTTP to HTTPS`) correctly. Click **Next**. *** **Step 3: Enable Security** * **Web Application Firewall (WAF):** For this basic setup, you can select **Do not enable security protections**. Click **Next**. *** **Step 4: Get TLS Certificate** * A **Custom SSL certificate** is required to use your custom domain. You must have a certificate for your domain (e.g., `cdn.your-app.com`) available in **AWS Certificate Manager (ACM)** in the **us-east-1** region. * CloudFront will automatically find and select the correct certificate for the custom domain you entered in Step 1. Click **Next**. *** **Step 5: Review and Create** * Review the summary of your settings to ensure they are correct. * Click **Create distribution**. After you create it, wait for the distribution to finish deploying. Once ready, copy the **Distribution domain name** (e.g., `d12345abcdef.cloudfront.net`) for the next step. In your domain registrar's DNS panel, create a new `CNAME` record pointing your branded subdomain to CloudFront. * **Type:** `CNAME` * **Name / Host:** `cdn` (or the subdomain you chose) * **Value / Points to:** The CloudFront **Distribution domain name** you just copied. Save the record. DNS changes can take a few minutes to a few hours to propagate. Once DNS has updated, run the following command in your terminal. A `403 Forbidden` response is expected and confirms the proxy is working correctly. ```bash theme={null} curl -I https://cdn.your-app.com ``` This proxy routes all tracking data through your branded endpoint, making Radar's infrastructure invisible. Create a second CloudFront distribution with settings optimized for a real-time API. Go to the **AWS Console**, navigate to **CloudFront**, and click **Create distribution**. **Step 1: Get Started** * **Distribution name (optional):** `YourApp API Proxy` * **Custom domain:** `api.your-app.com` Click **Next**. *** **Step 2: Specify Origin** * **Specify origin type:** Select **Other**. * **Custom origin:** Enter `radar.snitcher.com`. * **Settings:** This is the most critical step. Select **Customize cache settings**. * **Cache policy:** From the dropdown, select the managed policy named **`CachingDisabled`**. This ensures API requests are never cached and are always passed through in real-time. * **Origin request policy:** Select the managed policy named **`AllViewerExceptHostHeader`**. This forwards all necessary headers, cookies, and query strings to the Radar API. Click **Next**. *** **Step 3: Enable Security** * **Web Application Firewall (WAF):** Select **Do not enable security protections**. Click **Next**. *** **Step 4: Get TLS Certificate** * A **Custom SSL certificate** for `api.your-app.com` must be available in **AWS Certificate Manager (ACM)** in the **us-east-1** region. CloudFront will automatically select it. Click **Next**. *** **Step 5: Review and Create** * Review the settings and click **Create distribution**. * Wait for the distribution to deploy, then copy the **Distribution domain name** (e.g., `d67890uvwxyz.cloudfront.net`). After the distribution is created and deployed, you must disable IPv6. 1. In the CloudFront distributions list, click on the ID of the API proxy distribution you just created. 2. Under the **General** tab, click **Edit**. 3. Scroll down to the **Settings** section. 4. Find the **IPv6** option and select **Off**. 5. Click **Save changes**. Create another `CNAME` record in your DNS settings: * **Type:** `CNAME` * **Name / Host:** `api` (or `api.your-app`) * **Value / Points to:** The CloudFront **Distribution domain name** you copied for your API proxy. Run a `curl` command to verify the API proxy. The server should respond with a message confirming the connection is live. ```bash theme={null} curl https://api.your-app.com ``` *** ## Part 2: Customer Installation Workflow Once your branded domains are ready, you can start generating trackers for your customers. For each customer, make a `POST` request to the **Generate a Tracking Script** endpoint in the API Reference. Include an `internal_identifier` that maps to the customer's ID in your own system. This identifier will be included in every webhook event, making it easy to associate data with the correct customer account. ```bash cURL theme={null} curl -X POST 'https://api.snitcher.com/radar/operator/v1/tracking-scripts' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "internal_identifier": "customer-abc-123", "description": "Tracking script for Customer ABC" }' ``` ```json Response theme={null} { "tracking_script_id": "ts_a1b2c3d4e5f6g7h8", "internal_identifier": "customer-abc-123", "description": "Tracking script for Customer ABC", "created_at": "2025-08-13T18:30:00Z" } ``` You'll receive a unique `tracking_script_id` for this customer. Construct the loader script for your customer to install on their website. It's crucial to populate the configuration object with your branded domains and the `tracking_script_id` you just generated. ```html HTML theme={null} ``` **Configuration Parameters:** * `cdn`: **(Required)** Your custom CDN proxy domain (e.g., `cdn.your-app.com`). * `apiEndpoint`: **(Required)** Your custom API proxy domain (e.g., `api.your-app.com`). * `profileId`: **(Required)** The unique `tracking_script_id` generated for the customer. * `namespace`: **(Required)** The name of the global JavaScript object your customers will use to interact with the tracker (e.g., `YourAppName`). This allows them to call functions like `YourAppName.track("Custom Event")`. We recommend using a single, consistent namespace across your entire customer base. This simplifies your own documentation, as you can always instruct your customers to use the same object name. It also prevents conflicts with other scripts on your customer's site. * `waitForConsent`: **(Optional)** When set to true, the tracker will wait until a visitor has given cookie consent before saving any data in their browser. If consent isn't given, the tracker will still work but will only keep data for the current visit (not saved after the browser is closed). The default is false. See [Consent Management](/powered-by-snitcher/radar/consent-management) for more details All of these settings and more can be customized. See the full [Configuration Reference](/powered-by-snitcher/radar/configuration) for a complete list of options, including how to enable powerful features like automatic session, form, and click tracking. Ask your customer to place the script in the `` section of their website. Once the script is live, Radar will immediately begin to capture events. You can verify the installation is working by checking your configured webhook endpoint for incoming data. Learn what events Radar captures automatically and how to track custom actions. See the data structure of webhook payloads and choose your delivery mode. # Introduction Source: https://docs.snitcher.com/powered-by-snitcher/radar/introduction Radar: Powerful, Whitelabeled Web Tracking **Please Note:** Radar is a standalone offering and is not included with our standard product plans. If you'd like to purchase or learn more about Radar, please reach out to support. ## What is Radar? Imagine adding powerful **Visitor ID** and **Intent Signals** to your own software product. Your customers could see which companies are visiting their websites and understand user behavior, all from within your application and under your brand. Building this from scratch is a massive undertaking, diverting your engineers from your core product for months. **Radar is the engine that powers these features for you.** For nearly a decade, Snitcher has built advanced web tracking systems to power our own platform. With Radar, we've packaged that same battle-tested infrastructure into a flexible, scalable, and fully brandable solution you can drop into your own product in days, not months. ### Key Outcomes for Your Business Offer valuable analytics features that make your product indispensable to your customers. Monetize visitor identification and behavioral analytics as a premium add-on to your existing plans. Launch analytics and intent features in weeks, not years, and focus your engineers on what makes your product unique. *** ## Why Use Radar? It Solves the Hard Problems. Radar helps you go to market fast with a highly reliable, fully managed backend that you can present as your own. * **Offer Powerful Analytics, Instantly:** Provide your customers with automatic tracking for sessions, form submissions, and clicks without any complex setup on their part. * **Maintain Your Brand Integrity:** Radar is completely invisible to your customers. All tracking scripts and data endpoints are served from your own domains. * **Eliminate Maintenance Headaches:** We handle the complexities of browser changes (like ITP), evolving privacy laws (GDPR/CCPA), and infrastructure scaling so your team can focus. * **You Control the Data Flow:** We stream raw events or fully processed sessions to **your webhook endpoint**. You can then process this data and display it in your application however you choose. *** ## The Build vs. Buy Trade-off For most companies, the decision to build a system like this comes down to one question: "Is this the best use of our engineering resources?" Building a tracking system distracts your team from your core product, and the ongoing maintenance is a permanent tax on your roadmap. | **Consideration** | **Build In-House** | **With Radar** | | ------------------------ | -------------------------------------------------------- | -------------------------------------------------------- | | **Time to Launch** | 6–12 months | \< 1 week | | **Initial Dev Cost** | 1000+ engineering hours | Zero | | **Ongoing Maintenance** | Constant updates for browsers & privacy laws | Fully managed by Snitcher | | **Infrastructure & Ops** | Your responsibility to scale, secure, and operate | Auto-scaled, secure, and operated by us | | **Core Product Focus** | Diverted to building and maintaining a secondary product | Your team stays focused on what makes your product great | For your technical team, consider the scope of a home-grown solution: * **You'll need to build** a tracker, event pipeline, enrichment engine, and privacy layer—just to get started. * **You'll need to constantly adapt** to browser quirks, cookie rules, and evolving compliance laws (GDPR, CCPA). * **Every update** to this secondary system adds risk and technical debt, pulling resources from your main product. *** ## How It Works Using Radar is simple. You provide the wrapper—Radar does the heavy lifting. ```mermaid theme={null} flowchart LR subgraph "Your customer's website" A["Website Visitor"] end subgraph "Your Application & Infrastructure" direction TB B["Your Branded CDN
cdn.your-app.com"] C["Your Branded API
api.your-app.com"] D["Your Webhook Endpoint
Receives enriched data"] end subgraph "Radar Infrastructure" direction TB E["Radar CDN
Serves radar.js"] F["Radar API
Collects, enriches, processes"] end A -- "Loads radar.js from" --> B B -- "Proxies script request to" --> E E -- "Returns script to proxy" --> B B -- "Serves script" --> A A -- "Sends tracking data to" --> C C -- "Proxies data to" --> F F -- "Delivers processed data to" --> D ``` Use our API to generate a unique tracking script configuration for each of your customers. Your customer installs a small JavaScript snippet on their website. All network requests are proxied through your branded domains. Radar immediately begins tracking user behavior and streams the data to your webhook endpoint in real-time. *** ## A Peek Under the Hood The Radar loader handles it all: * Automatically updates the SDK * Circumvents ITP and browser restrictions * Routes requests through your domain for 1st-party compliance * Configurable features: form tracking, click tracking, session tracking, and more. See the full [Configuration Reference](/powered-by-snitcher/radar/configuration). ```javascript theme={null} !(function (e) { "use strict"; var a = e && e.namespace; if (a && e.profileId && e.cdn) { var r = window[a]; if (((r && Array.isArray(r)) || (r = window[a] = []), !r.initialized && !r._loaded)) if (r._loaded) console && console.warn("[Radar] Duplicate initialization attempted"); else { r._loaded = !0; [ "track", "page", "identify", "company", "group", "alias", "ready", "debug", "on", "off", "once", "trackClick", "trackSubmit", "trackLink", "trackForm", "pageview", "screen", "reset", "register", "setAnonymousId", "addSourceMiddleware", "addIntegrationMiddleware", "addDestinationMiddleware", "giveCookieConsent", "denyCookieConsent", ].forEach(function (e) { var i; r[e] = ((i = e), function () { var e = window[a]; if (e.initialized) return e[i].apply(e, arguments); var r = [].slice.call(arguments); return r.unshift(i), e.push(r), e; }); }), (r.bootstrap = function () { var a = document.createElement("script"); (a.async = !0), (a.type = "text/javascript"), (a.id = "__radar__"), (a.dataset.settings = JSON.stringify(e)), (a.src = "https://"+e.cdn+"/releases/latest/radar.min.js"); var r = document.scripts[0]; r.parentNode.insertBefore(a, r); }), r.bootstrap(); } } else "undefined" != typeof console && console.error("[Radar] Configuration incomplete"); })({ cdn: "cdn.your-domain.com", apiEndpoint: "api.your-domain.com", profileId: "TRACKING-SCRIPT-ID", namespace: "YourApp", }); ``` *** ## Deployment: Branding the Radar Experience To make Radar feel native to your product, you'll configure: ### CDN Proxy Host the tracking SDK under your brand (cdn.your-domain.com) by setting up a cloud proxy (like AWS CloudFront) pointing to cdn.snitcher.com. ### API Proxy Send tracking data through your own API hostname (api.your-domain.com) via another cloud proxy for radar.snitcher.com. *** ## Rate Limits The Radar Operator API enforces the following rate limits to ensure platform stability: * **60 requests per minute** (per API token) When you exceed the rate limit, the API will return an `HTTP 429 Too Many Attempts` response. Implement exponential backoff in your application to handle rate limiting gracefully. Higher rate limits can be configured on your account upon request. Contact support if you need increased throughput for your Radar integration. *** ## Built for Builders. Backed by Snitcher. Radar combines the power of enterprise-grade tracking with the flexibility of a drop-in SDK. Whether you're trying to offer analytics to your own customers, build a new data product, or integrate behavioral insights into your platform, Radar gets you there without the infrastructure tax. Start with one customer. Scale to millions. Radar handles the rest. # JavaScript SDK Source: https://docs.snitcher.com/powered-by-snitcher/radar/javascript-sdk A complete reference for the methods available on the Radar JavaScript object for your customers to use. Once your customer installs the Radar loader script on their website, it exposes a global object with the `namespace` you defined. This JavaScript SDK provides a set of methods that your customers can use to send custom data, manage their users' identity, and control the tracker's behavior. Throughout this guide, we'll use `YourAppName` as the example namespace that you would provide to your customers. ## Core Methods ### track The `track` method is the primary way for your customers to send custom event data to Radar. ```javascript theme={null} YourAppName.track(eventName, properties); ``` The name of the event to track. You should advise your customers to use a consistent `[Object] [Verb]` naming convention, such as `Document Signed` or `Video Played`. A JSON object of key-value pairs to send as metadata with the event. **Example Implementation:** ```javascript theme={null} // Your customer would implement this after a successful action YourAppName.track("Trial Started", { plan: "Pro", source: "Website CTA" }); ``` ### identify The `identify` method allows your customers to associate a known user with their activity on the website. Once identified, the provided traits are stored by Radar and attached to all future events from that user. ```javascript theme={null} YourAppName.identify(email, traits); ``` The user's email address. Radar uses this as the primary identifier for enrichment. A JSON object of additional key-value pairs representing the user's traits. **Example Implementation:** ```javascript theme={null} // Your customer could call this after a user signs in YourAppName.identify("hello@snitcher.com", { name: "Alex", plan: "Enterprise" }); ``` ### page While Radar tracks pageviews automatically in most cases, the `page` method can be used to manually trigger a pageview event. This is useful in Single-Page Applications (SPAs) where routing changes don't always trigger a full page load. ```javascript theme={null} YourAppName.page(); ``` ## Consent Management ### giveCookieConsent This method signals to Radar that an end user has provided consent to use persistent storage (cookies and `localStorage`). See the [Consent Management](/powered-by-snitcher/radar/consent-management) guide for a full walkthrough. ```javascript theme={null} // Your customer calls this when their user accepts the cookie policy YourAppName.giveCookieConsent(); ``` ### denyCookieConsent This method is the symmetric counterpart to `giveCookieConsent`. It signals that an end user has revoked (or declined) consent — the CCPA opt-out case. Radar clears the user's persisted identity (device ID, traits, and session data) from both cookies and `localStorage`, drops back to session-scoped storage so the user is no longer recognized across sessions, and records the opt-out so it persists across page loads. The opt-out is reversible: calling `giveCookieConsent()` again re-enables persistent storage. See the [Consent Management](/powered-by-snitcher/radar/consent-management) guide for a full walkthrough. ```javascript theme={null} // Your customer calls this when their user opts out or withdraws consent YourAppName.denyCookieConsent(); ``` ## Advanced Methods ### flush Forces the tracker to immediately send any queued events to the Radar API. This can be useful for your customers in specific situations where they need to ensure data is sent before a certain action. ```javascript theme={null} YourAppName.flush(); ``` ### on Allows you to build functionality that listens for events emitted by the tracker on your customer's site. Your customers can use this to integrate the tracker's lifecycle with their own application code. ```javascript theme={null} YourAppName.on(eventName, callback); ``` The name of the internal tracker event to listen for. Common events include: `initialized`, `identify`, `page_view`, `track`, `form_submit`, `click`, `download`. A function to execute when the event occurs. The callback will receive the event payload as an argument. **Example Implementation:** ```javascript theme={null} // Your customer could use this to update their UI when a user is identified YourAppName.on('identify', (traits) => { console.log('User identified:', traits); }); ``` # Receiving Events Source: https://docs.snitcher.com/powered-by-snitcher/radar/receiving-events Deliver Radar events to your backend via webhooks. Radar delivers tracked data to your backend using webhooks. Before you can receive events, you must configure a webhook endpoint. You can choose between two delivery modes depending on your use case. ## Choosing a Delivery Mode Events are pushed to your webhook **as they occur**, in near real-time. **Pros:** * Low latency for real-time applications. * Immediate access to individual events. **Tradeoffs:** * Requires you to perform session stitching. * You must calculate session-level metrics (like time on page). Events are grouped by session and sent in a single payload **after the session ends** (typically 30 minutes of inactivity). **Pros:** * Session metrics are pre-computed for you. * Data is fully enriched and ready for analysis. * Simpler to process and store. Event-based and session-based payloads share the same structure. The difference is that event-based payloads contain a single event in the `events` array and are sent in near real-time, while session-based payloads contain all events from the session and are sent after 30 minutes of inactivity. ### Selecting your delivery mode Set the delivery mode with the `event_aggregation` field (`per_session` or `per_event`) on the [webhook configuration endpoint](/powered-by-snitcher/radar-api-reference). See the API Reference for the request and response details. Need an identification **during** a session rather than waiting for a webhook? Call the **Identify company for a session** endpoint (`POST /radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find`) with the visitor's `session_uuid`. By default this lookup only covers sessions from the **last 2 days**. To identify an older session, pass the optional `since` field — an ISO 8601 date (UTC) naming the day the session took place. The lookup is then scoped to that single calendar day. The date may be up to 30 days in the past and cannot be in the future. ```bash cURL theme={null} curl -X POST 'https://api.snitcher.com/radar/operator/v1/tracking-scripts/{trackingScriptId}/company/find' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "session_uuid": "42b7c5e0-76c0-4f8d-9b7c-6b8e1a2d3f45", "since": "2026-05-11" }' ``` *** ## Example: Pageview Event (Session-Based) This example shows a session payload containing a single `$pageview` event. Note the enriched context and pre-computed engagement times. ```json Pageview Event expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "anonymous-user-4455" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "$pageview", "created_at": "2025-06-16T13:02:17+00:00", "context": { "type": "browser", "geo": { "ip": "192.0.2.45", "country": "Germany", "region": "Berlin", "city": "Berlin" }, "device_uuid": "device-789", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", "browser": { "name": "Chrome", "version": "122.0.0.0" }, "device": { "type": "Desktop", "operating_system": "Windows", "operating_system_version": "10" }, "referrer": { "scheme": "https", "host": "newsletter.example.com", "path": "/latest", "query": "utm_source=newsletter&utm_medium=email", "fragment": "section-2" }, "utm": { "source": "newsletter", "medium": "email", "campaign": "june-product-update", "content": "cta-button", "term": "conversion" }, "page": { "url": "https://app.example.com/dashboard?view=analytics", "title": "User Dashboard - Analytics Overview", "engagement_time": 542 } }, "event_properties": { "$url": "https://app.example.com/dashboard?view=analytics", "$title": "User Dashboard - Analytics Overview", "$scheme": "https", "$host": "app.example.com", "$path": "/dashboard", "$query": { "view": "analytics" }, "$fragment": "section-2", "$total_time_on_page": 937, "$engaged_time_on_page": 542 }, "user_properties": { "$uuid": "anonymous-user-4455" }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` ## Example: Identified Visitor (Session-Based) When a visitor is identified — for example via the [`identify`](/powered-by-snitcher/radar/javascript-sdk#identify) SDK method or an `sn_email` query parameter — `user_properties` includes their `$email` and any `$traits` at both the session and event level. ```json Identified Visitor expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "anonymous-user-4455", "$email": "jane.doe@example.com", "first_name": "Jane", "title": "VP Marketing" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "$pageview", "created_at": "2025-06-16T13:02:17+00:00", "context": { "type": "browser", "geo": { "ip": "192.0.2.45", "country": "Germany", "region": "Berlin", "city": "Berlin" }, "device_uuid": "device-789", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", "browser": { "name": "Chrome", "version": "122.0.0.0" }, "device": { "type": "Desktop", "operating_system": "Windows", "operating_system_version": "10" }, "referrer": { "scheme": "https", "host": "newsletter.example.com", "path": "/latest", "query": "utm_source=newsletter&utm_medium=email", "fragment": null }, "utm": { "source": "newsletter", "medium": "email", "campaign": "june-product-update", "content": "cta-button", "term": null }, "page": { "url": "https://app.example.com/pricing?sn_email=jane.doe@example.com&sn_trait_first_name=Jane&sn_trait_title=VP+Marketing", "title": "Pricing - Plans for Every Team", "engagement_time": 542 } }, "event_properties": { "$url": "https://app.example.com/pricing?sn_email=jane.doe@example.com&sn_trait_first_name=Jane&sn_trait_title=VP+Marketing", "$title": "Pricing - Plans for Every Team", "$scheme": "https", "$host": "app.example.com", "$path": "/pricing", "$query": { "sn_email": "jane.doe@example.com", "sn_trait_first_name": "Jane", "sn_trait_title": "VP Marketing" }, "$fragment": null, "$total_time_on_page": 937, "$engaged_time_on_page": 542 }, "user_properties": { "$uuid": "anonymous-user-4455", "$email": "jane.doe@example.com", "$traits": { "first_name": "Jane", "title": "VP Marketing" } }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` ## Example: Form Submit Event (Session-Based) This example shows how a form submit event appears in a session payload. ```json Form Submit Event expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "pirate-user-456" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "$form_submit", "created_at": "2025-06-16T13:02:17+00:00", "context": { "type": "browser", "geo": { "ip": "198.51.100.23", "country": "Netherlands", "region": "North Holland", "city": "Amsterdam" }, "device_uuid": "pirate-device-789", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15", "browser": { "name": "Safari", "version": "16.4" }, "device": { "type": "Desktop", "operating_system": "macOS", "operating_system_version": "12.6.1" }, "page": { "url": "https://www.example.com/pricing", "title": "Pricing - Plans for Every Team", "engagement_time": 542 } }, "event_properties": { "$form_id": "contact-form", "$form_name": "Contact us", "$fields": [ { "$name": "full_name", "$type": "text", "$tag_name": "input", "$value": "Jane Doe" }, { "$name": "email", "$type": "email", "$tag_name": "input", "$value": "jane.doe@example.com" }, { "$name": "message", "$type": "textarea", "$tag_name": "textarea", "$value": "I'd like to learn more about your pricing options." } ] }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` ## Example: Custom Event (Session-Based) This example shows how a custom `track` event appears in a session payload. The data from the second argument of the `track` call is nested inside `event_properties`. ```json Custom Event expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "pirate-user-456" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "CTA_clicked", "created_at": "2025-06-16T13:02:17+00:00", "context": { "type": "browser", "geo": { "ip": "198.51.100.23", "country": "Netherlands", "region": "North Holland", "city": "Amsterdam" }, "device_uuid": "pirate-device-789", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15", "browser": { "name": "Safari", "version": "16.4" }, "device": { "type": "Desktop", "operating_system": "macOS", "operating_system_version": "12.6.1" }, "page": { "url": "https://www.example.com/pricing", "title": "Pricing - Plans for Every Team", "engagement_time": 542 } }, "event_properties": { "cta_text": "Try for free", "cta_position": "navbar-right" }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` ## Example: Click Event (Session-Based) This example shows how a click event appears in a session payload when `clickTracking` is enabled. ```json Click Event expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "pirate-user-456" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "$click", "created_at": "2025-06-16T13:05:30+00:00", "context": { "type": "browser", "geo": { "ip": "198.51.100.23", "country": "Netherlands", "region": "North Holland", "city": "Amsterdam" }, "device_uuid": "pirate-device-789", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15", "browser": { "name": "Safari", "version": "16.4" }, "device": { "type": "Desktop", "operating_system": "macOS", "operating_system_version": "12.6.1" }, "page": { "url": "https://www.example.com/pricing", "title": "Pricing - Plans for Every Team", "engagement_time": 542 } }, "event_properties": { "$element_tag": "a", "$element_text": "Start Free Trial", "$href": "https://www.example.com/signup", "$element_classes": "btn btn-primary", "$element_path": "body > main > section.hero > a.btn" }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` ## Example: Download Event (Session-Based) This example shows how a download event appears in a session payload when `downloadTracking` is enabled. ```json Download Event expandable theme={null} { "internal_identifier": "my-customer-id", "session_uuid": "123e4567-e89b-12d3-a456-426614174000", "start_time": "2025-06-16T13:00:00+00:00", "last_activity": "2025-06-16T13:15:42+00:00", "engagement_time": 937, "user_properties": { "$uuid": "pirate-user-456" }, "events": [ { "event_uuid": "89ab1234-cdef-5678-9012-3456789abcde", "event_name": "$download", "created_at": "2025-06-16T13:08:12+00:00", "context": { "type": "browser", "geo": { "ip": "198.51.100.23", "country": "Netherlands", "region": "North Holland", "city": "Amsterdam" }, "device_uuid": "pirate-device-789", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15", "browser": { "name": "Safari", "version": "16.4" }, "device": { "type": "Desktop", "operating_system": "macOS", "operating_system_version": "12.6.1" }, "page": { "url": "https://www.example.com/resources", "title": "Resources - Whitepapers & Guides", "engagement_time": 320 } }, "event_properties": { "$href": "https://www.example.com/files/2025-product-guide.pdf", "$file_name": "2025-product-guide.pdf", "$element_path": "body > main > section.resources > a.download-link" }, "meta": { "library": { "name": "radar.js", "version": "1.8.0" } } } ] } ``` # SPA & Client-Side Routing Source: https://docs.snitcher.com/powered-by-snitcher/radar/spa-tracking How Radar automatically tracks pageviews in your customers' Single-Page Applications (SPAs). Radar is designed to work seamlessly with modern Single-Page Applications (SPAs) built with frameworks like React, Vue, or Svelte, which your customers may be using. ## Automatic Pageview Tracking By default, Radar automatically detects client-side route changes on your customer's website. In modern browsers, it uses the [Navigation API](https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API) for reliable detection. In older browsers, it falls back to monkey-patching the browser's History API (`pushState` and `replaceState`) and listening for the `popstate` event. This means that for the vast majority of your customers' SPAs, you do **not** need to provide any extra configuration to get accurate pageview tracking. As long as their routing library uses standard browser navigation, Radar will automatically fire a `$pageview` event every time the route changes. ## Manual Tracking with the `page` Method In some rare cases, your customer may need to manually tell Radar when a pageview has occurred. The `YourAppName.page()` method is provided for these scenarios. You should advise your customers to use this if: * Their application uses a routing library that does not interact with the browser's History API in a standard way. * They want to record a pageview for an interaction that doesn't change the URL, such as opening a significant modal window. To manually trigger a pageview, your customer would call the `page` method: ```javascript theme={null} // Your customer would call this to manually trigger a pageview event YourAppName.page(); ``` # How Snitcher Works Source: https://docs.snitcher.com/product/how-snitcher-works Snitcher uses IP intelligence to identify companies and first-party tracking to identify users visiting your website. Learn how the technology works. **Snitcher identifies companies visiting your website using IP intelligence and tracks individual users through first-party cookies.** When a visitor loads your page, Snitcher captures their IP address and matches it against a proprietary database of business networks to reveal the company. When users provide their email (via forms, login, or tracked links), Snitcher links their entire browsing history to that identity. ## Data Collection Snitcher collects data via a lightweight JavaScript tracker installed on your website. Most companies install it on their: * Marketing website * Blog and content pages * Documentation / help center * Application (for product usage signals) The tracker automatically captures: * **Pageviews**: Every page visited, including time on page * **Sessions**: Grouping activity into browsing sessions * **Referrers**: Where visitors came from (Google, LinkedIn, email campaigns, etc.) * **UTM Parameters**: Campaign tracking data * **Device Info**: Browser, operating system, screen size * **Form Submissions**: When enabled, captures form interactions The tracker is asynchronous and lightweight (\~15KB gzipped). It won't slow down your website. ## Company Identification When a visitor loads your website, Snitcher attempts to identify their company: ```mermaid theme={null} flowchart LR A[Visitor loads page] --> B[Tracker captures IP] B --> C[IP Intelligence lookup] C --> D{Business IP?} D -->|Yes| E[Company identified] D -->|No| F[Anonymous visitor] E --> G[Enrich with firmographics] ``` ### How IP Intelligence Works Snitcher maintains a comprehensive database mapping IP addresses to companies. When we detect a visitor: 1. We look up their IP address in our database 2. If matched to a business, we return company information: * Company name and domain * Industry and employee count * Headquarters location * Social profiles (LinkedIn, etc.) 3. The visitor's session is associated with that company IP-based identification works at the **company level**, not the individual level. We can tell you "someone from Acme Corp visited your pricing page" but not specifically who—until they identify themselves. ### What About ISPs and VPNs? Not every IP can be identified: * **Consumer ISPs** (Comcast, Verizon, etc.) are shared by millions of households * **VPN services** mask the visitor's true location * **Mobile networks** use carrier IPs shared across users When we can't identify a company, the visitor appears as "Anonymous" with their approximate location based on IP geolocation. ## User Identification While IP intelligence reveals companies, **user identification** reveals specific people. This happens when visitors provide their email address: * Filling out a form (demo request, newsletter signup, content download) * Logging into your application * Clicking a tracked email link * Being identified via your code using `Snitcher.identify()` ```javascript theme={null} // When a user logs in Snitcher.identify("sarah@acme.com", { name: "Sarah Chen", role: "VP Marketing" }); ``` Once identified, the visitor's **entire session history**—including anonymous activity before identification—is linked to their profile. ### Cross-Session Identification Snitcher uses first-party cookies to maintain identity across sessions: 1. First visit: Anonymous visitor from Acme Corp 2. Second visit: Still anonymous, but same device ID 3. Form submission: Visitor identified as [sarah@acme.com](mailto:sarah@acme.com) 4. **All three sessions are now linked** to Sarah This means you see the complete buyer journey, from first touch to conversion. ## Data Flow to Your Tools Once collected, Snitcher data flows to your sales and marketing stack: ```mermaid theme={null} flowchart TB A[Website Visitor] --> B[Snitcher Tracker] B --> C[Snitcher Platform] C --> D[Dashboard] C --> E[Slack Alerts] C --> F[CRM Sync] C --> G[REST API] C --> H[Webhooks] ``` * **Dashboard**: View identified companies, sessions, and user activity * **Slack Alerts**: Get notified when target accounts visit key pages * **CRM Sync**: Push companies and contacts to Salesforce, HubSpot, etc. * **REST API**: Query data programmatically * **Webhooks**: Trigger workflows in external systems ## FAQ Snitcher uses IP intelligence to match visitor IP addresses to companies. We maintain a proprietary database of business IP ranges, updated continuously. When a visitor comes from a known business IP, we identify the company and enrich it with firmographic data. When users identify themselves on your website (submit a form, log in, etc.), Snitcher captures their email address and associates it with their browser session. This often happens automatically via form tracking, or you can call `Snitcher.identify()` manually. Snitcher handles profile merging automatically—if the same person visits from multiple devices, we unify their activity once they identify on each device. Yes. The tracker automatically detects client-side navigation (History API, hash changes) and tracks pageviews without additional configuration. Snitcher uses only first-party data and does not rely on third-party cookies. For GDPR compliance, you should: * Disclose Snitcher in your privacy policy * Integrate with your cookie consent manager (we support all major CMPs) * Use the `waitForConsent` configuration option See our [Cookie Consent guide](/product/tracker/cookie-consent) for details. Accuracy depends on the visitor's network: * **Office networks**: Very high accuracy—most businesses have dedicated IP ranges * **Corporate VPN**: High accuracy when traffic routes through company infrastructure * **Residential networks**: Company identification is limited, but [user identification](/product/identity-layer) fills this gap when visitors provide their email * **Mobile networks**: Company identification is limited—consider using [email link tracking](/product/tracker/identify-email-recipients) to identify these visitors No. The tracker loads asynchronously and is highly optimized (\~15KB gzipped). It has no impact on your Core Web Vitals or page load time. ## Next Steps Get started in minutes Deep dive into user identification # Snitcher Identity Layer Source: https://docs.snitcher.com/product/identity-layer The Identity Layer connects anonymous website visitors to known users by linking email addresses to browsing sessions across devices. **The Snitcher Identity Layer connects anonymous website visitors to known users by linking their email address to all past and future browsing sessions.** When a visitor provides their email (through a form, login, or email link click), Snitcher retroactively associates their previous anonymous sessions with that identity—giving you complete visibility into the buyer journey from first touch to conversion. ## Why Identity Matters Company-level identification tells you "someone from Acme Corp visited pricing." User-level identification tells you "Sarah Chen, VP Marketing at Acme Corp, visited pricing for the third time this week." Benefits of identified traffic: * **100% accurate**: No guessing—you know exactly who visited * **Privacy-friendly**: Users opted in by providing their email * **Perfect match rate**: Identified users stay identified across sessions * **Person-level detail**: See individual behavior, not just company aggregates Snitcher does not use third-party cookies or any third-party data in our Identity Layer. All identification comes from first-party interactions on your website. ## How Users Get Identified Snitcher captures user identity through several methods: ### 1. Automatic Form Tracking When enabled, Snitcher automatically detects form submissions containing email addresses. This includes: * Demo request forms * Newsletter signups * Gated content downloads * Contact forms * Webinar registrations No code changes required—Snitcher observes the form and extracts the email automatically. ### 2. Manual Identification via `identify()` For logins, signups, and non-standard flows, call `Snitcher.identify()`: ```javascript theme={null} // After user logs in Snitcher.identify("sarah@acme.com", { name: "Sarah Chen", title: "VP Marketing", company: "Acme Corp" }); ``` Call `identify()` whenever a user: * Signs up for your product * Logs in * Provides their email in a form you control * Completes onboarding ### 3. OAuth and SSO Logins For Google Sign-In, GitHub OAuth, SSO, and similar flows, you'll need to call `identify()` manually after successful authentication: ```javascript theme={null} // After OAuth callback async function handleOAuthSuccess(user) { // Identify to Snitcher Snitcher.identify(user.email, { name: user.name, auth_provider: "google" }); } ``` Install the tracker on your logged-in application pages and call `identify()` on every page load for authenticated users. This ensures sessions are always linked to the correct user. ### 4. Email Link Tracking When you send outbound emails, you can embed identification parameters that reveal who clicked through. Snitcher supports both plain email and base64-encoded formats: ``` # Plain email https://yoursite.com/pricing?sn_email=sarah@acme.com # Base64 encoded (recommended for privacy) https://yoursite.com/pricing?sn_eid=c2FyYWhAYWNtZS5jb20= ``` When the recipient clicks, Snitcher captures the email and identifies them automatically. This works with: * Sales outreach emails (Outreach, Salesloft, Apollo) * Marketing campaigns (HubSpot, Mailchimp, Marketo) * Transactional emails You can also pass additional traits via URL parameters like `sn_trait_first_name` and `sn_trait_company`. See the complete guide with platform-specific setup instructions for HubSpot, Apollo, Salesloft, and more. Only use email link tracking for emails you send directly. Don't expose email addresses in public links. ## Cross-Session Identity Persistence Once a user is identified, their identity persists across sessions (as long as cookies aren't cleared): | Session | Status | Activity | | ------- | -------------- | --------------------------------------------------------------- | | Week 1 | Anonymous | Visited blog, read 3 articles | | Week 2 | Anonymous | Returned, viewed pricing | | Week 3 | **Identified** | Filled out demo form as [sarah@acme.com](mailto:sarah@acme.com) | | Week 4 | Identified | Returned, viewed case studies | After identification in Week 3, **all four sessions** are linked to Sarah's profile in Snitcher. ## Profile Merging Snitcher automatically handles complex scenarios: ### Same Person, Multiple Devices When Sarah visits from her laptop and phone, she creates two device IDs. Once she identifies on both devices (e.g., logs in), Snitcher merges the activity: ``` Laptop sessions → sarah@acme.com Phone sessions → sarah@acme.com ``` ### Company + User Linking If Sarah visits from Acme Corp's office, we identify both: * **Company**: Acme Corp (from IP intelligence) * **User**: [sarah@acme.com](mailto:sarah@acme.com) (from identification) The session shows both, giving you company context and individual detail. ## Improving Your Identification Rate Want more identified traffic? Try these strategies: When users log in to your product, call `identify()`. This links their in-app behavior with website visits, giving you a complete picture of the customer journey. Require email for high-value content: ebooks, webinars, industry reports. Use progressive profiling to collect more data over time. Add tracking parameters to outbound emails. When prospects click through, you'll know exactly who they are—no form required. See the [complete setup guide](/product/tracker/identify-email-recipients) for HubSpot, Apollo, Salesloft, and more. Connect Snitcher with Intercom, Drift, or other chat tools. When visitors provide their email in chat, identify them in Snitcher. Host valuable webinars and capture emails at registration. Install Snitcher wherever registrations happen. ## Privacy Considerations The Identity Layer is built on first-party data and user consent: * **No third-party cookies**: All data comes from your website * **User-initiated**: Identification only happens when users provide their email * **Transparent**: Users know they're submitting a form or logging in * **GDPR-compatible**: Works with consent management when configured If you use cookie consent: ```javascript theme={null} // Only identify after consent if (hasMarketingConsent()) { Snitcher.identify(user.email, { name: user.name }); } ``` ## Next Steps Implementation guide for `identify()` Track clicks from outbound emails GDPR-compliant tracking setup # Apollo Source: https://docs.snitcher.com/product/integrations/apollo Sync identified contacts to Apollo.io for sales engagement and enrichment. Connect Snitcher to Apollo.io to add identified contacts to your sales intelligence platform. ## Features * **Add contacts to Apollo** from Snitcher * **Sync website engagement** data * **Trigger sequences** based on visits * **Lead prioritization** with engagement signals ## Setup 1. Go to **Settings** → **Integrations** → **Apollo** 2. Enter your Apollo API token 3. Click **Connect** ### Getting Your API Token 1. Log in to [Apollo.io](https://app.apollo.io) 2. Go to **Settings** → **Integrations** → **API** 3. Generate or copy your API key 4. Paste into Snitcher ## Usage ### Manual Push 1. View a company in Snitcher 2. Click on a revealed contact 3. Select **Add to Apollo** 4. Contact is synced to Apollo ### Data Synced | Snitcher Field | Apollo Field | | -------------- | ------------ | | Email | Email | | First Name | First Name | | Last Name | Last Name | | Company | Account | | Position | Title | | LinkedIn | LinkedIn URL | ## Troubleshooting Verify your Apollo API key is valid and has the necessary permissions. Check that the contact has a valid email address. Apollo requires email for contact creation. # Attio Source: https://docs.snitcher.com/product/integrations/attio Sync identified companies to Attio CRM. Connect Snitcher to Attio to automatically sync identified companies to your modern CRM. ## Features * **Company sync** to Attio * **Contact association** * **Custom attribute mapping** * **Two-way field mapping** - import any Attio attribute into a Snitcher custom field * **OAuth authentication** ## Setup 1. Go to **Settings** → **Integrations** → **Attio** 2. Click **Connect Attio** 3. Authorize Snitcher in Attio 4. Configure your sync settings ## Data Mapping | Snitcher Field | Attio Attribute | | -------------- | --------------- | | Company Name | Name | | Domain | Domain | | Industry | Industry | | Employee Count | Team size | | Location | Location | ## Import fields from Attio Field mapping is two-way. Alongside pushing Snitcher data into Attio, you can pull **any Attio attribute into a Snitcher custom field** on the company. Snitcher detects the attribute's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **Attio**, choose the Attio attributes to import, and either create a new custom field from each or link it to an existing one. ## Troubleshooting Verify the integration is connected and check your sync settings. # Close Integration Source: https://docs.snitcher.com/product/integrations/close Connect Snitcher to Close CRM to automatically sync identified companies as Leads, reveal contacts, and import Opportunities — with real-time two-way sync. **Connect Snitcher to Close to automatically create and enrich Leads when visitors are identified on your website.** Snitcher syncs in real-time in both directions, maps fields to any Close field (including custom fields), reveals contacts directly onto the right Lead, and imports your Opportunities for pipeline visibility. The Close integration is currently in **beta**. Want early access? [Contact support](https://help.snitcher.com) and we'll enable it for your workspace. ## How Snitcher maps to Close In Close, a **Lead represents the company** — contacts and opportunities live underneath it. Snitcher follows that model: | Snitcher | Close | | -------- | --------------------- | | Company | Lead | | Contact | Contact (on the Lead) | | Deal | Opportunity | Snitcher matches companies to existing Leads by **website domain**, so connecting to an existing Close organization enriches your current Leads instead of creating duplicates. ## Features * **Real-time two-way sync** — changes flow through securely signed webhooks, in both directions * **Auto-create Leads** when new companies are identified * **Auto-create Contacts** with revealed contact information, attached to the right Lead * **Custom field mapping** — map Snitcher data to any Close Lead field, including your custom fields * **Opportunity import** — see deal stage, value, and owner alongside visitor activity in Snitcher * **Deal segments** — automatic Open Deals and Lost Deals segments for retargeting and win-back * **Self-healing sync** — if Close pauses webhook delivery, Snitcher reactivates it and backfills missed changes automatically ## Setup 1. Go to **Settings** → **Integrations** → **Close** 2. Click **Connect Close** 3. Authorize Snitcher in the Close OAuth screen (select your Close organization) 4. Configure your sync settings Snitcher automatically creates its enrichment fields in Close during setup — no manual field creation needed. ## Data Mapping ### Default field mapping | Snitcher Field | Close Field | | -------------- | -------------------------------------- | | Company Name | Lead name | | Website | Lead URL (used for duplicate matching) | | Description | Description | | Lead Status | Lead status (read into Snitcher) | You can remap or extend these under **Settings** → **Integrations** → **Close**, including mapping to your own Close custom fields. Close custom fields are tracked by their internal ID, so renaming a field in Close never breaks the mapping. ### Snitcher enrichment fields During setup, Snitcher creates these custom fields on your Close Leads: | Field | Type | | --------------------------- | ------ | | Snitcher Total sessions | Number | | Snitcher Total page views | Number | | Snitcher Total time on site | Number | | Snitcher Segments | Text | | Snitcher Tags | Text | | Snitcher First visit date | Date | | Snitcher Last visit date | Date | | Snitcher Source | Text | These keep every Lead's engagement data fresh as visitors return to your site — ideal for Close Smart Views like "engaged this week." ### Opportunities Snitcher imports Opportunities from Close (read-only) so you can see pipeline context next to visitor activity: * Value, currency, and status/pipeline stage * Owner * Created and won dates Snitcher never creates or modifies Opportunities in Close. ## Contact Reveal When you reveal a contact in Snitcher and send it to Close, Snitcher: 1. Checks whether a contact with that email already exists in your Close organization 2. Creates the contact **on the matching Lead** with name, title, email, and phone 3. Updates the existing contact instead if one is found on the same Lead If the email already belongs to a contact on a *different* Lead, Snitcher reports it rather than moving the contact. ## Troubleshooting * Check that your segment filters aren't too restrictive * Verify the integration shows as "Connected" in settings * Companies need an identified website domain to be matched or created in Close Snitcher matches on the Lead URL field to prevent duplicates. If duplicates appear: * Make sure your existing Leads have their URL field filled in * Merge duplicates in Close directly — Snitcher follows Lead merges automatically Creating custom fields requires a Close role with organization management permission. Reconnect with an admin account, then use **Reinstall** on the integration page. Close can pause webhook delivery after extended downtime on either side. Snitcher detects this and recovers automatically within about 30 minutes, including changes made while delivery was paused. # Microsoft Dynamics Source: https://docs.snitcher.com/product/integrations/dynamics Sync identified companies to Microsoft Dynamics 365 as Accounts and Contacts. Connect Snitcher to Microsoft Dynamics 365 to automatically create Accounts and Contacts when visitors are identified on your website. ## Features * **Account and Contact sync** * **Custom field mapping** * **Two-way field mapping** - import any Dynamics field into a Snitcher custom field * **Activity tracking** * **Workflow integration** * **30-minute sync cycle** ## Setup 1. Go to **Settings** → **Integrations** → **Microsoft Dynamics** 2. Click **Connect Dynamics** 3. Sign in with your Microsoft account 4. Select your Dynamics environment 5. Configure field mappings ## Configuration Options ### Entity Mapping | Snitcher Data | Dynamics Entity | | ------------- | --------------- | | Company | Account | | Contact | Contact | | Activity | Activity | ### Field Mapping | Snitcher Field | Dynamics Field | | -------------- | ------------------- | | Company Name | Account Name | | Domain | Website | | Industry | Industry | | Employee Count | Number of Employees | | Revenue | Annual Revenue | | Location | Address | ### Import fields from Dynamics Field mapping is two-way. Alongside pushing Snitcher data into Dynamics, you can pull **any Dynamics field into a Snitcher custom field** on the company. Snitcher detects the field's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **Microsoft Dynamics**, choose the Dynamics fields to import, and either create a new custom field from each or link it to an existing one. ## Troubleshooting Ensure your Dynamics user has the necessary security roles to create and update records. Check that required fields are mapped. Dynamics may require specific fields for record creation. # Google Analytics 4 Source: https://docs.snitcher.com/product/integrations/google-analytics Enrich your GA4 data with company information using custom dimensions. Connect Snitcher to Google Analytics 4 to add company data as custom dimensions, enabling B2B analytics and audience segmentation. ## Features * **Custom dimensions** for company data (name, industry, size, location) * **Server-side enrichment** via Measurement Protocol * **Multiple GA4 properties** support * **Selective dimension mapping** - choose which data to sync ## Setup 1. Go to **Settings** → **Integrations** → **Google Analytics** 2. Click **Connect Google Analytics** 3. Authorize with your Google account 4. Select your GA4 property and data stream 5. Choose which dimensions to create ## Available Dimensions ### Basic Info (Default) | Dimension | Description | | ------------------------- | ----------------------- | | Snitcher Company Name | Identified company name | | Snitcher Company Domain | Company website domain | | Snitcher Company Industry | Industry classification | | Snitcher Company Size | Employee count range | ### Location | Dimension | Description | | ------------------------ | ----------------------------- | | Snitcher Company City | City where company is located | | Snitcher Company Region | State/region | | Snitcher Company Country | Country | | Snitcher Company Postal | Postal/ZIP code | ### Financial | Dimension | Description | | ------------------------ | ------------------------ | | Snitcher Company Revenue | Estimated annual revenue | | Snitcher Company Funding | Total funding raised | | Snitcher Company Founded | Year founded | ### Snitcher-Specific | Dimension | Description | | ----------------- | ------------------------------- | | Snitcher Segments | Segments the company belongs to | | Snitcher Tags | Tags assigned to the company | GA4 allows up to 25 user-scoped custom dimensions. Choose the dimensions most relevant to your analysis. ## How It Works 1. Visitor arrives on your website 2. Snitcher identifies the company 3. Company data is sent to GA4 via Measurement Protocol 4. Data appears as user properties in your reports ## Using the Data ### Custom Reports Create reports filtered by company attributes: * Sessions by Company Industry * Conversions by Company Size * Engagement by Company Country ### Audiences Build GA4 audiences based on company data: * Enterprise visitors (500+ employees) * Technology industry visitors * Companies in specific regions ### Looker Studio Connect GA4 to Looker Studio for B2B dashboards combining traffic data with company insights. ## Troubleshooting * Custom dimensions can take 24-48 hours to populate in reports * Verify the integration shows as connected * Check that you have traffic from identified companies GA4 limits user-scoped dimensions to 25. Remove unused dimensions in GA4 Admin before adding new ones. You need Admin or Editor access to the GA4 property to create custom dimensions. Ask your GA4 admin to grant access. # HubSpot Integration Source: https://docs.snitcher.com/product/integrations/hubspot Connect Snitcher to HubSpot CRM to automatically sync identified companies and contacts with real-time webhooks and custom field mapping. **Connect Snitcher to HubSpot to automatically create Companies and Contacts when visitors are identified on your website.** Snitcher syncs in real-time via webhooks, maps fields to any HubSpot property, and tracks pipeline attribution to measure sourced and influenced revenue. ## Features * **Real-time sync** via webhooks - no delays * **Auto-create Companies** when new organizations are identified * **Auto-create Contacts** with revealed contact information * **Two-way field mapping** - map Snitcher data to any HubSpot property, and import any HubSpot property into Snitcher * **Timeline activities** - log website visits as activities * **Deal pipeline tracking** - measure sourced and influenced revenue ## Setup 1. Go to **Settings** → **Integrations** → **HubSpot** 2. Click **Connect HubSpot** 3. Authorize Snitcher in the HubSpot OAuth popup 4. Configure your sync settings ## Configuration Options ### Company Sync Choose when to create or update companies in HubSpot: | Option | Description | | ---------------------------- | ---------------------------------------------- | | **All identified companies** | Sync every company Snitcher identifies | | **Segment-based** | Only sync companies matching specific segments | | **Manual only** | Don't auto-sync, push manually from Snitcher | ### Contact Sync Configure how contacts are synced: | Option | Description | | ------------------------ | ------------------------------------------- | | **Auto-create** | Create contacts when emails are revealed | | **Associate to Company** | Link contacts to their company record | | **Update existing** | Enrich existing contacts with Snitcher data | ### Field Mapping Map Snitcher fields to HubSpot properties: | Snitcher Field | Default HubSpot Property | | -------------- | ------------------------ | | Company Name | Company name | | Domain | Company domain | | Industry | Industry | | Employee Count | Number of employees | | Annual Revenue | Annual revenue | | LinkedIn URL | LinkedIn company page | | Location | City, State, Country | Create custom HubSpot properties to store additional Snitcher data like segments, tags, or first seen date. ### Import fields from HubSpot Field mapping is two-way. Alongside pushing Snitcher data into HubSpot, you can pull **any HubSpot property into a Snitcher custom field** on the company. Snitcher detects the field's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **HubSpot**, choose the HubSpot fields to import, and either create a new custom field from each or link it to an existing one. ## Pipeline Attribution Track how Snitcher contributes to your pipeline: * **Sourced** - Deals where Snitcher identified the company before any CRM activity * **Discovered** - Companies found by Snitcher not previously in your CRM * **Influenced** - Deals where the company visited your site during the sales cycle * **Engaged** - Companies showing repeat engagement on your website ## Troubleshooting * Check that your segment filters aren't too restrictive * Verify the integration shows as "Connected" in settings * Ensure you have the required HubSpot permissions Snitcher matches on domain to prevent duplicates. If duplicates exist: * Check for companies without domains in HubSpot * Merge duplicates in HubSpot directly Reconnect the integration to refresh permissions. Go to Settings → Integrations → HubSpot and click **Reconnect**. # Lemlist Source: https://docs.snitcher.com/product/integrations/lemlist Add identified contacts to Lemlist campaigns for automated outreach. Connect Snitcher to Lemlist to add identified contacts directly to your cold email campaigns. ## Features * **Add contacts to campaigns** with one click * **Personalize with company data** (name, industry, size) * **Trigger based on visits** via automations * **Campaign selection** - choose which campaign to add contacts to ## Setup 1. Go to **Settings** → **Integrations** → **Lemlist** 2. Enter your Lemlist API token 3. Click **Connect** ### Getting Your API Token 1. Log in to [Lemlist](https://app.lemlist.com) 2. Go to **Settings** → **Integrations** 3. Find your API key or generate a new one 4. Copy and paste into Snitcher ## Usage ### Manual Push 1. View a company in Snitcher 2. Click on a revealed contact 3. Select **Add to Lemlist** 4. Choose the campaign 5. Contact is added to the sequence ### Automated Push Use Automations to automatically add contacts: 1. Go to **Automations** 2. Create a new automation 3. Trigger: "Contact revealed" or "Company enters segment" 4. Action: **Add to Lemlist campaign** 5. Select the target campaign ## Data Passed to Lemlist | Field | Lemlist Variable | | ------------ | ----------------- | | Email | `{{email}}` | | First Name | `{{firstName}}` | | Last Name | `{{lastName}}` | | Company Name | `{{companyName}}` | | Position | `{{jobTitle}}` | Use Snitcher data in your Lemlist templates for better personalization. Reference company name, industry, or recent page views. ## Troubleshooting * Verify you copied the full token * Check that the token hasn't been revoked in Lemlist * Generate a new token if needed * Ensure the campaign is active (not paused) * Check for duplicate email detection in Lemlist * Verify the contact has a valid email address # Integrations Overview Source: https://docs.snitcher.com/product/integrations/overview Snitcher integrates with HubSpot, Salesforce, Pipedrive, Slack, Zapier, and 15+ other tools. Sync identified companies to your CRM and automate workflows. **Snitcher integrates with CRMs, communication tools, and automation platforms to help you act on identified website visitors.** Push companies and contacts to HubSpot, Salesforce, or Pipedrive in real-time. Get Slack alerts when target accounts visit. Build custom workflows with Zapier or webhooks. ## CRM Integrations Automatically sync identified companies and contacts to your CRM. Real-time sync via webhooks Leads, Contacts, and Accounts Organizations and activity tracking Accounts and Contacts sync Enterprise CRM integration Modern CRM sync Leads, Contacts, and Opportunities ## Communication Get notified when target accounts visit your website. Real-time alerts in your channels Notifications via webhook or OAuth ## Sales Engagement Add identified contacts to outreach campaigns. Cold email campaigns Sales intelligence platform AI-powered outreach ## Analytics Enrich your analytics with company data. Custom dimensions for company data ## Automation Build custom workflows and connect to any tool. Connect to 6,000+ apps Real-time data to any endpoint # Pipedrive Source: https://docs.snitcher.com/product/integrations/pipedrive Sync identified companies to Pipedrive as Organizations with real-time webhooks. Connect Snitcher to Pipedrive to automatically create Organizations and Persons when visitors are identified on your website. ## Features * **Real-time sync** via webhooks * **Auto-create Organizations** when companies are identified * **Auto-create Persons** with revealed contacts * **Activity notes** for website sessions * **Custom fields** for web activity data * **Two-way field mapping** - import any Pipedrive field into a Snitcher custom field * **Deal enrichment** with visitor insights ## Setup 1. Go to **Settings** → **Integrations** → **Pipedrive** 2. Click **Connect Pipedrive** 3. Authorize Snitcher in the Pipedrive OAuth popup 4. Configure your sync settings ## Configuration Options ### Organization Sync | Option | Description | | ------------------ | ---------------------------------------- | | **All companies** | Sync every identified company | | **Segment filter** | Only sync companies in specific segments | | **New only** | Only create, never update existing | ### Field Mapping | Snitcher Field | Pipedrive Field | | -------------- | ----------------- | | Company Name | Organization name | | Domain | Website | | Industry | Custom field | | Employee Count | Custom field | | Location | Address | | First Seen | Custom field | ### Import fields from Pipedrive Field mapping is two-way. Alongside pushing Snitcher data into Pipedrive, you can pull **any Pipedrive field into a Snitcher custom field** on the company. Snitcher detects the field's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **Pipedrive**, choose the Pipedrive fields to import, and either create a new custom field from each or link it to an existing one. ### Activity Tracking Optionally log website visits as Pipedrive activities: * Session start time * Pages viewed * Time on site * Referral source ## Troubleshooting * Check that webhooks are enabled in Pipedrive * Verify the integration is connected * Review segment filter settings Custom fields must be created in Pipedrive first, then mapped in Snitcher settings. # Salesforce Source: https://docs.snitcher.com/product/integrations/salesforce Sync identified companies to Salesforce as Leads, Contacts, or Accounts. Connect Snitcher to Salesforce to automatically create Leads, Contacts, and Accounts when visitors are identified on your website. ## Features * **Flexible object mapping** - create Leads, Contacts, or Accounts * **Custom field support** - map to standard and custom fields * **Two-way field mapping** - import any Salesforce field into a Snitcher custom field * **Deal/Opportunity tracking** - associate website activity with opportunities * **SOQL integration** - advanced querying for deduplication * **30-minute sync cycle** - regular polling for reliable data transfer ## Setup 1. Go to **Settings** → **Integrations** → **Salesforce** 2. Click **Connect Salesforce** 3. Log in to your Salesforce org and authorize Snitcher 4. Configure your object and field mappings ## Configuration Options ### Object Mapping Choose which Salesforce objects to create: | Option | Use Case | | --------------------- | ---------------------------------------- | | **Lead** | New prospects not yet qualified | | **Account + Contact** | Qualified companies with contact details | | **Account only** | Company-level tracking without contacts | ### Field Mapping Map Snitcher data to Salesforce fields: | Snitcher Field | Suggested Salesforce Field | | -------------- | --------------------------- | | Company Name | Account Name / Lead Company | | Domain | Website | | Industry | Industry | | Employee Count | Number of Employees | | Annual Revenue | Annual Revenue | | Location | Billing Address | | First Seen | Custom: First Website Visit | | Last Seen | Custom: Last Website Visit | Create custom Salesforce fields to capture Snitcher-specific data like segments, page views, and session count. ### Import fields from Salesforce Field mapping is two-way. Alongside pushing Snitcher data into Salesforce, you can pull **any Salesforce field into a Snitcher custom field** on the company. Snitcher detects the field's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **Salesforce**, choose the Salesforce fields to import, and either create a new custom field from each or link it to an existing one. ### Sync Settings | Setting | Description | | ---------------------- | ---------------------------------- | | **Sync frequency** | Every 30 minutes | | **Duplicate handling** | Match on domain/website field | | **Update existing** | Optionally update existing records | ## Deduplication Snitcher uses the Website/Domain field to match existing records: 1. Searches for existing Account/Lead with matching domain 2. If found, optionally updates the record 3. If not found, creates a new record ## Troubleshooting * Verify required fields are mapped (Salesforce may require specific fields) * Check your Salesforce validation rules * Ensure the connected user has create permissions * Enable the "match on domain" setting * Ensure existing records have the Website field populated * Consider using Salesforce duplicate rules Salesforce tokens expire periodically. Reconnect the integration if you see authentication errors. # Slack Source: https://docs.snitcher.com/product/integrations/slack Get real-time notifications in Slack when target accounts visit your website. Connect Snitcher to Slack to receive instant notifications when important companies visit your website. ## Features * **Real-time alerts** when companies are identified * **Multiple channels** - route different segments to different channels * **Rich messages** with company details and quick actions * **Customizable** - choose what data to include ## Setup 1. Go to **Settings** → **Integrations** → **Slack** 2. Click **Connect Slack** 3. Select your Slack workspace 4. Choose a default channel for notifications 5. Configure which companies trigger alerts via Automations ## Configuring Alerts Slack notifications are triggered through **Automations**: 1. Go to **Automations** in Snitcher 2. Create a new automation 3. Set your trigger (e.g., "New company identified") 4. Add a segment filter (e.g., "Enterprise companies") 5. Add the **Send to Slack** action 6. Choose the channel ### Example Automations | Automation | Trigger | Segment | Channel | | --------------- | ------------- | -------------- | ---------------- | | Hot leads | New company | ICP Match | #sales-alerts | | Target accounts | Company visit | Named Accounts | #target-accounts | | Enterprise | New company | 500+ employees | #enterprise | ## Message Content Slack notifications include: * Company name and logo * Industry and employee count * Location * Pages viewed * Session duration * Link to view in Snitcher ## Channel Management * **Default channel** - where notifications go if no automation specifies otherwise * **Multiple channels** - use automations to route to different channels * **Private channels** - invite the Snitcher bot first Create a dedicated channel like `#website-visitors` to keep notifications organized without cluttering your main channels. ## Troubleshooting * Verify the integration shows as "Connected" * Check that you have an active automation with Slack action * Ensure the segment filter isn't too restrictive * Verify the Snitcher bot is in the target channel Update the channel in your automation settings, or change the default channel in integration settings. For private channels, invite the Snitcher bot by typing `/invite @Snitcher` in the channel. # Smartlead Source: https://docs.snitcher.com/product/integrations/smartlead Add identified contacts to Smartlead campaigns for AI-powered outreach. Connect Snitcher to Smartlead to add identified contacts to your AI-powered email campaigns. ## Features * **Add contacts to campaigns** directly from Snitcher * **AI-powered outreach** sequences * **Campaign automation** based on website visits ## Setup 1. Go to **Settings** → **Integrations** → **Smartlead** 2. Enter your Smartlead API token 3. Click **Connect** ### Getting Your API Token 1. Log in to [Smartlead](https://app.smartlead.ai) 2. Navigate to **Settings** → **API** 3. Copy your API key 4. Paste into Snitcher ## Usage ### Manual Push 1. View a company in Snitcher 2. Click on a revealed contact 3. Select **Add to Smartlead** 4. Choose the campaign 5. Contact enters the sequence ## Troubleshooting Verify your API token is correct and hasn't expired. Ensure you have active campaigns in Smartlead. Only active campaigns appear in the selection. # Microsoft Teams Source: https://docs.snitcher.com/product/integrations/teams Get real-time notifications in Microsoft Teams when target accounts visit your website. Connect Snitcher to Microsoft Teams to receive instant notifications when important companies visit your website. ## Features * **Real-time alerts** when companies are identified * **Rich adaptive cards** with company details * **Flexible setup** - OAuth or webhook URL * **Channel selection** - choose where notifications go ## Setup Options ### Option 1: OAuth (Recommended) Full integration with channel selection: 1. Go to **Settings** → **Integrations** → **Microsoft Teams** 2. Click **Connect Microsoft Teams** 3. Sign in with your Microsoft account 4. Grant permissions to Snitcher 5. Select your team and channel ### Option 2: Incoming Webhook Simple setup using a webhook URL: 1. In Teams, go to your channel → **Manage channel** → **Connectors** 2. Add **Incoming Webhook** 3. Copy the webhook URL 4. In Snitcher, go to **Settings** → **Integrations** → **Microsoft Teams** 5. Paste the webhook URL ## Configuring Alerts Teams notifications are triggered through **Automations**: 1. Go to **Automations** in Snitcher 2. Create a new automation 3. Set your trigger (e.g., "New company identified") 4. Add a segment filter 5. Add the **Send to Microsoft Teams** action ## Message Content Teams notifications include: * Company name and logo * Industry and size * Location * Website activity summary * Direct link to view in Snitcher ## Troubleshooting * Verify the integration is connected * Check that you have an active automation * For webhooks, verify the URL is correct and the connector is active If using OAuth, ensure you have permission to post to the channel. Try refreshing the channel list. Webhook URLs can expire if the connector is removed. Regenerate the webhook in Teams if needed. # Webhooks Source: https://docs.snitcher.com/product/integrations/webhooks Send real-time data to any endpoint. Build custom integrations with webhooks. Use webhooks to send identified company data to any URL in real-time. Build custom integrations, power internal tools, or connect to any service. ## Features * **Real-time delivery** when events occur * **Custom endpoints** - send to any URL * **Flexible payload** with full company data * **Retry logic** for failed deliveries * **Secret authentication** for security * **Delivery logs** for debugging ## Setup 1. Go to **Settings** → **Integrations** → **Webhooks** 2. Click **Create Webhook** 3. Enter a name and your endpoint URL 4. Optionally add a secret for signature verification 5. Save and activate ## Webhook Events Configure which events trigger your webhook via **Automations**: | Event | Trigger | | ---------------- | ------------------------------------------------ | | New company | When a new company is first identified | | Company returns | When a known company visits again | | Session started | When any session begins | | Contact revealed | When a contact email or phone number is revealed | | Enters segment | When a company matches a segment | ## Payload Format ```json theme={null} { "event": "company.identified", "timestamp": "2024-01-15T10:30:00Z", "workspace": { "uuid": "ws_abc123", "name": "My Workspace" }, "company": { "uuid": "org_xyz789", "name": "Acme Inc", "domain": "acme.com", "industry": "Technology", "employee_range": "50-200", "location": { "city": "San Francisco", "region": "California", "country": "United States" } }, "session": { "uuid": "sess_123", "started_at": "2024-01-15T10:25:00Z", "pages_viewed": 3, "referrer": "google.com" } } ``` ### Contact Revealed Payload ```json theme={null} { "event": "contacts_revealed", "site_id": 12345, "subjects": [ { "first_name": "John", "last_name": "Doe", "email": "john@acme.com", "phone": "+1-555-123-4567", "headline": "VP of Sales at Acme Inc", "title": "VP of Sales", "linkedin_url": "https://linkedin.com/in/johndoe", "location": "San Francisco, CA", "company": { "name": "Acme Inc", "domain": "acme.com" } } ] } ``` The `phone` field is only included when a phone number has been revealed for the contact. ## Security ### Signature Verification If you add a secret, each webhook request includes a `Signature` header. The signature is an HMAC-SHA256 hash of the request body using your secret as the key, so it will be different for every request. ``` Signature: abc123... ``` Verify the signature by computing HMAC-SHA256 of the raw JSON request body with your secret and comparing it to the header value: ```javascript theme={null} const crypto = require('crypto'); function verifySignature(payload, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return signature === expected; } ``` ## Retry Logic Failed webhook deliveries are retried automatically: | Attempt | Delay | | ------- | ---------- | | 1 | Immediate | | 2 | 1 minute | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | After 5 failed attempts, the delivery is marked as failed and logged. ## Viewing Logs 1. Go to **Integrations** → **Webhooks** 2. Click on your webhook 3. Select **View Logs** Logs include: * Request payload * Response status code * Response body (if any) * Error messages * Timestamp ## Testing Send a test webhook to verify your endpoint: 1. Edit your webhook 2. Click **Send Test** 3. Choose an event type 4. Check your endpoint for the test payload ## Common Use Cases | Use Case | Description | | ------------------ | ------------------------------------------ | | Internal dashboard | Send data to your own analytics system | | Custom CRM | Integrate with CRMs not natively supported | | Slack bot | Build custom notifications | | Data warehouse | Stream to Snowflake, BigQuery, etc. | | Lead scoring | Trigger custom scoring workflows | ## Troubleshooting * Verify you have an automation configured to trigger the webhook * Check that the webhook is not archived * Review webhook logs for errors * Ensure you're using the raw request body (not parsed JSON) * Verify the secret matches exactly * Check for any proxy/middleware modifying the request Webhooks time out after 30 seconds. Ensure your endpoint responds quickly. For slow processing, respond immediately and process asynchronously. # Zapier Source: https://docs.snitcher.com/product/integrations/zapier Connect Snitcher to 6,000+ apps with Zapier. Automatically sync identified companies with your CRM, Slack, email tools, and more. Connect Snitcher to thousands of apps with Zapier. Automatically sync your identified website visitors with your CRM, marketing tools, and more. ## Setup ### 1. Get Your API Key 1. Log in to your [Snitcher account](https://app.snitcher.com) 2. Go to **Settings** → **API** 3. Generate a new API key 4. Copy the key for use in Zapier ### 2. Connect in Zapier 1. In Zapier, search for "Snitcher" 2. Click **Connect** 3. Paste your API key 4. Test the connection *** ## Available Triggers Triggers start your Zap when something happens in Snitcher. | Trigger | Description | | ------------------------------- | ------------------------------------------------------------------ | | **New Organisation** | Fires when Snitcher identifies a new company visiting your website | | **Organisation Enters Segment** | Fires when a company matches a specific segment | Use segments to filter which companies trigger your Zaps. For example, only trigger for companies with 100+ employees in the Technology industry. *** ## Available Actions Actions are things Zapier can do in Snitcher. | Action | Description | | -------------------------------- | ----------------------------------------------- | | **Add Tag to Organisation** | Add an existing tag to a company | | **Remove Tag from Organisation** | Remove a tag from a company | | **Create Tag** | Create a new tag in your workspace | | **Reveal Contact Email** | Reveal a contact's email address (uses credits) | *** ## Available Searches Searches let you find existing data in Snitcher to use in your Zap. | Search | Description | | ------------------------ | --------------------------------------------------- | | **Find Organisation** | Find a company by name or domain | | **Search Organisations** | Search companies with filters (segment, date range) | | **Find Contacts** | Find contacts for a company | *** ## Common Recipes ### Track Leads in Google Sheets Build a custom reporting spreadsheet with identified companies. 1. **Trigger:** Organisation Enters Segment ("Hot Leads") 2. **Action:** Google Sheets → Create Row 3. Map fields: Company Name, Domain, Industry, Employee Count, LinkedIn URL ### Add to Notion Database Create entries in your Notion sales pipeline. 1. **Trigger:** New Organisation 2. **Action:** Notion → Create Database Item 3. Map to your pipeline properties ### Create Outreach Sequence Automatically add contacts to Outreach.io sequences. 1. **Trigger:** Organisation Enters Segment 2. **Action:** Reveal Contact Email 3. **Action:** Outreach → Add to Sequence ### Add to Airtable Build a custom lead database in Airtable. 1. **Trigger:** New Organisation 2. **Action:** Airtable → Create Record 3. Map fields to your base columns ### Build LinkedIn Ads Audience Export companies to a CSV for LinkedIn matched audiences. 1. **Trigger:** Organisation Enters Segment 2. **Action:** Google Sheets → Create Row (company domains) 3. Upload sheet to LinkedIn Campaign Manager ### Alert on Discord Notify your team in Discord when target accounts visit. 1. **Trigger:** Organisation Enters Segment ("Target Accounts") 2. **Action:** Discord → Send Message *** ## Advanced Recipes ### Tag Leads from Your Target Account List Automatically tag companies in Snitcher if they appear in your Google Sheet of target accounts. 1. **Trigger:** New Organisation 2. **Search:** Google Sheets → Lookup Row (match by domain) 3. **Filter:** Only continue if row found 4. **Action:** Add Tag to Organisation ("Target Account") ### Enrich and Route by Company Size Route leads to different destinations based on company size. 1. **Trigger:** New Organisation 2. **Path A (Enterprise):** If Employee Count > 500 → Notion → Add to "Enterprise Pipeline" 3. **Path B (Mid-Market):** If Employee Count 50-500 → Google Sheets → Add Row 4. **Path C (SMB):** If Employee Count \< 50 → Mailchimp → Add to nurture list ### Sync Tags from Your CRM When a deal stage changes in your CRM, update the tag in Snitcher. 1. **Trigger:** Close CRM → Deal Updated 2. **Search:** Find Organisation (by domain) 3. **Action:** Remove Tag ("Prospect") 4. **Action:** Add Tag ("Customer") ### Auto-Reveal High-Value Contacts Automatically reveal contact emails for companies that match your ICP. 1. **Trigger:** Organisation Enters Segment ("ICP Match") 2. **Search:** Find Contacts (for organisation) 3. **Action:** Reveal Contact Email 4. **Action:** Lemlist → Add to Campaign ### Cross-Reference with Technographic Data Combine Snitcher with BuiltWith or similar to tag companies using specific technologies. 1. **Trigger:** New Organisation 2. **Action:** BuiltWith → Lookup Technologies (by domain) 3. **Filter:** If uses "Shopify" 4. **Action:** Add Tag to Organisation ("Shopify User") *** ## Data Available ### Organisation Fields | Field | Description | | --------------- | ----------------------- | | Organisation ID | Unique identifier | | Company Name | Identified company name | | Domain | Company website domain | | Industry | Company industry | | Employee Count | Company size range | | Annual Revenue | Estimated revenue | | First Seen | First visit timestamp | | Last Seen | Most recent visit | | Tags | Applied tags | | LinkedIn URL | Company LinkedIn page | ### Contact Fields | Field | Description | | ---------- | ---------------------------- | | Contact ID | Unique identifier | | Email | Contact email (after reveal) | | First Name | Contact first name | | Last Name | Contact last name | | Position | Job title | | Department | Department | | Seniority | Seniority level | *** ## Troubleshooting * Ensure your API key is valid and not expired * Check that you have access to the workspace * Try regenerating your API key in Snitcher settings * Verify your workspace has identified companies * Check that segment filters aren't too restrictive * Wait a few minutes for new data to sync * Confirm the Zap is turned on * Check that companies match your segment criteria * Review Zap history for errors *** ## Need Help? * [Snitcher Help Center](https://help.snitcher.com) * [Zapier Help](https://zapier.com/help) * Email: [support@snitcher.com](mailto:support@snitcher.com) # Zoho CRM Source: https://docs.snitcher.com/product/integrations/zoho Sync identified companies to Zoho CRM as Accounts and Contacts. Connect Snitcher to Zoho CRM to automatically create Accounts and Contacts when visitors are identified on your website. ## Features * **Real-time sync** via webhooks * **Account and Contact creation** * **Custom module support** * **Two-way field mapping** - import any Zoho field into a Snitcher custom field * **Web activity timeline** * **Lead scoring integration** ## Setup 1. Go to **Settings** → **Integrations** → **Zoho CRM** 2. Click **Connect Zoho** 3. Log in to your Zoho account and authorize Snitcher 4. Configure your sync settings ## Configuration Options ### Object Mapping | Snitcher Data | Zoho Object | | ------------- | ------------- | | Company | Account | | Contact | Contact | | Activity | Note/Activity | ### Field Mapping | Snitcher Field | Zoho Field | | -------------- | --------------- | | Company Name | Account Name | | Domain | Website | | Industry | Industry | | Employee Count | Employees | | Location | Billing Address | ### Import fields from Zoho Field mapping is two-way. Alongside pushing Snitcher data into Zoho, you can pull **any Zoho field into a Snitcher custom field** on the company. Snitcher detects the field's type automatically (text, number, date, checkbox, or list) and keeps the value up to date on each sync. To set it up, open **Settings** → **Integrations** → **Zoho CRM**, choose the Zoho fields to import, and either create a new custom field from each or link it to an existing one. ## Troubleshooting * Verify the integration is connected * Check field mapping for required Zoho fields * Ensure your Zoho user has create permissions Zoho tokens refresh automatically. If issues persist, reconnect the integration. # Welcome to Snitcher Source: https://docs.snitcher.com/product/introduction Official documentation for Snitcher's B2B visitor identification platform. Install the tracker, integrate with CRMs, and use our APIs to identify companies visiting your website. **Snitcher is a B2B visitor identification platform that reveals which companies visit your website.** Use this documentation to install the tracker, integrate with your CRM, and access our APIs to turn anonymous traffic into actionable leads. ## Getting Started Install the Snitcher tracker and start identifying companies visiting your website. Add the tracking script to your website in minutes. Supports all major platforms. Configure Snitcher for GDPR compliance with automatic CMP integration. ## Enhance Your Tracking Go beyond basic pageviews with custom events and user identification. Track button clicks, form submissions, and custom conversions. Link known users (logged-in visitors) to their company sessions. ## APIs & Integrations Use Snitcher data in your own applications and integrate with your marketing stack. Real-time company identification for website personalization. Access organisations, sessions, and contacts programmatically. ### Popular Integrations Sync company data to GA4 Use Data Layer variables Send data to Segment ## Resources Step-by-step guides, tutorials, and FAQs Company sizes, industries, and country codes # MCP Server Source: https://docs.snitcher.com/product/mcp/overview Connect Snitcher to Claude, ChatGPT, and other AI assistants with the Snitcher MCP server. Explore identified companies, manage segments, reveal contacts, and sync to your CRM in natural language. **The Snitcher MCP server gives AI assistants secure access to your Snitcher workspace.** Ask Claude, ChatGPT, or any MCP-compatible client to look up identified companies, dig into their website activity, build segments, reveal contacts, and push accounts to your CRM — all in plain language, using your own Snitcher permissions. [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard for connecting AI assistants to external tools and data. Snitcher hosts a remote MCP server, so there's nothing to install — you connect your AI client once over OAuth and start asking questions. ## Why use it * **No setup beyond a one-time connection.** Snitcher hosts the server. Add the URL to your AI client, sign in with your Snitcher account, and you're done. * **Work in natural language.** Skip the dashboard for everyday questions — "Which enterprise companies visited pricing this week?" — and let the assistant call the right tools. * **Your data, your permissions.** The server acts as *you*. It can only see and change what your Snitcher account can, scoped to the workspaces you have access to. * **Read and act in one place.** Go from "who visited" to "tag them, add them to a segment, and sync to HubSpot" without leaving the conversation. * **Safe by default.** Write actions are confirmed before they run, credit-consuming actions state the cost first, and destructive changes preview as a dry run. ## What you can do List and inspect identified companies, their website sessions, engagement, and top pages. Build and refine segments with filters, then list the companies that match. See contacts and buyer personas at a company, and reveal verified email addresses. Tag companies, update notes, set custom fields, and push accounts to your CRM, Slack, or Teams. ## Getting started ### Prerequisites * An active Snitcher account with access to at least one workspace. * An MCP-compatible AI client — for example [Claude](https://claude.ai) (web, desktop, or mobile), ChatGPT, Cursor, or any client that supports remote MCP servers. ### Connection URL Connect your client to the Snitcher MCP server at: ``` https://app.snitcher.com/mcp/snitcher ``` Authentication uses OAuth. When you add the connector, your client opens a Snitcher sign-in page in the browser; approve access and you're connected. No API keys to copy or rotate. 1. Open **Settings → Connectors** (in Claude on the web or desktop). 2. Choose **Add custom connector**. 3. Enter the URL `https://app.snitcher.com/mcp/snitcher` and save. 4. Click **Connect** and sign in to Snitcher when prompted to authorize access. The Snitcher tools are now available in your conversations. Try asking *"List my Snitcher workspaces."* 1. Open **Settings → Connectors** and choose to add a custom / remote MCP connector. 2. Enter the URL `https://app.snitcher.com/mcp/snitcher`. 3. Complete the Snitcher OAuth sign-in to authorize access. Availability of custom MCP connectors depends on your ChatGPT plan. Any client that supports remote (HTTP) MCP servers can connect. Point it at: ``` https://app.snitcher.com/mcp/snitcher ``` The server uses OAuth for authentication — your client will open a browser sign-in flow. Refer to your client's documentation for where to add a remote MCP server. Every tool operates on a **workspace**. Start a session by asking your assistant to list your workspaces — it will use the workspace identifier automatically for follow-up requests. ## Available tools The assistant decides which tools to call based on your request. Tools are grouped by what they do. **Read** tools only fetch data; **Write** tools change data and are confirmed before they run. ### Workspaces | Tool | Type | Description | | ----------------- | ---- | ---------------------------------------------------------------------------- | | `list-workspaces` | Read | List all workspaces you have access to. Usually the first call in a session. | | `get-workspace` | Read | Get a workspace's name, URL, plan status, usage limits, and tags. | ### Companies | Tool | Type | Description | | ----------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `list-organisations` | Read | List identified companies, filtered by segment, date range, or name search. Returns websites, industries, employee counts, and visit data. | | `get-organisation` | Read | Full details of a company: profile, tags, segments, technologies, CRM data, and visit stats. | | `get-organisation-engagement` | Read | Engagement over a time period: total sessions, timeline, unique visitors, time on site, first/last seen, and traffic sources. | | `get-organisation-insights` | Read | Key insights: unique visitors, pageview stats, most popular pages, and top traffic sources. | | `get-organisation-activities` | Read | Session-by-session activity: page views, duration, referrer, location, and visitor details (paginated). | | `get-organisation-people` | Read | Contacts at a company with titles, departments, seniority, LinkedIn, and email availability (paginated). | | `update-organisation-notes` | Write | Replace the notes on a company with new text. | ### Segments & filters | Tool | Type | Description | | --------------------- | ----- | ---------------------------------------------------------------------------------------------------- | | `list-segments` | Read | List segments with their filter definitions and matching company counts. | | `create-segment` | Write | Create a segment from filter groups and conditions. | | `update-segment` | Write | Replace a segment's filter definition. | | `list-filter-options` | Read | Discover valid values for a filter attribute (e.g. technologies, industries) when building segments. | ### Tags | Tool | Type | Description | | ------------------------------ | ----- | -------------------------------------------------- | | `list-tags` | Read | List all tags with their UUIDs, names, and colors. | | `create-tag` | Write | Create a new tag in a workspace. | | `add-tag-to-organisation` | Write | Add a tag to a company (by tag name or UUID). | | `remove-tag-from-organisation` | Write | Remove a tag from a company. | ### Contacts | Tool | Type | Description | | ---------------------- | ----- | -------------------------------------------------------------------------------------- | | `list-contacts` | Read | List people at a company with names, titles, departments, seniority, and email status. | | `reveal-contact-email` | Write | Reveal a contact's email address. **Consumes 1 email reveal credit.** | ### Buyer personas | Tool | Type | Description | | --------------------------------- | ----- | ------------------------------------------------------------------------------------------------- | | `list-buyer-personas` | Read | List buyer personas and their filter definitions (job titles, seniority, departments, countries). | | `get-organisation-buyer-personas` | Read | Show which buyer personas match a company, with the associated contacts. | | `create-persona` | Write | Create a buyer persona with filters. | | `update-persona` | Write | Update a persona's name and/or filters. | ### Sessions & usage | Tool | Type | Description | | ----------------------- | ---- | ---------------------------------------------------------------------------------------- | | `list-sessions` | Read | List visits for a company: pages viewed, duration, referrer, location, and visitor info. | | `list-tracking-scripts` | Read | List tracking scripts for a workspace with IDs, types, and active status. | | `get-usage` | Read | Current identification usage and credit balance against your plan limits. | ### Custom fields | Tool | Type | Description | | ------------------------------- | ----- | ----------------------------------------------------------------------------------- | | `list-custom-fields` | Read | List custom field definitions for companies in a workspace. | | `create-custom-field` | Write | Create a custom field definition on companies. Previews as a dry run by default. | | `update-custom-field` | Write | Update a custom field's name or description. Previews as a dry run by default. | | `delete-custom-field` | Write | Archive (soft-delete) a custom field. Reversible. Previews as a dry run by default. | | `set-organisation-custom-field` | Write | Set or clear a custom field value on a company. Previews as a dry run by default. | ### Integrations | Tool | Type | Description | | ---------------- | ----- | --------------------------------------------------------------------------------------------- | | `sync-to-crm` | Write | Push a company to a connected CRM (HubSpot, Salesforce, Pipedrive, Zoho, Dynamics, or Attio). | | `share-to-slack` | Write | Share a company to a Slack channel or user. | | `share-to-teams` | Write | Share a company to a Microsoft Teams channel. | ### Feedback | Tool | Type | Description | | ---------------------- | ----- | ------------------------------------------------------------------------- | | `capture-mcp-feedback` | Write | Send feedback about the MCP server — feature requests, bugs, or friction. | ## Workspace context resources Beyond tools, the server exposes **resources** — read-only snapshots an assistant can pull in for context without making a request. Most clients read these automatically when relevant. | Resource | Description | | --------------------------------------------------------- | --------------------------------------------------------- | | `snitcher://session/state` | Who you're authenticated as and current session metadata. | | `snitcher://workspaces/{workspace_uuid}` | Workspace name, URL, plan status, usage limits, and tags. | | `snitcher://workspaces/{workspace_uuid}/segments` | All segments with filters and matching counts. | | `snitcher://workspaces/{workspace_uuid}/tags` | All tags with UUIDs, names, and colors. | | `snitcher://workspaces/{workspace_uuid}/buyer-personas` | Buyer personas with their filter definitions. | | `snitcher://workspaces/{workspace_uuid}/tracking-scripts` | Tracking scripts with IDs, types, and status. | | `snitcher://workspaces/{workspace_uuid}/integrations` | Status of CRM, Slack, and Teams connections. | ## Example prompts **Explore visitors** * "List the companies that visited my site this week, biggest first." * "Show me everything you know about Acme Corp — industry, size, tags, and which pages they viewed." * "How engaged has Acme been over the last 30 days? Sessions, unique visitors, and traffic sources." * "What are the most popular pages among companies that visited yesterday?" **Find the right accounts** * "Create a segment for SaaS companies with 200+ employees in the US." * "Which companies match my 'Enterprise' segment right now?" * "What technology filter values can I use when building a segment?" **Reach the right people** * "Who are the decision-makers at Acme Corp?" * "Which of my buyer personas does Acme match, and who are the contacts?" * "Reveal the email for their VP of Marketing." *(uses 1 credit — the assistant will confirm first)* **Organize and act** * "Tag every company that visited the pricing page this week as 'Hot Lead'." * "Add a note to Acme: 'Reached out via LinkedIn on Monday.'" * "Push Acme Corp to HubSpot." * "Share Acme to the #sales Slack channel." **Account hygiene** * "How much of my monthly identification quota have I used?" * "List my custom fields, then set 'Account Owner' to 'Jordan' on Acme." ## Safety and confirmations The server is designed to be safe to use conversationally: * **Writes are confirmed.** The assistant explains any change and asks before calling a write tool. * **Bulk actions show their scope.** Before changing many companies at once, the assistant states how many will be affected. * **Credits are surfaced first.** Revealing an email consumes one credit, and the assistant states the cost and your balance before it runs. * **Destructive changes preview first.** Custom field changes default to a dry-run preview so you can confirm the exact effect before applying it. * **Permissions are inherited.** The server can only access the workspaces and data your Snitcher account can. It never elevates your access. ## Feedback and support The MCP server is actively evolving. If something is missing or doesn't work as expected, ask your assistant to send feedback with `capture-mcp-feedback`, or reach us through the [Help Center](https://help.snitcher.com/en/). Looking for direct, programmatic access instead? See the [REST API reference](/product/rest-api/introduction). # REST API Introduction Source: https://docs.snitcher.com/product/rest-api/introduction Access your Snitcher data programmatically using our REST API for integrations, automation, and custom workflows. The Snitcher REST API allows you to programmatically access and manage your Snitcher data. Use it to build custom integrations, automate workflows, or sync data with your other business tools. ## Authentication All API requests require authentication using a Personal Access Token (PAT) passed as a Bearer token. ### Generate an API Token 1. Go to your [Snitcher Dashboard](https://app.snitcher.com) 2. Navigate to **Settings > Account > API** 3. Click **Generate New Token** 4. Copy and securely store your token Treat your API token like a password. Never expose it in client-side code or public repositories. ### Making Authenticated Requests Include your token in the `Authorization` header: ```bash theme={null} curl -X GET 'https://api.snitcher.com/v1/workspaces' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Accept: application/json' ``` ## Base URL All API endpoints use this base URL: ``` https://api.snitcher.com/v1 ``` ## Rate Limits To ensure fair usage and platform stability, the REST API enforces the following rate limits: * **60 requests per minute** (per API token) When you exceed the rate limit, the API returns: ```json theme={null} { "message": "Too Many Attempts." } ``` **Status Code:** `429 Too Many Requests` Implement exponential backoff in your application to handle rate limiting gracefully. Start with a 1-second delay, then double it on each retry. Need higher rate limits? Contact support to discuss your requirements. ## Response Format All responses are JSON. Successful responses include the requested data: ```json theme={null} { "data": { // Response data } } ``` Error responses include a message: ```json theme={null} { "message": "Error description", "errors": { "field": ["Validation error"] } } ``` ## Common HTTP Status Codes | Status | Description | | ------ | ---------------------------------------- | | `200` | Success | | `201` | Created | | `400` | Bad Request - Invalid parameters | | `401` | Unauthorized - Invalid or missing token | | `403` | Forbidden - Insufficient permissions | | `404` | Not Found - Resource doesn't exist | | `422` | Validation Error - Check `errors` object | | `429` | Rate Limited - Too many requests | | `500` | Server Error - Contact support | ## Available Endpoints The REST API provides access to: List, create, and manage your workspaces Access identified companies and their data Retrieve visitor session data Access contacts and reveal emails or phone numbers List and manage segments Create and manage company tags ## Example: List Workspaces ```bash theme={null} curl -X GET 'https://api.snitcher.com/v1/workspaces' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Accept: application/json' ``` **Response:** ```json theme={null} { "data": [ { "uuid": "ws_abc123", "name": "My Website", "url": "https://example.com", "status": "active" } ] } ``` ## Example: Get Sessions with Events Sessions now include an `events` array containing all tracking events (pageviews, form submissions, custom events, clicks, and downloads). The `views` array is deprecated and only contains pageviews. ```bash theme={null} curl -X GET 'https://api.snitcher.com/v1/workspaces/{workspaceUuid}/organisations/{organisationUuid}/sessions?date=2025-03-01' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Accept: application/json' ``` **Response (abbreviated):** ```json theme={null} { "data": [ { "uuid": "...", "organisation_uuid": "...", "started_at": "2025-03-01T10:00:00+00:00", "ended_at": "2025-03-01T10:05:00+00:00", "events": [ { "event_type": "pageview", "url": "https://acme.com/pricing", "triggered_at": "2025-03-01T10:00:00+00:00", "time_on_page": 45 }, { "event_type": "form_submit", "url": "https://acme.com/contact", "triggered_at": "2025-03-01T10:02:00+00:00", "form_id": "contact-form", "form_name": "Contact Form", "fields": [ { "name": "email", "value": "j@acme.com" } ] }, { "event_type": "track", "url": "https://acme.com/pricing", "triggered_at": "2025-03-01T10:03:00+00:00", "name": "plan_selected", "properties": [ { "name": "plan", "value": "enterprise" } ] }, { "event_type": "click", "url": "https://acme.com/page", "triggered_at": "2025-03-01T10:04:00+00:00", "name": "CTA Button", "properties": [ { "name": "elementText", "value": "Get Started" } ] }, { "event_type": "download", "url": "https://acme.com/whitepaper.pdf", "triggered_at": "2025-03-01T10:05:00+00:00", "name": "$download", "properties": [ { "name": "url", "value": "https://acme.com/whitepaper.pdf" } ] } ], "views": [ { "url": "https://acme.com/pricing", "visited_at": "2025-03-01T10:00:00+00:00", "time_on_page": 45 } ] } ] } ``` Each event has a common `event_type`, `url`, and `triggered_at` field. Additional fields depend on the event type: | Event Type | Additional Fields | | ------------- | -------------------------------- | | `pageview` | `time_on_page` | | `form_submit` | `form_id`, `form_name`, `fields` | | `track` | `name`, `properties` | | `click` | `name`, `properties` | | `download` | `name`, `properties` | ## Example: Get Organisations ```bash theme={null} curl -X GET 'https://api.snitcher.com/v1/workspaces/{workspaceUuid}/organisations' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Accept: application/json' ``` ## Pagination List endpoints support pagination using query parameters: | Parameter | Type | Default | Description | | ---------- | ------- | ------- | ------------------------ | | `page` | integer | 1 | Page number | | `per_page` | integer | 25 | Items per page (max 100) | ```bash theme={null} curl -X GET 'https://api.snitcher.com/v1/workspaces/{workspaceUuid}/organisations?page=2&per_page=50' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Accept: application/json' ``` ## Filtering & Searching Many endpoints support filtering. Use the `POST` method with a JSON body for advanced searches: ```bash theme={null} curl -X POST 'https://api.snitcher.com/v1/workspaces/{workspaceUuid}/organisations' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -d '{ "filters": { "industry": "Software", "size": ["51-200 employees", "201-500 employees"] } }' ``` ## SDK & Libraries While we don't provide official SDK libraries, the REST API is straightforward to use with any HTTP client: * **JavaScript/Node.js**: `fetch`, `axios` * **Python**: `requests`, `httpx` * **PHP**: `Guzzle`, `cURL` * **Ruby**: `HTTParty`, `Faraday` ## Best Practices 1. **Store tokens securely**: Use environment variables, not hardcoded values 2. **Handle rate limits**: Implement retry logic with exponential backoff 3. **Cache responses**: Reduce API calls by caching data locally when appropriate 4. **Use pagination**: Don't try to fetch all data in one request 5. **Monitor usage**: Track your API usage to stay within limits ## Need Help? Browse the full API documentation Contact our support team # Fullstory Integration Source: https://docs.snitcher.com/product/spotter/example-fullstory Enrich Fullstory session recordings with company identification data. Enrich your Fullstory session recordings with company data from Snitcher, allowing you to filter and search sessions by company attributes. Fullstory requires specific naming conventions for custom properties. We use the `_str` suffix for string values as per their [property name requirements](https://help.fullstory.com/hc/en-us/articles/360020623234#Custom%20Property%20Name%20Requirements). ## Using getSpotterIdentification() (Recommended) Call `getSpotterIdentification()` after the tracker initializes: ```javascript theme={null} Snitcher.on('initialized', async function() { const identification = await Snitcher.getSpotterIdentification(); if (identification && identification.success) { const data = identification.data; // Set Fullstory user vars FS.setUserVars({ snitcher_company_name_str: data.name, snitcher_company_domain_str: data.website, snitcher_company_industry_str: data.industry, snitcher_company_size_str: data.size }); } }); ``` ## Using Callback (Legacy) Define `SpotterSettings` before the Snitcher script loads: ```html theme={null} ``` No API token is required. Make sure your domain is [authorised in the Spotter settings](/product/spotter/installation#setup) before getting started. ## Available Properties All string properties should use the `_str` suffix: | Fullstory Property | Snitcher Field | Description | | ------------------------------- | ------------------------- | ----------------- | | `snitcher_company_name_str` | `name` | Company name | | `snitcher_company_domain_str` | `website` / `domain` | Primary domain | | `snitcher_company_industry_str` | `industry` | Industry category | | `snitcher_company_size_str` | `size` / `employee_range` | Employee range | ## Using in Fullstory Once configured, you can: 1. **Search sessions** by company name or industry 2. **Create segments** for enterprise companies or specific industries 3. **Filter recordings** to focus on target accounts 4. **Build funnels** segmented by company size # Google Analytics 4 Integration Source: https://docs.snitcher.com/product/spotter/example-ga-4 Send company identification data to Google Analytics 4 for enhanced B2B analytics. Snitcher can automatically sync identified company data to Google Analytics 4, enabling you to build powerful reports, create audiences, and optimize your marketing based on company firmographics. ## Native Integration (Recommended) Snitcher now offers a **native Google Analytics 4 integration** that requires no code. Company data is automatically synced as GA4 user properties. ### Setup in Dashboard 1. Go to your [Snitcher Dashboard](https://app.snitcher.com) 2. Navigate to **Settings > Workspace > Integrations > Google Analytics** 3. Click **Connect Google Analytics** 4. Authorize Snitcher to access your GA4 property 5. Select your GA4 property and configure which company attributes to sync 6. Save your settings The native integration handles everything automatically - no GTM setup, no custom code, no maintenance. ### What Gets Synced The integration automatically sends these user properties to GA4: | User Property | Description | | --------------------------- | -------------------- | | `snitcher_company_name` | Company name | | `snitcher_company_domain` | Company domain | | `snitcher_company_industry` | Industry category | | `snitcher_company_size` | Employee count range | You can customize which attributes are synced and their property names in the dashboard. ### Creating Custom Dimensions in GA4 To use the synced data in reports, create custom dimensions: 1. Sign in to [Google Analytics](https://analytics.google.com/) 2. Navigate to **Admin > Custom definitions > Custom dimensions** 3. Click **Create custom dimension** 4. Configure: * **Dimension name**: e.g., "Company Name" * **Scope**: User * **User property**: e.g., `snitcher_company_name` 5. Click **Save** Repeat for each attribute you want to use in reports. ### Use Cases With company data in GA4, you can: * **Build B2B reports**: Analyze traffic and conversions by company size or industry * **Create audiences**: Target enterprise companies or specific industries in Google Ads * **Segment behavior**: Compare how different company types engage with your site * **Optimize campaigns**: Exclude competitors or low-value segments from ad spend *** ## Manual Integration (Advanced) If you need custom control over how data flows to GA4, you can use the Spotter callback method. The manual approach requires more maintenance and is only recommended for advanced use cases where the native integration doesn't meet your needs. ### Using Data Layer Variables Push company data to the dataLayer for use in Google Tag Manager: ```javascript theme={null} // Define the callback before Snitcher loads window.SpotterSettings = { callback: function(identification) { if (identification && identification.type !== "isp") { var company = identification.company; window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: "snitcher_identified", snitcher: { name: company.name, domain: company.domain, industry: company.industry, size: company.employee_range } }); } } }; ``` Then in GTM: 1. Create Data Layer Variables for each property 2. Create a trigger for the `snitcher_identified` event 3. Configure your GA4 tag to send user properties using those variables ### Using getSpotterIdentification() For more control, call the method directly after the tracker initializes: ```javascript theme={null} // Wait for tracker to initialize Snitcher.on('initialized', async function() { const identification = await Snitcher.getSpotterIdentification(); if (identification && identification.success) { gtag('set', 'user_properties', { company_name: identification.data.name, company_industry: identification.data.industry, company_size: identification.data.size }); } }); ``` *** ## Viewing Data in GA4 Once configured, company data appears in: * **Reports > User > User attributes**: See user property values * **Explore**: Create custom explorations with company dimensions * **Audiences**: Build audiences based on company attributes It may take 24-48 hours for new custom dimensions to appear in GA4 reports. # Segment Integration Source: https://docs.snitcher.com/product/spotter/example-segment Sync company identification data to Segment for use across your analytics stack. Sync Snitcher's company identification data to Segment.com, making it available across all your connected destinations. ## Using getSpotterIdentification() (Recommended) The cleanest approach is to call `getSpotterIdentification()` after the tracker initializes: ```javascript theme={null} // Wait for Snitcher to initialize Snitcher.on('initialized', async function() { const identification = await Snitcher.getSpotterIdentification(); if (identification && identification.success) { const data = identification.data; // Send to Segment as a track event analytics.track("Company Identified", { company_name: data.name, company_domain: data.website, company_industry: data.industry, company_size: data.size }); // Or set as user traits analytics.identify({ company: { id: data.uuid, name: data.name, industry: data.industry, employee_count: data.size } }); } }); ``` ## Using Callback (Legacy) If you prefer the callback approach, define `SpotterSettings` before the Snitcher script loads: ```html theme={null} ``` No API token is required. Make sure your domain is [authorised in the Spotter settings](/product/spotter/installation#setup) before getting started. ## What Data to Send We recommend tracking these company attributes: | Segment Property | Snitcher Field | Description | | ------------------ | -------------------------------------- | ----------------- | | `company_name` | `data.name` / `company.name` | Company name | | `company_domain` | `data.website` / `company.domain` | Primary domain | | `company_industry` | `data.industry` / `company.industry` | Industry category | | `company_size` | `data.size` / `company.employee_range` | Employee range | ## Use Cases Once company data flows to Segment, you can: * **Enrich CRM records** in Salesforce, HubSpot, etc. * **Personalize experiences** in tools like Intercom or Drift * **Build audiences** for advertising platforms * **Power analytics** in Amplitude, Mixpanel, or BigQuery # Google Tag Manager Integration Source: https://docs.snitcher.com/product/spotter/example-tag-manager Push company identification data to the dataLayer for use in GTM tags and triggers. Push Snitcher company data to the Google Tag Manager dataLayer, making it available for use in tags, triggers, and variables throughout your GTM container. ## Setup Overview 1. Configure the Spotter callback to push data to the dataLayer 2. Create Data Layer Variables in GTM 3. Use those variables in your tags ## Step 1: Push Data to dataLayer ### Using getSpotterIdentification() (Recommended) ```javascript theme={null} Snitcher.on('initialized', async function() { const identification = await Snitcher.getSpotterIdentification(); if (identification && identification.success) { const data = identification.data; window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'snitcher_identified', snitcher: { name: data.name, domain: data.website, industry: data.industry, size: data.size } }); } }); ``` ### Using Callback (Legacy) Define `SpotterSettings` before the Snitcher script loads: ```html theme={null} ``` No API token is required. Make sure your domain is [authorised in the Spotter settings](/product/spotter/installation#setup) before getting started. ## Step 2: Create Data Layer Variables in GTM 1. [Sign in to Google Tag Manager](https://tagmanager.google.com/) 2. Navigate to **Variables** → **User-Defined Variables** → **New** 3. Configure each variable: | Variable Name | Data Layer Variable Name | Version | | ----------------------- | ------------------------ | --------- | | SnitcherCompanyName | snitcher.name | Version 2 | | SnitcherCompanyDomain | snitcher.domain | Version 2 | | SnitcherCompanyIndustry | snitcher.industry | Version 2 | | SnitcherCompanySize | snitcher.size | Version 2 | For each variable: * Click **Variable Configuration** → **Data Layer Variable** * Enter the **Data Layer Variable Name** from the table * Set **Data Layer Version** to **Version 2** * Click **Save** ## Step 3: Create a Trigger (Optional) To fire tags when a company is identified: 1. Go to **Triggers** → **New** 2. Choose **Custom Event** 3. Set **Event name** to `snitcher_identified` 4. Save the trigger ## Using the Variables Once configured, use `{{"{{SnitcherCompanyName}}"}}`, `{{"{{SnitcherCompanyIndustry}}"}}`, etc. in any tag: ### Example: GA4 Event Create a GA4 Event tag with these event parameters: | Parameter Name | Value | | ----------------- | ----------------------------------- | | company\_name | `{{"{{SnitcherCompanyName}}"}}` | | company\_industry | `{{"{{SnitcherCompanyIndustry}}"}}` | | company\_size | `{{"{{SnitcherCompanySize}}"}}` | ### Example: LinkedIn Insight Tag Use company data to build retargeting audiences based on company attributes. ## Available Data | Variable | Description | | ------------------- | ----------------- | | `snitcher.name` | Company name | | `snitcher.domain` | Primary domain | | `snitcher.industry` | Industry category | | `snitcher.size` | Employee range | You can extend the callback to include additional fields as needed. See [Spotter API documentation](/product/spotter/installation) for the full response structure. # Getting Started with Spotter Source: https://docs.snitcher.com/product/spotter/installation Use Snitcher's Spotter API to identify companies visiting your website in real-time for personalization and targeting. The Spotter API lets you identify the company behind a website visitor in real-time, directly from JavaScript. Use it to personalize your website, show relevant content, or trigger custom workflows based on who's visiting. ## What is Spotter? Spotter is a client-side JavaScript API that: * **Identifies companies** visiting your website in real-time * **Returns rich company data** including industry, size, location, and contact info * **Works automatically** with the Snitcher tracker once your domains are authorised * **Integrates natively** with Google Analytics 4 Spotter is included with your Snitcher subscription. It uses the same identification data that powers your dashboard. ## Setup Before using Spotter, you need to authorise the domains that are allowed to make Spotter API requests. This prevents unauthorised websites from using your identification quota. 1. Go to your [Snitcher Dashboard](https://app.snitcher.com) 2. Navigate to **Settings > Integrations > Spotter** 3. Add the domains you want to authorise (e.g. `*.example.com`) 4. Click **Save** Use a wildcard prefix like `*.example.com` to authorise all subdomains at once, including the root domain itself. ## Access Identification Data Once your domains are authorised and the Snitcher tracker is installed, you can access identification data in two ways: #### Option 1: Using `getSpotterIdentification()` (Recommended) Call the method directly on the Snitcher object: ```javascript theme={null} // Get identification data const identification = await Snitcher.getSpotterIdentification(); if (identification && identification.success) { console.log("Company:", identification.data.name); console.log("Industry:", identification.data.industry); console.log("Size:", identification.data.size); } ``` #### Option 2: Using a Callback If you prefer a callback-based approach, define `window.SpotterSettings` before the tracker loads: ```html theme={null} ``` No token or API key is required. Spotter authenticates using the `Origin` header of your request, matched against your [authorised domains](#setup). ## Response Structure ### Successful Identification When a company is identified, you receive: ```javascript theme={null} { success: true, data: { uuid: "abc123", name: "Acme Corporation", website: "acme.com", email: "info@acme.com", phone: "+1-555-0100", industry: "Software", founded: 2010, size: "51-200 employees", logo: "https://...", address: { street: "Market Street", street_number: "123", postal_code: "94102", city: "San Francisco", state: "California", country: "United States", full_address: "123 Market Street, San Francisco, CA 94102", latitude: 37.7749, longitude: -122.4194 }, profiles: [ { name: "linkedin", handle: "acme-corp", url: "https://linkedin.com/company/acme-corp" }, { name: "twitter", handle: "acme", url: "https://twitter.com/acme" } ], tags: ["Enterprise", "Target Account"], segments: [ { uuid: "seg123", name: "High-Value Prospects" } ], icp_tier: "A", custom_fields: { account_owner: "Jane Smith", contract_value: 48000, is_target_account: true, renewal_date: "2026-11-01", product_interests: ["Analytics", "Enrichment"] } } } ``` The `custom_fields` object contains the custom fields your workspace has chosen to expose to Spotter, as a `key: value` map. The key is omitted when there are none to return. ### Callback Format (Legacy) If using the callback approach, you receive data in the legacy format: ```javascript theme={null} { type: "business", // "business" or "isp" domain: "acme.com", company: { name: "Acme Corporation", domain: "acme.com", industry: "Software", employee_range: "51-200 employees", founded_year: 2010, location: "San Francisco, United States", emails: ["info@acme.com"], phones: ["+1-555-0100"], geo: { /* location details */ }, profiles: { /* social profiles */ } } } ``` ### Unidentified Visitor When using the callback format, if the visitor can't be identified: ```javascript theme={null} { type: "isp" } ``` When using `getSpotterIdentification()`: ```javascript theme={null} { success: false, message: "No company identified" } ``` ## Common Use Cases ### Personalize Headlines ```javascript theme={null} const id = await Snitcher.getSpotterIdentification(); if (id?.success) { document.querySelector('h1').textContent = `Welcome, ${id.data.name}!`; } ``` ### Show Relevant Content by Industry ```javascript theme={null} const id = await Snitcher.getSpotterIdentification(); if (id?.success) { const industry = id.data.industry; if (industry.includes("Finance") || industry.includes("Banking")) { showCaseStudy('finance'); } else if (industry.includes("Software") || industry.includes("Technology")) { showCaseStudy('tech'); } } ``` ### Adjust Pricing Display ```javascript theme={null} const id = await Snitcher.getSpotterIdentification(); if (id?.success) { const size = id.data.size; // Show enterprise pricing for large companies if (size.includes("1000") || size.includes("5000") || size.includes("10,000")) { document.querySelector('.pricing-toggle').dataset.default = 'enterprise'; } } ``` ### Track High-Value Visitors ```javascript theme={null} const id = await Snitcher.getSpotterIdentification(); if (id?.success && isTargetAccount(id.data)) { Snitcher.track("Target Account Visit", { company_name: id.data.name, industry: id.data.industry }); // Notify sales team notifySalesTeam(id.data); } ``` ## Company Data Reference | Field | Type | Description | | --------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | string | Company name | | `website` | string | Primary domain | | `industry` | string | Industry category | | `size` | string | Employee range (e.g., "51-200 employees") | | `founded` | number | Year founded | | `email` | string | Primary contact email | | `phone` | string | Primary phone number | | `address` | object | Full location details | | `profiles` | array | Social media profiles | | `tags` | array | Your custom tags | | `segments` | array | Matching segments | | `icp_tier` | string \| null | ICP fit tier: one of `A+`, `A`, `B`, `C`, or `D`. `null` if the company hasn't been scored | | `custom_fields` | object | Map of the custom fields your workspace exposes to Spotter, keyed by field key, each value in its natural JSON type (string, number, boolean, array for multi-select, ISO-8601 string for dates). The key is omitted when there are none | See [Company Sizes](/reference/company-sizes) and [Company Industries](/reference/company-industries) for all possible values. ## Native Integrations Snitcher can automatically sync identification data to: Sync company data as GA4 user properties Push data to the dataLayer for GTM ## Best Practices 1. **Handle missing data gracefully**: Not all companies have complete profiles 2. **Don't block page load**: Identification is async; design for delayed data 3. **Cache is automatic**: Data is cached in sessionStorage to avoid repeated calls 4. **Respect privacy**: Don't use identification in ways that might concern visitors ## Troubleshooting * Make sure your domain is listed under **Settings > Integrations > Spotter** in the dashboard * If using subdomains, add a wildcard entry like `*.example.com` * Changes to authorised domains may take up to 10 minutes to take effect * Ensure the tracker is fully initialized before calling * Use `Snitcher.on('initialized', callback)` to wait for initialization * Check browser console for errors * Residential/consumer IPs don't identify to companies * VPN users may not be identified * Test from a business network or office * Ensure `SpotterSettings` is defined before the tracking script * Consider using `getSpotterIdentification()` instead # Automatic Tracking Source: https://docs.snitcher.com/product/tracker/automatic-tracking Enable form, click, and download tracking with zero code. Understand what each feature captures and how to use the data. Snitcher can automatically track common visitor actions without any code changes. Enable these features in **Settings → Tracker → Features**. ## Form Tracking **What it does:** Captures when visitors submit or abandon forms on your website. ### Events Captured | Event | When It Fires | | --------------- | ----------------------------------------------------------- | | `$form_submit` | Visitor submits any form | | `$form_abandon` | Visitor starts filling a form but leaves without submitting | ### Data Collected * Form ID or name * Form action URL * Field names (not values, for privacy) * Page URL where the form exists ### Why Enable It * **See which forms convert** - Identify high-performing lead capture forms * **Find form abandonment issues** - Discover forms that visitors start but don't complete * **Segment by form submissions** - Create segments like "Submitted contact form" or "Started but didn't submit" Form abandonment data is valuable for identifying UX issues. If many visitors start your pricing calculator but don't complete it, the form might be too long or confusing. *** ## Click Tracking **What it does:** Tracks clicks on links and buttons, plus enables declarative tracking with `data-track-event` attributes. ### What Gets Tracked * **All link clicks** - Internal and external navigation * **Button clicks** - Any ` ``` No JavaScript required. The click is automatically captured with your custom event name and properties. See [Declarative Click Tracking](/product/tracker/custom-events#declarative-click-tracking) for more examples. *** ## Download Tracking **What it does:** Captures when visitors download files from your website. ### File Types Tracked | Category | Extensions | | ------------- | --------------------------------------- | | Documents | `.pdf`, `.doc`, `.docx`, `.txt`, `.rtf` | | Spreadsheets | `.xls`, `.xlsx`, `.csv` | | Presentations | `.ppt`, `.pptx` | | Archives | `.zip`, `.rar`, `.7z`, `.tar`, `.gz` | | Other | Any link with `download` attribute | ### Data Collected * File name * File URL * File extension * Page URL where download occurred ### Why Enable It * **Identify high-intent visitors** - Visitors who download pricing sheets or case studies are often further along in their buying journey * **Measure content performance** - See which whitepapers, ebooks, or resources get downloaded most * **Segment by downloads** - Create segments like "Downloaded pricing PDF" for targeted follow-up Downloads often indicate buying intent. A visitor who downloads your ROI calculator or implementation guide is likely evaluating seriously. *** ## Where the Data Appears Once enabled, tracking data shows up in several places: ### Company Timeline Each company's timeline shows their tracked events: * Form submissions and abandonments * Click events * File downloads ### Session Details Drill into any session to see the full sequence of events, including automatic tracking data. ### Segments Create segments based on automatic tracking events: * "Submitted a form in the last 7 days" * "Downloaded any PDF" * "Clicked pricing page CTA" ### Automations Trigger automations based on events: * Send to Slack when someone downloads a case study * Add a tag when a form is submitted * Notify sales when high-intent actions occur *** ## Recommended Setup For most websites, we recommend enabling all three features: | Feature | Recommendation | Why | | ----------------- | -------------- | -------------------------------------------------------------------- | | Form Tracking | ✅ Enable | Essential for lead gen sites | | Click Tracking | ✅ Enable | Valuable for understanding navigation + enables declarative tracking | | Download Tracking | ✅ Enable | Great for identifying high-intent visitors | These features track actions, not personal data. Form tracking captures field names but not the values visitors enter. *** ## Going Further Once you're comfortable with automatic tracking, you can layer on custom events for business-specific actions: Track purchases, video views, and other custom actions Get the most out of your tracking setup # Best Practices Source: https://docs.snitcher.com/product/tracker/best-practices Get the most out of Snitcher with these proven strategies for tracking, identification, and data quality. Follow these best practices to maximize the value you get from Snitcher and ensure high-quality data for your sales and marketing teams. ## Driving More Identified Users The more visitors you identify, the more valuable your Snitcher data becomes. Here's how to increase your identification rate: ### Install on Your Application When users log in to your product, identify them to Snitcher: ```javascript theme={null} // After successful login Snitcher.identify(user.email, { name: user.name, plan: user.subscription?.plan, company: user.company }); ``` This links their in-app behavior with their website visits, giving you a complete picture of the customer journey. ### Gate Your Best Content Require email for high-value content: * **Ebooks and whitepapers**: Gate behind a download form * **Webinars**: Capture email at registration * **Product demos**: Interactive demos behind email capture * **Industry reports**: Exclusive data behind email gate Consider "progressive profiling"—ask for email first, then collect more data (company, role) on subsequent downloads. ### Use Email Link Tracking Add identification parameters to outbound emails: ``` https://yoursite.com/case-study?sn_email=prospect@company.com ``` When recipients click, they're automatically identified—no form required. ### Integrate with Chat Widgets If you use Intercom, Drift, or similar tools, identify users when they provide their email: ```javascript theme={null} // Intercom example Intercom('onUserEmail', function(email) { Snitcher.identify(email); }); // Drift example drift.on('emailCapture', function(data) { Snitcher.identify(data.email); }); ``` ### Capture Newsletter Signups Every email subscription is an opportunity to identify: ```javascript theme={null} form.addEventListener('submit', function(e) { const email = form.querySelector('[name="email"]').value; Snitcher.identify(email, { source: 'newsletter_signup' }); }); ``` ## Event Tracking Best Practices ### Use Consistent Naming Conventions Adopt a clear pattern for event names: ```javascript theme={null} // Good: [Object] [Action] format "Button Clicked" "Form Submitted" "Video Played" "Document Downloaded" "Trial Started" // Bad: Inconsistent patterns "click_button" "formSubmit" "user watched video" ``` ### Include Meaningful Properties Add context to every event: ```javascript theme={null} // Good: Rich context Snitcher.track("CTA Clicked", { button_text: "Start Free Trial", button_location: "pricing_page", plan_selected: "pro", page_url: window.location.href }); // Bad: No context Snitcher.track("CTA Clicked"); ``` ### Don't Include Dynamic Data in Event Names Keep event names consistent; use properties for variations: ```javascript theme={null} // Good: Consistent event name, dynamic property Snitcher.track("Feature Viewed", { feature_name: "Analytics" }); Snitcher.track("Feature Viewed", { feature_name: "Integrations" }); // Bad: Dynamic event names Snitcher.track("Analytics Feature Viewed"); Snitcher.track("Integrations Feature Viewed"); ``` ### Track High-Intent Actions Focus on actions that indicate buying intent: | Action | Why It Matters | | ------------------- | -------------------- | | Pricing page visit | Evaluating cost | | Comparison page | Active evaluation | | Integration docs | Technical fit check | | Contact sales click | Ready to talk | | Demo request | High intent | | Case study view | Social proof seeking | ## Automatic vs Custom Event Tracking ### Start with Automatic Tracking (Recommended) Enable all three tracking features in **Settings → Tracker → Features**: | Feature | What You Get | | --------------------- | ------------------------------------------------------------ | | **Form Tracking** | All form submissions and abandonments captured automatically | | **Click Tracking** | Link/button clicks + `data-track-event` declarative tracking | | **Download Tracking** | PDF, Word, Excel, and other file downloads | Most users should enable all three features. This gives you comprehensive tracking with zero code changes. ### When to Add Custom Events Layer custom events on top of automatic tracking for business-specific actions: | Automatic Tracking Handles | Add Custom Events For | | -------------------------- | ---------------------------------------- | | Generic form submissions | Demo requests with company size/industry | | All link clicks | Pricing plan selection | | File downloads | Video engagement (play, pause, complete) | | | In-app feature usage | | | Purchases and conversions | ### Example: Enriching Automatic Tracking Automatic tracking captures that a form was submitted. Custom events add business context: ```javascript theme={null} // Automatic tracking already captures $form_submit // Add a custom event with business-specific data form.addEventListener('submit', function() { Snitcher.track("Demo Request Submitted", { company_size: form.querySelector('[name="size"]').value, industry: form.querySelector('[name="industry"]').value, use_case: form.querySelector('[name="use_case"]').value }); }); ``` ## Privacy Best Practices ### Respect Cookie Consent Integrate with your consent management platform: ```javascript theme={null} // Initialize with consent requirement { "waitForConsent": true, ... } // Grant consent when user accepts cookieConsentTool.on('accept', function() { Snitcher.giveCookieConsent(); }); ``` ### Don't Track Sensitive Data Avoid sending PII in event properties unless necessary: ```javascript theme={null} // Good: Aggregate/safe data Snitcher.track("Profile Updated", { fields_updated: ["name", "company"], profile_complete: true }); // Bad: Unnecessary PII Snitcher.track("Profile Updated", { new_name: "John Smith", ssn: "123-45-6789" // Never do this! }); ``` ### Honor Do Not Track Consider respecting the browser's DNT setting: ```javascript theme={null} if (navigator.doNotTrack !== "1") { // Initialize Snitcher } ``` ## Data Quality Tips ### Identify Early Don't wait until checkout to identify users: ```javascript theme={null} // Good: Identify as soon as email is captured emailField.addEventListener('blur', function() { if (isValidEmail(this.value)) { Snitcher.identify(this.value); } }); // Bad: Only identify at the end form.addEventListener('submit', function() { Snitcher.identify(email); }); ``` ### Update Traits Over Time Call `identify()` whenever you learn new information: ```javascript theme={null} // Initial signup Snitcher.identify("user@company.com", { name: "Alex" }); // After profile completion Snitcher.identify("user@company.com", { role: "Marketing Manager", company_size: "51-200" }); // After upgrade Snitcher.identify("user@company.com", { plan: "enterprise", upgraded_at: new Date().toISOString() }); ``` ### Use Consistent Property Names Standardize across your codebase: ```javascript theme={null} // Pick one format and stick with it { company_size: "51-200" } // snake_case { companySize: "51-200" } // camelCase // Don't mix: { company_size: "51-200", companyName: "Acme" } // Inconsistent! ``` ## Common Mistakes to Avoid Track meaningful actions, not every click. Too many events create noise and slow down analysis. Ensure the tracker loads on mobile devices. Test on real devices, not just browser simulators. Always verify tracking works in staging before deploying to production. The Snitcher tracker is async by design. Don't wrap it in synchronous code. ## Next Steps Deep dive into user identification Track meaningful actions # Cookie Consent Source: https://docs.snitcher.com/product/tracker/cookie-consent Configure Snitcher to work with your cookie consent management solution for GDPR and privacy compliance. Snitcher supports integration with popular Consent Management Platforms (CMPs) to help you comply with GDPR, CCPA, and other privacy regulations. ## Enabling Consent Management To enable consent management, add `waitForConsent: true` to your tracking script configuration: ```javascript theme={null} { "profileId": "YOUR_PROFILE_ID", "apiEndpoint": "radar.snitcher.com", "cdn": "cdn.snitcher.com", "namespace": "Snitcher", "waitForConsent": true } ``` Without `waitForConsent: true`, Snitcher grants consent automatically on page load and visitor identity persists immediately—bypassing your consent flow. ## How It Works When `waitForConsent` is enabled: 1. **Before Consent**: Snitcher tracks pageviews and sessions, but visitor identity is not persisted across browser sessions. 2. **After Consent**: Visitor identity persists across sessions, enabling cross-session recognition and attribution. Even without consent, Snitcher still tracks pageviews and sessions—visitors just won't be recognized when they return. ## Automatic CMP Integration Snitcher automatically integrates with these Consent Management Platforms: | CMP | Detection | Notes | | ------------- | --------- | -------------------------------------- | | **Cookiebot** | Automatic | Listens for consent events | | **CookieYes** | Automatic | Listens for CookieYes consent events | | **OneTrust** | Automatic | Integrates with OneTrust's consent API | | **Transcend** | Automatic | Detects Transcend consent signals | If you use one of these CMPs, Snitcher will automatically: * Detect when a visitor grants analytics or marketing consent * Enable persistent visitor recognition Just ensure your CMP script loads before the Snitcher tracking script. ## Manual Consent Handling For custom cookie banners or other CMPs, you can manually grant consent: ```javascript theme={null} // Call this when your visitor accepts cookies Snitcher.giveCookieConsent(); ``` ### Example: Custom Cookie Banner ```html theme={null} ``` ### Opting Out (CCPA) Under opt-out regulations like the CCPA, Snitcher identifies visitors by default and the visitor has the right to withdraw consent at any time—for example, through a "Do Not Sell or Share My Personal Information" link. Call `denyCookieConsent()` when a visitor opts out: ```javascript theme={null} // Call this when your visitor opts out or withdraws consent Snitcher.denyCookieConsent(); ``` This clears the visitor's persisted identity (device ID, traits, and session) from cookies and `localStorage`, and stops recognizing them across sessions from that point forward. The opt-out persists across page loads and future sessions. The opt-out is reversible. If the visitor later opts back in, call `Snitcher.giveCookieConsent()` to clear the opt-out and re-enable cross-session recognition. ### Checking Existing Consent If a visitor has previously set a preference (stored in your own cookie/localStorage), apply it on page load: ```javascript theme={null} // Check your own consent storage const preference = localStorage.getItem('cookie_consent'); if (preference === 'granted') { Snitcher.giveCookieConsent(); } else if (preference === 'denied') { Snitcher.denyCookieConsent(); } ``` ## Integration with Tag Managers ### Google Tag Manager Create a Custom HTML tag that fires when your consent trigger activates: ```javascript theme={null} ``` Set this tag to fire on your consent-granted trigger (e.g., when a user accepts cookies). ### Cookiebot via GTM If using Cookiebot through GTM, create a trigger for the `CookiebotOnAccept` event: ```javascript theme={null} ``` ## Best Practices 1. **Load order matters**: Ensure your CMP script loads before the Snitcher tracking script 2. **Test both scenarios**: Verify tracking works both with and without consent 3. **Don't over-complicate**: If using a supported CMP, automatic integration should "just work" ## Troubleshooting * Ensure the CMP script loads before Snitcher * Check browser console for CMP-related errors * Verify the CMP is correctly configured * Confirm `giveCookieConsent()` was called * Check if localStorage is being cleared by the browser * Verify consent was actually granted in your CMP * Tracking still works without consent—just without cross-session recognition * Check network requests to `radar.snitcher.com` in DevTools # Custom Events Source: https://docs.snitcher.com/product/tracker/custom-events Track custom events and conversions with automatic tracking or the Snitcher JavaScript API. Snitcher tracks events in two ways: **automatic tracking** (zero code required) and **custom events** (for business-specific actions). Most users should start with automatic tracking enabled. ## Automatic Event Tracking Enable automatic tracking in your dashboard under **Settings → Tracker → Features**. No code changes required. | Feature | What It Tracks | Events Generated | | --------------------- | -------------------------------------------------------- | ------------------------------- | | **Form Tracking** | All form submissions and abandonments | `$form_submit`, `$form_abandon` | | **Click Tracking** | Link and button clicks, plus `data-track-event` elements | Click events | | **Download Tracking** | File downloads (.pdf, .docx, .zip, .xlsx, etc.) | Download events | **Recommended:** Enable all three for comprehensive tracking without writing any code. You can always add custom events later for specific use cases. ### What Gets Tracked Automatically **With Form Tracking enabled:** * Form submissions (with form ID, action URL, and field names) * Form abandonment (when users start but don't complete forms) **With Click Tracking enabled:** * All link clicks (with href, text, and position) * Button clicks * Elements with `data-track-event` attribute (see [Declarative Tracking](#declarative-click-tracking)) **With Download Tracking enabled:** * PDF, Word, Excel, PowerPoint downloads * ZIP, RAR, and other archive files * Any link with a `download` attribute *** ## Custom Events For business-specific actions not covered by automatic tracking, use the `Snitcher.track()` method. ### When to Use Custom Events | Use Automatic Tracking | Use Custom Events | | ---------------------- | --------------------------------- | | Form submissions | Demo requests with custom fields | | General click tracking | Pricing plan selection | | File downloads | Video engagement (play, complete) | | Link navigation | In-app feature usage | | | Purchases and conversions | | | A/B test interactions | ### The `track` Method ```javascript theme={null} Snitcher.track(eventName, properties); ``` The name of the event. Use `[Object] [Action]` format (e.g., "Trial Started", "Plan Selected"). Additional context about the event. ### Examples **Track a demo request with business context:** ```javascript theme={null} Snitcher.track("Demo Requested", { company_size: formData.company_size, industry: formData.industry, use_case: formData.use_case }); ``` **Track pricing interactions:** ```javascript theme={null} Snitcher.track("Pricing Plan Selected", { plan_name: "Pro", plan_price: 99, billing_cycle: "monthly" }); ``` **Track video engagement:** ```javascript theme={null} video.addEventListener('play', () => { Snitcher.track("Video Started", { video_title: "Product Demo" }); }); video.addEventListener('ended', () => { Snitcher.track("Video Completed", { video_title: "Product Demo" }); }); ``` **Track in-app actions:** ```javascript theme={null} Snitcher.track("Feature Enabled", { feature_name: "Dark Mode", user_plan: "pro" }); ``` *** ## Declarative Click Tracking For simple click tracking, you can use HTML `data-*` attributes instead of writing JavaScript. This is perfect for marketing sites, CMS-managed content, or anywhere you want to track clicks without code changes. ### The `data-track-event` Attribute Add `data-track-event` to any element to make it trackable: ```html theme={null} ``` When clicked, Snitcher automatically captures the click with the event name you specified. ### Adding Custom Properties Include additional `data-*` attributes to pass properties with the event: ```html theme={null} ``` This sends an event with properties: ```javascript theme={null} { buttonLocation: "hero", buttonVariant: "primary", campaign: "summer-2024" } ``` Property names are automatically converted from `kebab-case` to `camelCase`. So `data-button-location` becomes `buttonLocation`. ### Common Examples **Tracking navigation clicks:** ```html theme={null}
``` **Tracking feature interest:** ```html theme={null}

Analytics

Real-time insights...

Integrations

Connect to your stack...

``` **Tracking pricing tier interest:** ```html theme={null}

Starter

$29/mo

Pro

$99/mo

``` ### When to Use Declarative vs JavaScript Tracking | Use Declarative (`data-track-event`) | Use JavaScript (`Snitcher.track()`) | | ------------------------------------ | ----------------------------------- | | Simple click tracking | Complex event logic | | Static HTML / CMS content | Dynamic values from state | | No JavaScript access | Need to track non-click events | | Marketing pages | Application interactions | **Requires Click Tracking:** Enable click tracking in **Settings → Tracker → Features** for declarative tracking to work. *** ## Event Naming Best Practices * Use `[Object] [Action]` format * Be specific: "Pricing Plan Selected" * Use consistent capitalization * Keep names concise * Don't use vague names: "Clicked" * Don't include dynamic data in event names * Don't use special characters * Don't exceed 100 characters ### Good Event Names ```javascript theme={null} "Demo Requested" "Pricing Page Viewed" "Feature Toggle Enabled" "Trial Started" "Document Downloaded" "Chat Widget Opened" ``` ### Property Guidelines * Use `snake_case` for property names * Keep values short and meaningful * Include context: page URL, button location, user action * Don't include PII (emails, names) unless necessary ## Viewing Events in Snitcher Custom events appear in: 1. **Company Timeline**: See all events from a specific company 2. **Session Details**: View events within a visitor session 3. **Segments**: Create segments based on custom events ## Flush Events Immediately By default, events are batched and sent periodically. To send immediately (useful before navigation): ```javascript theme={null} // Track the event Snitcher.track("Checkout Started", { cart_value: 99.99 }); // Force immediate send Snitcher.flush(); // Now safe to navigate away window.location.href = '/checkout'; ``` ## React / Vue / SPA Integration For single-page applications, track events normally—the tracker handles client-side navigation automatically: ```javascript theme={null} // React example function handlePurchase() { Snitcher.track("Purchase Completed", { order_id: order.id, total: order.total }); } // Vue example methods: { onFeatureClick(feature) { Snitcher.track("Feature Selected", { feature_name: feature.name }); } } ``` ## Event Listeners Snitcher emits events that you can listen to for custom integrations, debugging, or triggering other actions. ### The `on` Method Subscribe to tracker events: ```javascript theme={null} Snitcher.on(eventType, callback); ``` ### Available Events | Event | Fired When | | ------------- | --------------------------------- | | `initialized` | Tracker finishes loading | | `pageview` | A pageview is tracked | | `identify` | A user is identified | | `track` | A custom event is tracked | | `form_submit` | A form submission is captured | | `click` | A click is tracked (when enabled) | ### Examples **Wait for tracker to initialize:** ```javascript theme={null} Snitcher.on('initialized', function(data) { console.log('Snitcher loaded, version:', data.version); // Safe to call other Snitcher methods loadUserAndIdentify(); }); ``` **React to pageviews:** ```javascript theme={null} Snitcher.on('pageview', function(page) { console.log('Page viewed:', page.path); // Trigger third-party analytics thirdPartyAnalytics.pageview(page.path); }); ``` **Log all tracked events:** ```javascript theme={null} Snitcher.on('track', function(event) { console.log('Event tracked:', event.name, event.properties); }); ``` **Sync identification with other tools:** ```javascript theme={null} Snitcher.on('identify', function(traits) { console.log('User identified:', traits.email); // Sync with other tools if (window.Intercom) { Intercom('update', { email: traits.email, name: traits.name }); } }); ``` ### One-Time Listeners Use `once` to listen for an event only once: ```javascript theme={null} Snitcher.once('initialized', function() { // This only fires once, even if tracker re-initializes performOneTimeSetup(); }); ``` ### Remove Listeners Use `off` to remove a listener: ```javascript theme={null} function myCallback(event) { console.log('Event:', event); } // Add listener Snitcher.on('track', myCallback); // Remove listener Snitcher.off('track', myCallback); ``` Event listeners are useful for integrating Snitcher with other tools, debugging, or building custom analytics dashboards. ## Debugging Open your browser's Developer Tools to see event tracking in action: 1. Go to the **Network** tab 2. Filter by `radar.snitcher.com` 3. Click on requests to see event payloads Events are batched, so you may see multiple events in a single request. ### Debug Mode Enable debug mode to see detailed logs in the console: ```javascript theme={null} { "profileId": "YOUR_PROFILE_ID", "debug": true, ... } ``` With debug mode enabled, you'll see logs for: * Tracker initialization * Every event sent * Any errors encountered # First-Party Tracking Source: https://docs.snitcher.com/product/tracker/first-party-tracking Set up a custom proxy to send tracking data through your own domain for maximum reliability. By default, Snitcher's tracker sends data to `radar.snitcher.com` and loads scripts from `cdn.snitcher.com`. While this works for most websites, some visitors use ad-blockers or privacy tools that may block requests to third-party tracking domains. **First-party tracking** solves this by routing all Snitcher traffic through your own domain, making it indistinguishable from your website's regular traffic. ## Why Use First-Party Tracking? Requests to `your-domain.com` aren't blocked by tools that target third-party trackers. Capture more pageviews, sessions, and identified users. Cookies set by your domain have longer lifespans and better browser support. All data flows through your infrastructure, giving you full control. ## How It Works Instead of: ``` Your Website → cdn.snitcher.com (script) Your Website → radar.snitcher.com (data) ``` With first-party tracking: ``` Your Website → cdn.yoursite.com → cdn.snitcher.com Your Website → tracking.yoursite.com → radar.snitcher.com ``` You set up a reverse proxy on your domain that forwards requests to Snitcher's servers. The tracker is configured to use your domain instead of ours. ## Setup Overview You'll need to configure two proxies: | Purpose | Your Domain | Proxies To | | -------------------- | ----------------------- | -------------------- | | Tracker script (CDN) | `cdn.yoursite.com` | `cdn.snitcher.com` | | Tracking API | `tracking.yoursite.com` | `radar.snitcher.com` | Avoid subdomains containing words like `analytics`, `tracking`, or `pixel`—some ad-blockers target these patterns. Use neutral names like `api`, `cdn`, or your company abbreviation. ## CloudFront Setup (AWS) CloudFront is a popular choice for proxying because it's fast, reliable, and easy to configure. ### Step 1: Create SSL Certificates If using Route 53 for DNS, create certificates for your proxy domains: 1. Go to **AWS Certificate Manager** in `us-east-1` (required for CloudFront) 2. Request certificates for: * `cdn.yoursite.com` * `tracking.yoursite.com` 3. Validate via DNS ### Step 2: Create CloudFront Distribution for the API 1. Go to **CloudFront** → **Create Distribution** 2. Configure the origin: * **Origin Domain**: `radar.snitcher.com` * **Protocol**: HTTPS Only 3. Configure cache behavior: * **Viewer Protocol Policy**: Redirect HTTP to HTTPS * **Allowed HTTP Methods**: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE * **Cache Policy**: CachingDisabled 4. Create an **Origin Request Policy** that forwards: * Headers: `Origin`, `Accept`, `User-Agent`, `Content-Type` * Query strings: All * Cookies: All 5. Under **Settings**: * Add alternate domain name: `tracking.yoursite.com` * Select your SSL certificate 6. Create the distribution ### Step 3: Create CloudFront Distribution for the CDN Repeat the process for the CDN: 1. **Origin Domain**: `cdn.snitcher.com` 2. **Alternate Domain**: `cdn.yoursite.com` 3. Use default caching (scripts can be cached) 4. Select your SSL certificate ### Step 4: Configure DNS Create CNAME records pointing to your CloudFront distributions: ``` cdn.yoursite.com → d1234abcd.cloudfront.net tracking.yoursite.com → d5678efgh.cloudfront.net ``` ### Step 5: Update Your Tracking Script Modify your Snitcher tracking script to use your proxy domains: ```html theme={null} ``` Note the changes: * `apiEndpoint`: Your API proxy domain * `cdn`: Your CDN proxy domain ## Nginx Setup If you're running your own infrastructure, nginx is a lightweight proxy option. ### Nginx Configuration ```nginx theme={null} # API Proxy server { listen 443 ssl http2; server_name tracking.yoursite.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass https://radar.snitcher.com; proxy_ssl_server_name on; proxy_set_header Host radar.snitcher.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } # CDN Proxy server { listen 443 ssl http2; server_name cdn.yoursite.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass https://cdn.snitcher.com; proxy_ssl_server_name on; proxy_set_header Host cdn.snitcher.com; # Cache static assets proxy_cache_valid 200 1d; add_header X-Cache-Status $upstream_cache_status; } } ``` ## Vercel Rewrites For Next.js sites on Vercel, use rewrites in `next.config.js`: ```javascript theme={null} /** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { return [ { source: '/sn-api/:path*', destination: 'https://radar.snitcher.com/:path*', }, { source: '/sn-cdn/:path*', destination: 'https://cdn.snitcher.com/:path*', }, ]; }, }; module.exports = nextConfig; ``` Then update your tracking script: ```javascript theme={null} { "apiEndpoint": "yoursite.com/sn-api", "cdn": "yoursite.com/sn-cdn", ... } ``` ## Netlify Redirects Add to your `netlify.toml`: ```toml theme={null} [[redirects]] from = "/sn-api/*" to = "https://radar.snitcher.com/:splat" status = 200 force = true [[redirects]] from = "/sn-cdn/*" to = "https://cdn.snitcher.com/:splat" status = 200 force = true ``` ## Testing Your Setup After configuration, verify everything works: ### 1. Test the CDN Proxy ```bash theme={null} curl -I https://cdn.yoursite.com/releases/latest/radar.min.js ``` You should receive a `200 OK` response with JavaScript content. ### 2. Test the API Proxy ```bash theme={null} curl https://tracking.yoursite.com/health ``` You should receive a successful response. ### 3. Check Browser Network Tab 1. Visit your website 2. Open Developer Tools → Network 3. Look for requests to your proxy domains 4. Verify no requests go to `*.snitcher.com` ## Troubleshooting * Clear your browser cache * Verify your tracking script has the correct `apiEndpoint` and `cdn` values * Check that DNS has propagated: `dig cdn.yoursite.com` Ensure your proxy forwards the `Origin` header and returns appropriate CORS headers. CloudFront handles this automatically with the right origin request policy. * Verify certificates are valid and not expired * For CloudFront, certificates must be in `us-east-1` * Ensure the certificate covers your proxy subdomain Cloudflare doesn't support cross-account proxying. If your main domain is on Cloudflare, use a different CDN (CloudFront, Fastly) for the proxy, or use a different subdomain not on Cloudflare. ## Next Steps Confirm tracking is working GDPR-compliant setup # Identify Email Recipients Source: https://docs.snitcher.com/product/tracker/identify-email-recipients Track and identify visitors who click links in your outbound and marketing emails. Snitcher can detect when a user clicks a link to your website from an outbound or marketing email. This allows you to collect identities from any clicks in your email campaigns—no form submission required. This integration significantly increases your identified visitor count, helping you understand how email recipients interact with your content and product before they ever fill out a form. Snitcher also captures all UTM parameters from email clicks, so you can attribute website activity to specific campaigns. ## Why Email Identification Matters Snitcher can usually identify which company is visiting your site, but many email clicks are harder to trace—people check emails on their phones, at home, or use privacy-focused email apps that hide their identity. Email link tracking solves this. When someone clicks a link in your email, you'll know exactly who they are—not just their company, but the actual person. Instead of "Someone from Acme Corp viewed pricing," you'll see "**Sarah Chen** from Acme Corp viewed pricing." ## How It Works Add a special parameter to your email links that contains the recipient's email. When they click through: 1. Snitcher reads the email parameter from the URL 2. The visitor is immediately identified 3. All their activity is linked to their email address 4. The parameter is automatically removed from the URL (no ugly query strings) ## Two Ways to Identify Snitcher supports two methods for passing email addresses in URLs: ### Option 1: Plain Email (`sn_email`) The simplest approach—pass the email address directly: ``` https://yoursite.com/pricing?sn_email=sarah@acme.com ``` **Pros:** Simple to implement, easy to debug\ **Cons:** Email is visible in the URL ### Option 2: Base64 Encoded (`sn_eid`) For better privacy and shorter URLs, encode the email as base64: ``` https://yoursite.com/pricing?sn_eid=c2FyYWhAYWNtZS5jb20= ``` **Pros:** Obfuscates the email address, shorter URLs for long email addresses\ **Cons:** Requires encoding step To encode an email address: ```javascript theme={null} // JavaScript / Node.js const email = "sarah@acme.com"; const encoded = Buffer.from(email).toString("base64"); // Result: "c2FyYWhAYWNtZS5jb20=" ``` ```python theme={null} # Python import base64 email = "sarah@acme.com" encoded = base64.b64encode(email.encode()).decode() # Result: "c2FyYWhAYWNtZS5jb20=" ``` Use base64 encoding when generating URLs programmatically or when you want to avoid exposing email addresses in browser history and server logs. *** ## Platform-Specific Setup ### HubSpot Add Snitcher parameters to your Sales and Marketing email templates. **For Sales Templates:** 1. Go to **Conversations** → **Templates** 2. Edit your template and add the parameter to your links **For Marketing Emails:** 1. Go to **Marketing** → **Emails** 2. Edit your template and add the parameter to your links **URL Parameters:** If there are no other URL params: ``` ?sn_email={{contact.email}} ``` If there are other URL params: ``` &sn_email={{contact.email}} ``` For base64-encoded emails, you'll need to create a custom property and workflow: **1. Create a `base64_email` property** in your Contact object schema. **2. Create a HubSpot Workflow:** Set the enrollment trigger to: * `Email` is known * `Email` has been updated in the last 1 day Add a custom code step: ```javascript theme={null} exports.main = async (event, callback) => { const email = event.inputFields['email']; const base64Encoded = Buffer.from(email).toString("base64"); callback({ outputFields: { base64_email: base64Encoded } }); } ``` Set the output variable to update the contact's `base64_email` property. **3. Update your templates** to use `{{contact.base64_email}}`: ``` ?sn_eid={{contact.base64_email}} ``` ### Apollo.io Update your sequence templates to include Snitcher parameters. 1. Go to **Engage** → **Sequences** 2. Edit your email template 3. Add the parameter to your links If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` ### Salesloft Update your email templates to include Snitcher parameters. 1. Open the email template editor 2. Add the parameter to your links If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` ### Outreach Update your sequence templates to include Snitcher parameters. 1. Open your sequence in the template editor 2. Add the parameter to all links pointing to your website If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` ### Smartlead Update your campaign sequence templates to include Snitcher parameters. 1. Open your campaign and go to the **Sequences** tab 2. Edit your email template 3. Add the parameter to any links pointing to your website If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` `{{email}}` is a default variable in Smartlead, automatically mapped from your lead list CSV. You can insert it by typing `{{` in the template editor and selecting from the dropdown. ### Lemlist Update your campaign sequence to include Snitcher parameters. 1. Go to **Campaigns** and open your campaign 2. Click the **Sequences** tab 3. Edit your email step and add the parameter to your links If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` ### Mailchimp Use merge tags to include the recipient's email in links. If there are no other URL params: ``` ?sn_email=*|EMAIL|* ``` If there are other URL params: ``` &sn_email=*|EMAIL|* ``` ### Constant Contact Use Constant Contact's **dynamic links** feature to insert the recipient's email address into your link URL. 1. In the email editor, highlight the text or select the button you want to link 2. Click the link icon and choose **Web Page** 3. Enter your URL with the `[[EmailAddress]]` variable If there are no other URL params: ``` ?sn_email=[[EmailAddress]] ``` If there are other URL params: ``` &sn_email=[[EmailAddress]] ``` Dynamic link variables like `[[EmailAddress]]` don't resolve when you preview or send a test email—they only populate during a live, scheduled send. To verify, send a real campaign to yourself and click the link. ### Customer.io Use Liquid templating to include the email in links. If there are no other URL params: ``` ?sn_email={{customer.email}} ``` If there are other URL params: ``` &sn_email={{customer.email}} ``` ### beehiiv Use beehiiv's merge tags to include the subscriber's email in your newsletter links. 1. Open the post editor 2. Select or create a link or button pointing to your website 3. Add the parameter to the URL If there are no other URL params: ``` ?sn_email={{email}} ``` If there are other URL params: ``` &sn_email={{email}} ``` `email` is a reserved field in beehiiv, so it works out of the box—no custom fields needed. Merge tags work inside both hyperlink URLs and button URLs. ### Marketo Use Marketo tokens in your email templates. If there are no other URL params: ``` ?sn_email={{lead.Email Address}} ``` If there are other URL params: ``` &sn_email={{lead.Email Address}} ``` *** ## Custom Implementation For any email platform or custom-built emails, simply append the appropriate parameter to your links: ### Using Plain Email ``` https://yoursite.com/demo?sn_email=recipient@company.com ``` ### Using Base64 Encoding ```javascript theme={null} // Generate the encoded ID const email = "recipient@company.com"; const encodedId = Buffer.from(email).toString("base64"); // Construct the URL const url = `https://yoursite.com/demo?sn_eid=${encodedId}`; // Result: https://yoursite.com/demo?sn_eid=cmVjaXBpZW50QGNvbXBhbnkuY29t ``` *** ## Adding Traits to Email Links You can enrich identification with additional traits by adding `sn_trait_` parameters to your URLs. Snitcher detects any parameter following the pattern `sn_trait_` and includes it in the user's profile. **Example traits:** ``` ?sn_email=sarah@acme.com&sn_trait_first_name=Sarah&sn_trait_last_name=Chen&sn_trait_title=VP%20Marketing ``` This identifies the visitor with: * Email: [sarah@acme.com](mailto:sarah@acme.com) * First Name: Sarah * Last Name: Chen * Title: VP Marketing ```javascript JavaScript theme={null} const params = new URLSearchParams({ sn_email: "sarah@acme.com", sn_trait_first_name: "Sarah", sn_trait_last_name: "Chen", sn_trait_title: "VP Marketing", sn_trait_company: "Acme Corp" }); const url = `https://yoursite.com/demo?${params.toString()}`; ``` ```python Python theme={null} from urllib.parse import urlencode params = urlencode({ "sn_email": "sarah@acme.com", "sn_trait_first_name": "Sarah", "sn_trait_last_name": "Chen", "sn_trait_title": "VP Marketing", "sn_trait_company": "Acme Corp" }) url = f"https://yoursite.com/demo?{params}" ``` ### Common Traits to Include | Trait | Parameter | Example | | ---------- | --------------------- | ----------------- | | First Name | `sn_trait_first_name` | `Sarah` | | Last Name | `sn_trait_last_name` | `Chen` | | Full Name | `sn_trait_name` | `Sarah Chen` | | Job Title | `sn_trait_title` | `VP Marketing` | | Company | `sn_trait_company` | `Acme Corp` | | Phone | `sn_trait_phone` | `+1-555-123-4567` | URL encode trait values that contain spaces or special characters. For example, "VP Marketing" becomes `VP%20Marketing`. *** ## Best Practices When generating links via code (APIs, scripts, automation), use `sn_eid` to keep emails out of logs and analytics. Before sending a campaign, click a test link and verify the visitor appears identified in Snitcher. Add name and title traits to make identified visitors immediately actionable for sales. Use UTM parameters for campaign attribution (`utm_campaign`, `utm_content`) alongside Snitcher's `sn_*` params for identity. ### Combine with UTM Parameters Snitcher's `sn_*` parameters identify **who** clicked your link. UTM parameters tell you **what** they clicked and **where** it came from. We recommend always using both together. Most email platforms (HubSpot, Mailchimp, ActiveCampaign, etc.) already have built-in UTM tagging—keep using that alongside Snitcher parameters. | Purpose | Parameters | Example | | -------------- | -------------------------- | -------------------------------------- | | Who clicked | `sn_email`, `sn_trait_*` | `sn_email=sarah@acme.com` | | Which campaign | `utm_campaign` | `utm_campaign=spring_launch` | | Which channel | `utm_source`, `utm_medium` | `utm_source=email&utm_medium=outreach` | | Which link | `utm_content` | `utm_content=hero_cta` | ### Example: Complete Email Link A fully instrumented email link might look like: ``` https://yoursite.com/case-studies?utm_source=email&utm_medium=outreach&utm_campaign=q1-enterprise&utm_content=case_study_cta&sn_email=sarah@acme.com&sn_trait_first_name=Sarah&sn_trait_company=Acme%20Corp ``` Or with base64 encoding: ``` https://yoursite.com/case-studies?utm_source=email&utm_medium=outreach&utm_campaign=q1-enterprise&utm_content=case_study_cta&sn_eid=c2FyYWhAYWNtZS5jb20=&sn_trait_first_name=Sarah&sn_trait_company=Acme%20Corp ``` *** ## Privacy Considerations Only use email link tracking for emails you send directly to recipients. Never expose email addresses in public links, social posts, or anywhere they could be accessed by unintended parties. Email link tracking is designed for: * Sales outreach emails * Marketing campaigns to your own lists * Transactional emails * Newsletter links **Not appropriate for:** * Public landing pages * Social media posts * Shared documents * Any link that could be forwarded or shared publicly *** ## Troubleshooting * Verify the parameter name is correct (`sn_email` or `sn_eid`) * Check that the Snitcher tracker is installed on the landing page * Ensure the email format is valid * For base64, verify the encoding is correct (no padding issues) Make sure you're using standard base64 encoding. Test your encoding: ```javascript theme={null} // Encode const encoded = Buffer.from("test@example.com").toString("base64"); console.log(encoded); // "dGVzdEBleGFtcGxlLmNvbQ==" // Decode to verify const decoded = Buffer.from(encoded, "base64").toString(); console.log(decoded); // "test@example.com" ``` * Ensure trait parameters follow the `sn_trait_` prefix pattern * Check that values are properly URL encoded * Traits should appear within a few minutes of the click Snitcher automatically removes identification parameters from the URL. If they persist: * Check that the tracker script is loading correctly * Verify there are no JavaScript errors on the page * Ensure the tracker version is up to date ## Next Steps Learn about the `identify()` method for form and login identification Track specific actions taken by identified visitors # Identify Users Source: https://docs.snitcher.com/product/tracker/identify-users Associate known user data with Snitcher visitor sessions for enhanced lead intelligence. When a visitor logs in, fills out a form, or otherwise reveals their identity, you can use the `identify` method to associate their information with the Snitcher session. This enables richer lead data and better attribution. ## The `identify` Method ```javascript theme={null} Snitcher.identify(email, traits); ``` The user's email address. This is the primary identifier used for enrichment and CRM matching. Additional properties about the user, such as name, company, role, or any custom attributes. ## Basic Example ```javascript theme={null} Snitcher.identify("john@company.com", { name: "John Doe", company: "Acme Inc", role: "Marketing Manager" }); ``` ## When to Identify Call `identify` whenever you learn who a visitor is: When a user signs into your app When someone submits a lead form When a visitor starts a trial When they provide email in chat ## Common Use Cases ### After Login ```javascript theme={null} // After successful authentication async function handleLogin(credentials) { const user = await login(credentials); // Identify the user to Snitcher Snitcher.identify(user.email, { name: user.name, user_id: user.id, plan: user.subscription.plan, account_created: user.createdAt }); } ``` ### On Form Submission ```javascript theme={null} document.querySelector('#lead-form').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); // Identify with form data Snitcher.identify(formData.get('email'), { name: formData.get('name'), company: formData.get('company'), phone: formData.get('phone'), message: formData.get('message') }); // Continue with form submission this.submit(); }); ``` ### Trial Signup ```javascript theme={null} async function handleTrialSignup(data) { const trial = await createTrial(data); Snitcher.identify(data.email, { name: data.name, company: data.company, company_size: data.companySize, trial_started: new Date().toISOString(), trial_plan: data.plan }); } ``` ### Chat Widget Integration ```javascript theme={null} // Example with Intercom Intercom('onUserEmail', function(email) { Snitcher.identify(email); }); // Example with Drift drift.on('emailCapture', function(data) { Snitcher.identify(data.email, { source: 'drift_chat' }); }); ``` ## OAuth, SSO, and Passwordless Login For login methods that don't use traditional forms—Google Sign-In, GitHub OAuth, SAML SSO, or magic links—you'll need to call `identify` manually after authentication completes. Snitcher's automatic form tracking captures emails from standard forms, but OAuth and SSO flows bypass form submission entirely. Manual identification is required. ### Google Sign-In ```javascript theme={null} // Using Google Identity Services google.accounts.id.initialize({ client_id: 'YOUR_CLIENT_ID', callback: handleCredentialResponse }); function handleCredentialResponse(response) { // Decode the JWT to get user info const payload = decodeJwt(response.credential); // Identify to Snitcher Snitcher.identify(payload.email, { name: payload.name, auth_provider: 'google', google_id: payload.sub }); // Continue with your auth flow authenticateWithBackend(response.credential); } ``` ### GitHub OAuth ```javascript theme={null} // After OAuth callback async function handleGitHubCallback(code) { const { user, token } = await exchangeCodeForToken(code); // Identify to Snitcher Snitcher.identify(user.email, { name: user.name, auth_provider: 'github', github_username: user.login }); // Store token and redirect setAuthToken(token); } ``` ### SAML SSO / Enterprise SSO ```javascript theme={null} // After SSO callback/assertion processing async function handleSSOCallback(samlResponse) { const user = await processSAMLResponse(samlResponse); // Identify to Snitcher Snitcher.identify(user.email, { name: user.displayName, auth_provider: 'saml', organization: user.organization, role: user.role }); } ``` ### Magic Links / Passwordless ```javascript theme={null} // When user clicks magic link and lands on your app async function handleMagicLinkAuth() { const token = getTokenFromURL(); const user = await verifyMagicLink(token); if (user) { // Identify to Snitcher Snitcher.identify(user.email, { name: user.name, auth_provider: 'magic_link' }); } } ``` ### Auth0 ```javascript theme={null} // Using Auth0 SPA SDK auth0.handleRedirectCallback().then(async () => { const user = await auth0.getUser(); if (user?.email) { Snitcher.identify(user.email, { name: user.name, auth_provider: 'auth0', auth0_id: user.sub }); } }); ``` ### Firebase Authentication ```javascript theme={null} // Firebase Auth state observer firebase.auth().onAuthStateChanged((user) => { if (user) { Snitcher.identify(user.email, { name: user.displayName, auth_provider: user.providerData[0]?.providerId || 'firebase', firebase_uid: user.uid }); } }); ``` ### Next.js with NextAuth ```typescript theme={null} // In your authentication callback or middleware import { getSession } from 'next-auth/react'; export default function AuthenticatedPage() { const { data: session } = useSession(); useEffect(() => { if (session?.user?.email) { window.Snitcher?.identify(session.user.email, { name: session.user.name, auth_provider: 'nextauth' }); } }, [session]); return
...
; } ``` ### Best Practices for OAuth/SSO For authenticated sections, call `identify` on every page load to ensure sessions are linked, not just on login. OAuth flows are async. Make sure `identify` is called after you have the user data, not before. Track which auth provider was used. This helps analyze user acquisition channels. `identify` is async and non-blocking. Don't wait for it to complete before redirecting users. ## What Happens After Identification When you call `identify`: 1. **Email is stored**: Associated with the current device/session 2. **Traits are merged**: Added to the user profile 3. **Event is sent**: An `$identify` event is recorded 4. **Enrichment triggered**: Snitcher enriches data based on the email domain Identification persists across sessions (if cookie consent is granted), so returning visitors are automatically recognized. ## Best Practices ### Include Useful Traits ```javascript theme={null} // Rich identification Snitcher.identify("sarah@startup.io", { name: "Sarah Chen", role: "Head of Growth", company: "Startup Inc", company_size: "51-200", industry: "SaaS", plan_interest: "Enterprise", source: "demo_request" }); ``` ### Identify Early Call `identify` as soon as you have the email—don't wait: ```javascript theme={null} // Good: Identify immediately after email capture emailInput.addEventListener('blur', function() { if (isValidEmail(this.value)) { Snitcher.identify(this.value); } }); ``` ### Update Traits Over Time You can call `identify` multiple times—traits are merged: ```javascript theme={null} // Initial identification Snitcher.identify("user@company.com", { name: "Alex" }); // Later, add more info Snitcher.identify("user@company.com", { plan: "Pro", upgraded_at: new Date().toISOString() }); // Result: { name: "Alex", plan: "Pro", upgraded_at: "..." } ``` ## Privacy Considerations Only identify users who have consented to tracking. In regions with strict privacy laws (GDPR, CCPA), ensure you have appropriate consent before calling `identify`. If you're using consent management: ```javascript theme={null} // Only identify after consent if (hasUserConsent()) { Snitcher.identify(user.email, { name: user.name }); } ``` ## Viewing Identified Users Identified users appear in your Snitcher dashboard with: * **Email address** (clickable to reveal company) * **Associated company** (from email domain + enrichment) * **Custom traits** you provided * **Full session history** ## Combining with Custom Events For complete tracking, combine identification with events: ```javascript theme={null} // User signs up Snitcher.identify(email, { name, company }); Snitcher.track("Trial Started", { plan: "Pro", source: "website" }); // User converts Snitcher.track("Subscription Started", { plan: "Pro", mrr: 99 }); ``` ## Troubleshooting * Verify `identify` was called (check network requests) * Ensure email format is valid * Check if consent was granted (if using consent management) * Traits may take a few minutes to sync * Verify traits are being sent in network request * Check for JavaScript errors in console * Ensure cookie consent is granted * Check if localStorage is being cleared * Verify same email is used across sessions ## Other Ways to Identify Users Don't have user logins or forms? You can identify visitors directly from email clicks by adding tracking parameters to your outbound and marketing emails. # Tracker Installation Source: https://docs.snitcher.com/product/tracker/installation Install the Snitcher JavaScript tracker on your website in minutes. Supports WordPress, Next.js, Webflow, Shopify, Google Tag Manager, and more. **Install the Snitcher tracker by adding a lightweight JavaScript snippet to your website's `` section.** The tracker works on any website platform including WordPress, Next.js, Webflow, Shopify, and via Google Tag Manager. Once installed, it automatically captures pageviews, sessions, and identifies companies visiting your site. ## Quick Start 1. Log in to your [Snitcher Dashboard](https://app.snitcher.com) 2. Navigate to **Settings → Tracker → Installation Instructions** 3. Copy your unique tracking script 4. Paste it into the `` section of your website ## Your Tracking Script Your tracking script looks like this (with your unique `profileId`): ```html theme={null} ``` Always copy the script from your dashboard to get your unique `profileId`. Do not modify the script code. ## Installation Methods Add the tracking script directly to your website's HTML: 1. Open your website's HTML template or CMS settings 2. Locate the `` section 3. Paste the tracking script immediately before the closing `` tag 4. Save and publish your changes ```html theme={null} ``` Deploy Snitcher via Google Tag Manager: 1. Log in to [Google Tag Manager](https://tagmanager.google.com) 2. Create a new **Custom HTML** tag 3. Paste your Snitcher tracking script 4. Set the trigger to **All Pages** 5. Save and publish your container For GTM, ensure the tag fires on all pages and before other marketing tags for best results. **Option 1: Using a Plugin** Use a header script plugin like "Insert Headers and Footers": 1. Install and activate the plugin 2. Go to Settings > Insert Headers and Footers 3. Paste your tracking script in the "Scripts in Header" section 4. Save changes **Option 2: Theme Editor** 1. Go to Appearance > Theme Editor 2. Select `header.php` 3. Add the script before `` 4. Update the file When using the theme editor, your changes may be lost when the theme updates. Use a child theme or plugin method for persistence. 1. Go to **Project Settings > Custom Code** 2. Paste the script in the **Head Code** section 3. Save changes 4. **Publish** your site (changes won't appear until published) 1. Go to **Online Store > Themes** 2. Click **Actions > Edit Code** 3. Find and open `theme.liquid` 4. Paste the script just before `` 5. Save the file 1. Go to **Settings > Custom Code** 2. Click **+ Add Custom Code** 3. Paste your tracking script 4. Set placement to **Head** and pages to **All Pages** 5. Apply and publish 1. Go to **Settings > Advanced > Code Injection** 2. Paste the script in the **Header** section 3. Save changes 1. Go to **Settings > Website > Pages** 2. Click **Templates** or go to the specific page 3. Add the script to the **Site Header HTML** section 4. Publish changes **App Router (Next.js 13+)** Create a client component for the tracker: ```tsx theme={null} // components/SnitcherTracker.tsx 'use client'; import Script from 'next/script'; export function SnitcherTracker() { return (