vTilt
By roleFoundersKnow what to fix firstMarketersSee what happens after the clickCMOsSee what your budget really buys
By businessSaaSTurn signups into active usersEcommerceSee why shoppers abandon cartsAgenciesProve your work to clientsEnterpriseOne customer record for every team
MeasureWeb AnalyticsFind where buyers leaveSession ReplaySee why they left, not just that they didAdsKnow what paid visitors do nextIntegrationsOne snippet feeds your stack
ThinkPeopleOne profile per customerCustomer MemoryvTilt remembers every visitorSite KnowledgeAnswers and audits from your own pages
ActAsk AIAnswers from real behaviorAI ChatChat that knows the visitorEmail CampaignsEmail from real visits
PricingWhy vTiltDocs
Docs / Java
Getting Started
OverviewInstallInitializeIdentify usersTrack eventsLogout & resetVerify eventsCommon mistakes
Guides
Event forwardingReverse proxyRealtime dashboardSite knowledge
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
API Reference
Browser SDK
Script bundlesAutocaptureWeb VitalsSession recordingChat widgetFeature readinessRemote configurationDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdownGlobal properties & opt-outError tracking
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceSite knowledgeGoogle AdsMeta Ads
Client setup
CursorClaude DesktopVS CodeCodex

Getting Started

OverviewInstallInitializeIdentify usersTrack eventsLogout & resetVerify eventsCommon mistakes

Guides

Event forwardingReverse proxyRealtime dashboardSite knowledge
PythonPHPRubyElixirGoJava.NET / C#Rust

API Reference

MCP server

On this page

On this page

  • 1. Add dependencies
  • 2. Capture client
  • 3. Capture events
  • 4. Spring Boot controller
  • Next steps
DocsGuidesBackend languagesJava

Java

Last updated July 22, 2026

Send vTilt events from Java code (Spring Boot, Micronaut, Quarkus, plain Java) by POSTing to the ingest API.

There's no native Java SDK yet, but vTilt's wire format is a plain JSON POST so any Java code can emit events. The pattern below uses the JDK 11+ HttpClient and Jackson; the same shape works inside Spring Boot, Micronaut, Quarkus, and standalone tools.

#1. Add dependencies

For Spring Boot (Gradle):

implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.0'
groovy

For Maven:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.16.0</version>
</dependency>
xml

#2. Capture client

A singleton client with a virtual-thread (Java 21+) executor for fire-and-forget captures. Replace with Executors.newCachedThreadPool() on Java 17.

// src/main/java/com/example/vtilt/Vtilt.java
package com.example.vtilt;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public final class Vtilt {
    private static final String TOKEN = System.getenv("VTILT_TOKEN");
    private static final String HOST = System.getenv().getOrDefault("VTILT_HOST", "https://www.vtilt.com");
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final HttpClient CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(2))
            .build();
    private static final ExecutorService EXEC = Executors.newVirtualThreadPerTaskExecutor();

    private Vtilt() {}

    public static void capture(String distinctId, String event, Map<String, Object> properties) {
        EXEC.submit(() -> send(distinctId, event, properties == null ? Map.of() : properties));
    }

    public static void identify(String distinctId, Map<String, Object> properties) {
        capture(distinctId, "$identify", Map.of("$set", properties));
    }

    private static void send(String distinctId, String event, Map<String, Object> properties) {
        try {
            Map<String, Object> body = new HashMap<>();
            body.put("api_key", TOKEN);
            body.put("event", event);
            body.put("distinct_id", distinctId);
            body.put("properties", properties);

            HttpRequest req = HttpRequest.newBuilder(URI.create(HOST + "/api/e"))
                    .header("Content-Type", "application/json")
                    .timeout(Duration.ofSeconds(2))
                    .POST(HttpRequest.BodyPublishers.ofString(MAPPER.writeValueAsString(body)))
                    .build();

            CLIENT.send(req, HttpResponse.BodyHandlers.discarding());
        } catch (Exception ignored) {
            // never raise on analytics
        }
    }
}
java

#3. Capture events

import com.example.vtilt.Vtilt;
import java.util.Map;

public class CheckoutService {
    public void completePurchase(String userId, double amount) {
        Vtilt.identify(userId, Map.of("plan", "pro"));

        Vtilt.capture(userId, "purchase_completed", Map.of(
            "amount", amount,
            "currency", "USD"
        ));
    }
}
java

#4. Spring Boot controller

@RestController
public class CheckoutController {

    @PostMapping("/checkout")
    public Map<String, Boolean> complete(@RequestBody CheckoutRequest req) {
        Vtilt.capture(req.userId(), "purchase_completed", Map.of("amount", req.amount()));
        return Map.of("ok", true);
    }
}
java

#Next steps

  • Identify & alias — full identification model.
  • Event forwarding — fan events out to GA4, Meta CAPI, PostHog.
  • Reverse proxy — block-resistant ingestion.
  • Common mistakes — integration pitfalls to avoid before you ship.
PreviousGoIntegration guidesNext.NET / C#Integration guides