@@ -10,14 +10,14 @@ Add to your `pom.xml`:
1010<dependency >
1111 <groupId >com.klime</groupId >
1212 <artifactId >klime</artifactId >
13- <version >1.0.0 </version >
13+ <version >1.0.2 </version >
1414</dependency >
1515```
1616
1717Or with Gradle:
1818
1919``` groovy
20- implementation 'com.klime:klime:1.0.0 '
20+ implementation 'com.klime:klime:1.0.2 '
2121```
2222
2323## Quick Start
@@ -64,6 +64,85 @@ public class Example {
6464}
6565```
6666
67+ ## Installation Prompt
68+
69+ Copy and paste this prompt into Cursor, Copilot, or your favorite AI editor to integrate Klime:
70+
71+ ```
72+ Integrate Klime for B2B customer analytics. Klime tracks user activity to identify which customers (companies) are healthy vs at risk of churning.
73+
74+ KEY CONCEPTS:
75+ - Groups = companies/organizations (your B2B customers)
76+ - Every track() call requires a userId (no anonymous events)
77+ - group() links a user to a company AND sets company traits
78+ - Order doesn't matter - events before identify/group still get attributed correctly
79+
80+ BEST PRACTICES:
81+ - Initialize client ONCE at app startup (singleton or Spring bean)
82+ - Store write key in KLIME_WRITE_KEY environment variable
83+ - Call shutdown() on application stop to flush remaining events
84+ - Pass user's IP address for geolocation (use .ip() option)
85+
86+ Add to pom.xml:
87+ <dependency>
88+ <groupId>com.klime</groupId>
89+ <artifactId>klime</artifactId>
90+ <version>1.0.2</version>
91+ </dependency>
92+
93+ Or with Gradle: implementation 'com.klime:klime:1.0.2'
94+
95+ import com.klime.KlimeClient;
96+ import com.klime.TrackOptions;
97+ import com.klime.GroupOptions;
98+
99+ KlimeClient client = KlimeClient.builder().writeKey(System.getenv("KLIME_WRITE_KEY")).build();
100+
101+ // Identify users at signup/login:
102+ client.identify("usr_abc123", Map.of("email", "jane@acme.com", "name", "Jane Smith"));
103+
104+ // Track key activities:
105+ client.track("Report Generated", Map.of("report_type", "revenue"), TrackOptions.builder().userId("usr_abc123").ip(clientIp).build());
106+ client.track("Feature Used", Map.of("feature", "export", "format", "csv"), TrackOptions.builder().userId("usr_abc123").build());
107+ client.track("Teammate Invited", Map.of("role", "member"), TrackOptions.builder().userId("usr_abc123").build());
108+
109+ // Link user to their company and set company traits:
110+ client.group("org_456", Map.of("name", "Acme Inc", "plan", "enterprise"), GroupOptions.builder().userId("usr_abc123").build());
111+
112+ INTEGRATION WORKFLOW:
113+
114+ Phase 1: Discover
115+ Explore the codebase to understand:
116+ 1. What framework is used? (Spring Boot, Quarkus, Micronaut, Jakarta EE, etc.)
117+ 2. Where is user identity available? (e.g., SecurityContextHolder, @AuthenticationPrincipal, Principal, JWT claims)
118+ 3. How are organizations/companies modeled? (look for: organization, workspace, tenant, team, account)
119+ 4. Where do core user actions happen? (controllers, services, event handlers)
120+ 5. Is there existing analytics? (search: segment, posthog, mixpanel, amplitude, track)
121+ Match your integration style to the framework's conventions.
122+
123+ Phase 2: Instrument
124+ Add these calls using idiomatic patterns for the framework:
125+ - Initialize client once (Spring: @Bean/@Configuration, Quarkus: @ApplicationScoped, Jakarta EE: @WebListener)
126+ - identify() in auth/login success handler
127+ - group() when user-org association is established
128+ - track() for key user actions (see below)
129+
130+ WHAT TO TRACK:
131+ Active engagement (primary): feature usage, resource creation, collaboration, completing flows
132+ Session signals (secondary): login/session start, dashboard access - distinguishes "low usage" from "churned"
133+ Do NOT track: every endpoint, health checks, actuator calls, background jobs
134+
135+ Phase 3: Verify
136+ Confirm: client initialized, shutdown handled, identify/group/track calls added
137+
138+ Phase 4: Summarize
139+ Report what you added:
140+ - Files modified and what was added to each
141+ - Events being tracked (list event names and what triggers them)
142+ - How userId and groupId are obtained
143+ - Any assumptions made or questions
144+ ```
145+
67146## API Reference
68147
69148### Initialization
@@ -170,26 +249,26 @@ client.shutdown().join();
170249
171250## Configuration
172251
173- | Option | Default | Description |
174- | ------------------- | ----------------------- | -- ------------------------------- |
175- | ` writeKey ` | (required) | Your Klime write key |
176- | ` endpoint ` | ` https://i.klime.com ` | API endpoint URL |
177- | ` flushInterval ` | ` 2 seconds ` | Time between automatic flushes |
178- | ` maxBatchSize ` | ` 20 ` | Max events per batch (max: 100) |
179- | ` maxQueueSize ` | ` 1000 ` | Max queued events |
180- | ` retryMaxAttempts ` | ` 5 ` | Max retry attempts |
181- | ` retryInitialDelay ` | ` 1 second ` | Initial retry delay |
182- | ` flushOnShutdown ` | ` true ` | Auto-flush on JVM shutdown |
252+ | Option | Default | Description |
253+ | ------------------- | --------------------- | ------------------------------- |
254+ | ` writeKey ` | (required) | Your Klime write key |
255+ | ` endpoint ` | ` https://i.klime.com ` | API endpoint URL |
256+ | ` flushInterval ` | ` 2 seconds ` | Time between automatic flushes |
257+ | ` maxBatchSize ` | ` 20 ` | Max events per batch (max: 100) |
258+ | ` maxQueueSize ` | ` 1000 ` | Max queued events |
259+ | ` retryMaxAttempts ` | ` 5 ` | Max retry attempts |
260+ | ` retryInitialDelay ` | ` 1 second ` | Initial retry delay |
261+ | ` flushOnShutdown ` | ` true ` | Auto-flush on JVM shutdown |
183262
184263## Error Handling
185264
186- | Status Code | Behavior |
187- | ----------- | ----------------------------------------------- |
188- | 200 | Success (may contain partial failures) |
189- | 400 | Malformed request - events dropped, no retry |
190- | 401 | Invalid write key - events dropped, no retry |
191- | 429 | Rate limited - retry with exponential backoff |
192- | 503 | Service unavailable - retry with backoff |
265+ | Status Code | Behavior |
266+ | ----------- | --------------------------------------------- |
267+ | 200 | Success (may contain partial failures) |
268+ | 400 | Malformed request - events dropped, no retry |
269+ | 401 | Invalid write key - events dropped, no retry |
270+ | 429 | Rate limited - retry with exponential backoff |
271+ | 503 | Service unavailable - retry with backoff |
193272
194273## Size Limits
195274
@@ -230,7 +309,7 @@ public class UserService {
230309
231310 public void registerUser (String userId , String email ) {
232311 // Your business logic...
233-
312+
234313 klime. identify(userId, Map . of(
235314 " email" , email,
236315 " registeredAt" , Instant . now(). toString()
@@ -278,7 +357,7 @@ public class ActionServlet extends HttpServlet {
278357 @Override
279358 protected void doPost (HttpServletRequest req , HttpServletResponse resp ) {
280359 String userId = req. getParameter(" userId" );
281-
360+
282361 KlimeListener . getClient(). track(" Action Performed" , Map . of(
283362 " action" , " submit"
284363 ), TrackOptions . builder()
@@ -329,4 +408,3 @@ public class KlimeProducer {
329408## License
330409
331410MIT License - see [ LICENSE.md] ( LICENSE.md ) for details.
332-
0 commit comments