Skip to content

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 ​

MethodDescription
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 ​

  1. Create a survey in your Klero dashboard
  2. Go to the survey's settings or embed section
  3. 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-webview

Basic 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');
});

Customer Feedback Management