Surveys
The Surveys module allows you to display customizable survey forms to collect targeted feedback from your users.
Features
- Multiple question types (text, rating, multiple choice, etc.)
- Customizable appearance
- Response collection and analytics
- Conditional logic support
- Progress indicators
Web Integration
Basic Usage
Add the Klero script to your page, then open a survey programmatically using JavaScript:
html
<script src="https://YOUR-PROJECT.klero.ai/embed/klero.js" async></script>
<script>
// Open a survey by its ID
window.Klero.openSurvey('YOUR_SURVEY_ULID');
</script>Trigger on Button Click
html
<button onclick="window.Klero.openSurvey('YOUR_SURVEY_ULID')">
Take our survey
</button>With Authenticated User
Pre-fill respondent information when users are logged in by setting the customer token before opening the survey:
html
<script src="https://YOUR-PROJECT.klero.ai/embed/klero.js" async></script>
<klero-feedback data-config='{"customerToken": "YOUR_JWT_TOKEN"}'></klero-feedback>
<script>
// The customer token from any Klero embed is shared across modules
window.Klero.openSurvey('YOUR_SURVEY_ULID');
</script>API Reference
| Method | Description |
|---|---|
window.Klero.openSurvey(surveyUlid) | Opens a survey modal by its ULID |
window.KleroSurvey.open(surveyUlid) | Opens a survey (module must be loaded) |
window.KleroSurvey.close() | Closes the currently open survey |
window.KleroSurvey.destroy() | Destroys the survey widget instance |
Getting the Survey ID
- Create a survey in your Klero dashboard
- Go to the survey's settings or embed section
- Copy the Survey ULID
React
tsx
import { KleroSurvey } from '@kleroai/react';
function App() {
return (
<KleroSurvey
projectSlug="myproject"
surveyUlid="01ABC123..."
onComplete={(data) => console.log('Completed:', data.responseUlid)}
onClose={(data) => console.log('Closed, completed:', data.completed)}
onError={(error) => console.error('Error:', error)}
/>
);
}Vue
vue
<script setup>
import { KleroSurvey } from '@kleroai/vue';
function handleComplete(data) {
console.log('Completed:', data.responseUlid);
}
</script>
<template>
<KleroSurvey
project-slug="myproject"
survey-ulid="01ABC123..."
@complete="handleComplete"
/>
</template>React Native
Use the @kleroai/react-native package to show surveys in your React Native app.
Installation
bash
npm install @kleroai/react-native react-native-webviewBasic Usage
tsx
import { KleroSurvey } from '@kleroai/react-native';
function App() {
return (
<KleroSurvey
projectSlug="myproject"
surveyUlid="01ABC123..."
onComplete={(data) => {
console.log('Survey completed:', data.responseUlid);
console.log('Answers:', data.answers);
}}
onClose={(data) => {
console.log('Survey closed, completed:', data.completed);
}}
onError={(error) => console.error('Survey error:', error)}
/>
);
}Programmatic Control
tsx
import { useRef } from 'react';
import { Button, View } from 'react-native';
import { KleroSurvey, KleroSurveyHandle } from '@kleroai/react-native';
function App() {
const surveyRef = useRef<KleroSurveyHandle>(null);
return (
<View style={{ flex: 1 }}>
<Button title="Open Survey" onPress={() => surveyRef.current?.open()} />
<Button title="Close Survey" onPress={() => surveyRef.current?.close()} />
<KleroSurvey
ref={surveyRef}
projectSlug="myproject"
surveyUlid="01ABC123..."
onComplete={(data) => console.log('Completed!')}
/>
</View>
);
}With Customer Token
tsx
<KleroSurvey
projectSlug="myproject"
surveyUlid="01ABC123..."
customerToken="user-jwt-token-from-your-backend"
onComplete={(data) => {}}
/>Android
Installation
kotlin
dependencies {
implementation("com.github.klero-ai:klero-android:0.1.0")
}Basic Usage
kotlin
import com.klero.sdk.KleroConfig
import com.klero.sdk.KleroSurvey
import com.klero.sdk.KleroSurveyListener
class MainActivity : AppCompatActivity(), KleroSurveyListener {
private lateinit var survey: KleroSurvey
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = KleroConfig(projectSlug = "myproject")
survey = KleroSurvey(this, config, "01ABC123...")
survey.listener = this
setContentView(survey)
}
override fun onComplete(surveyUlid: String, responseUlid: String, answers: Map<String, Any>) {
println("Survey completed: $responseUlid")
}
override fun onClose(surveyUlid: String, completed: Boolean) {
println("Survey closed, completed: $completed")
}
override fun onError(surveyUlid: String, error: String) {
println("Survey error: $error")
}
override fun onDestroy() {
super.onDestroy()
survey.destroy()
}
}Jetpack Compose
kotlin
@Composable
fun KleroSurveyComposable(
projectSlug: String,
surveyUlid: String,
customerToken: String? = null,
onComplete: ((String, String, Map<String, Any>) -> Unit)? = null,
onClose: ((String, Boolean) -> Unit)? = null,
onError: ((String, String) -> Unit)? = null
) {
AndroidView(
factory = { context ->
val config = KleroConfig(
projectSlug = projectSlug,
customerToken = customerToken
)
KleroSurvey(context, config, surveyUlid).apply {
listener = object : KleroSurveyListener {
override fun onComplete(s: String, r: String, a: Map<String, Any>) {
onComplete?.invoke(s, r, a)
}
override fun onClose(s: String, c: Boolean) { onClose?.invoke(s, c) }
override fun onError(s: String, e: String) { onError?.invoke(s, e) }
}
}
}
)
}iOS
Installation (Swift Package Manager)
swift
dependencies: [
.package(url: "https://github.com/klero-ai/klero-ios.git", from: "0.1.0")
]UIKit
swift
import UIKit
import KleroSDK
class ViewController: UIViewController, KleroSurveyDelegate {
private var survey: KleroSurvey!
override func viewDidLoad() {
super.viewDidLoad()
let config = KleroConfig(projectSlug: "myproject")
survey = KleroSurvey(config: config, surveyUlid: "01ABC123...")
survey.delegate = self
survey.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(survey)
NSLayoutConstraint.activate([
survey.topAnchor.constraint(equalTo: view.topAnchor),
survey.leadingAnchor.constraint(equalTo: view.leadingAnchor),
survey.trailingAnchor.constraint(equalTo: view.trailingAnchor),
survey.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
func kleroSurveyDidComplete(
surveyUlid: String,
responseUlid: String,
answers: [String: Any]
) {
print("Survey completed: \(responseUlid)")
}
func kleroSurveyDidClose(surveyUlid: String, completed: Bool) {
print("Survey closed, completed: \(completed)")
}
func kleroSurveyDidError(surveyUlid: String, error: String) {
print("Survey error: \(error)")
}
}SwiftUI
swift
import SwiftUI
import KleroSDK
struct KleroSurveyView: UIViewRepresentable {
let projectSlug: String
let surveyUlid: String
var customerToken: String?
var onComplete: ((String, String, [String: Any]) -> Void)?
var onClose: ((String, Bool) -> Void)?
var onError: ((String, String) -> Void)?
func makeUIView(context: Context) -> KleroSurvey {
let config = KleroConfig(
projectSlug: projectSlug,
customerToken: customerToken
)
let survey = KleroSurvey(config: config, surveyUlid: surveyUlid)
survey.delegate = context.coordinator
return survey
}
func updateUIView(_ uiView: KleroSurvey, context: Context) {}
func makeCoordinator() -> Coordinator { Coordinator(self) }
class Coordinator: NSObject, KleroSurveyDelegate {
let parent: KleroSurveyView
init(_ parent: KleroSurveyView) { self.parent = parent }
func kleroSurveyDidComplete(surveyUlid: String, responseUlid: String, answers: [String: Any]) {
parent.onComplete?(surveyUlid, responseUlid, answers)
}
func kleroSurveyDidClose(surveyUlid: String, completed: Bool) {
parent.onClose?(surveyUlid, completed)
}
func kleroSurveyDidError(surveyUlid: String, error: String) {
parent.onError?(surveyUlid, error)
}
}
}
// Usage
struct ContentView: View {
var body: some View {
KleroSurveyView(
projectSlug: "myproject",
surveyUlid: "01ABC123...",
onComplete: { _, responseUlid, _ in print("Completed: \(responseUlid)") }
)
}
}Flutter
dart
import 'package:klero_flutter/klero_flutter.dart';
KleroSurvey(
projectSlug: 'myproject',
surveyUlid: '01ABC123...',
onComplete: (data) {
print('Completed: ${data.responseUlid}');
},
onClose: (data) {
print('Closed, completed: ${data.completed}');
},
onError: (error) {
print('Error: $error');
},
)Complete Web Example
html
<!DOCTYPE html>
<html>
<head>
<title>Quick Survey</title>
</head>
<body>
<h1>We'd love your feedback</h1>
<p>This survey takes about 2 minutes to complete.</p>
<button onclick="window.Klero.openSurvey('YOUR_SURVEY_ULID')">
Start Survey
</button>
<script src="https://your-project.klero.ai/embed/klero.js" async></script>
</body>
</html>Use Cases
NPS Survey
Collect Net Promoter Score after key interactions:
javascript
// Trigger after a key action (e.g., completing onboarding)
window.Klero.openSurvey('nps-survey-ulid');Feature Feedback
Gather feedback on specific features:
javascript
// Trigger when user interacts with a new feature
window.Klero.openSurvey('new-dashboard-feedback-ulid');Exit Survey
Understand why users cancel:
javascript
// Trigger when user clicks "Cancel Subscription"
document.getElementById('cancel-btn').addEventListener('click', () => {
window.Klero.openSurvey('cancellation-survey-ulid');
});