vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / Java
Quick startEvent forwarding
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceGoogle Ads
Client setup
CursorClaude DesktopVS CodeCodex
Realtime
Debug ViewRealtime Dashboard
Integration guides
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
SDK
Browser SDK
InstallScript bundlesEvent trackingAutocaptureIdentify & aliasWeb VitalsSession recordingChat widgetFeature readinessRemote configurationReverse proxyDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdown

Documentation

vTilt
Quick startEvent forwarding

MCP server

Realtime

Debug ViewRealtime Dashboard

Integration guides

PythonPHPRubyElixirGoJava.NET / C#Rust

SDK

DocsIntegration guidesJava

Java

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.
PreviousGoIntegration guidesNext.NET / C#Integration guides

On this page

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