{"id":20217344,"url":"https://github.com/gojek/clickstream-android","last_synced_at":"2025-08-22T11:43:54.989Z","repository":{"id":36971603,"uuid":"483142816","full_name":"gojek/clickstream-android","owner":"gojek","description":"A Modern, Fast, and Lightweight Android Library Ingestion Platform.","archived":false,"fork":false,"pushed_at":"2024-02-01T07:37:59.000Z","size":1556,"stargazers_count":71,"open_issues_count":3,"forks_count":9,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-10T16:06:49.127Z","etag":null,"topics":["android","android-library","gojek","ingestion-platform","kotlin-library","mobile-development"],"latest_commit_sha":null,"homepage":"https://odpf.gitbook.io/raccoon/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gojek.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING-GUIDE.md","funding":null,"license":"LICENSE","code_of_conduct":"docs/CODE-OF-CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-19T07:32:42.000Z","updated_at":"2025-01-22T09:00:19.000Z","dependencies_parsed_at":"2024-11-14T12:32:16.836Z","dependency_job_id":null,"html_url":"https://github.com/gojek/clickstream-android","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/gojek/clickstream-android","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gojek%2Fclickstream-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gojek%2Fclickstream-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gojek%2Fclickstream-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gojek%2Fclickstream-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gojek","download_url":"https://codeload.github.com/gojek/clickstream-android/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gojek%2Fclickstream-android/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271632763,"owners_count":24793744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-22T02:00:08.480Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","gojek","ingestion-platform","kotlin-library","mobile-development"],"created_at":"2024-11-14T06:33:37.133Z","updated_at":"2025-08-22T11:43:54.948Z","avatar_url":"https://github.com/gojek.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/clickstream-horizontal-black.svg#gh-light-mode-only\" width=\"500\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/clickstream-horizontal-white.svg#gh-dark-mode-only\" width=\"500\"/\u003e\n\u003c/p\u003e\n\n#### A Modern, Fast, and Lightweight Android Ingestion Library\n\n![CI](https://github.com/gojek/clickstream-android/workflows/Build/badge.svg)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.gojek.clickstream/clickstream-android/badge.svg)](https://search.maven.org/artifact/com.gojek.android/clickstream)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nClickstream is an event agnostic, real-time data ingestion platform. Clickstream allows apps to maintain a long-running connection to send data in real-time.\n\nThe word “Clickstream” is a trail of digital breadcrumbs left by users as they click their way through a website or mobile app. It is loaded with valuable customer information for businesses and its analysis and usage has emerged as a powerful data source.\n\n**To know more about Clickstream, you can read our [Medium post](https://www.gojek.io/blog/introducing-clickstream?utm_source=blog\u0026utm_medium=medium%20blog\u0026utm_campaign=blog_clickstream)**\n\n**Clickstream provides an end to end solution for event ingestion. For setting up the backend infrastructure please check out [raccoon](https://github.com/goto/raccoon)**\n\n\n## Architecture\n\n![Clickstream Architecture](https://github.com/gojekfarm/clickstream-ios/blob/main/Resources/clickstream-architecture.png)\n\n#### Mobile Library Architecture\n\n![Clickstream HLD](https://github.com/gojekfarm/clickstream-ios/blob/main/Resources/clickstream-HLD.png)\n\n## Key features\n\n-   Simple and lightweight\n-   Remotely Configurable\n-   Support for real-time data\n-   Multiple QoS support (QoS0 and QoS1)\n-   Typesafe and reusable schemas\n-   Efficient payloads\n-   In-built data aggregation\n\n### Getting Started with Clickstream\n\n1. Add the maven repository URL to the root `build.gradle` of your project.\n\n```kotlin\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n}\n```\n\n2. Add the following dependencies to your module `build.gradle`\n\n```kotlin\ndependencies {\n    val version = \"x.y.z\"\n    // Required\n    implementation 'com.gojek.clickstream:clickstream-android:[latest_version]'\n    implementation 'com.gojek.clickstream:clickstream-lifecycle:[latest_version]'\n\n    // Optional\n    implementation 'com.gojek.clickstream:clickstream-health-metrics:[latest_version]'\n}\n```\n\nBy default ClickStream embedded the rules, so not necessary client added the rules explicitly\n\n```\n-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }\n\n# Scarlet\n-if interface * { @com.tinder.scarlet.ws.* \u003cmethods\u003e; }\n-keep,allowobfuscation interface \u003c1\u003e\n-keepclassmembers,allowshrinking,allowobfuscation interface * {\n    @com.tinder.scarlet.ws.* \u003cmethods\u003e;\n}\n\n# Keep the ProcessLifecycleInitializer meta\n-keepresourcexmlelements manifest/application/provider/meta-data@name=androidx.lifecycle.ProcessLifecycleInitializer\n-keepresourcexmlelements manifest/application/provider/meta-data@value=androidx.startup\n```\n\nOnce you’ve added the dependencies and synchronized your Gradle project, the next step is to initialize Clickstream.\n\n### Initialization\n\nInitialization of the Clickstream can be done on the background thread or main-thread,\nInvocation should be done on the Application class. So that the initialization happens only once.\n\nTo create a Clickstream instance you can do the following setup:\n\n```kotlin\nclass App : Application() {\n\n    override fun onCreate() {\n        initClickStream()\n    }\n\n    private fun initClickStream() {\n        ClickStream.initialize(\n            configuration = CSConfiguration.Builder(\n                context = context,\n                info = CSInfo(\n                    appInfo = appInfo,\n                    locationInfo = locationInfo,\n                    deviceInfo = csDeviceInfo,\n                    customerInfo = customerInfo,\n                    sessionInfo = sessionInfo\n                ),\n                config = getBuildConfig(config),\n                appLifeCycle = DefaultCSAppLifeCycleObserver(context),\n                healthGateway = DefaultOpCSHealthGateway.factory(/*args*/)\n            ).apply {\n                setLogLevel(DEBUG)\n                /**/ \n                setCSSocketConnectionListener(connectionListener())\n            }.build())\n    }\n\n    /**\n    * @see [CSConnectionEvent] for more detail explanation\n    */\n    private fun onConnectionListener(): CSSocketConnectionListener {\n        return object : CSSocketConnectionListener {\n            override fun onEventChanged(event: CSConnectionEvent) {\n                is OnConnectionConnecting -\u003e {}\n                is OnConnectionConnected -\u003e {}\n                is OnMessageReceived -\u003e {}\n                is OnConnectionClosing -\u003e {}\n                is OnConnectionClosed -\u003e {}\n                is OnConnectionFailed -\u003e {}\n \t\t\t}\n    \t}\n    }\n}\n```\n\n\n### Configuration\n\n#### CSEventSchedulerConfig\n\nHolds the configurations for Clickstream. These constraints allow for fine-grained control over the library behaviour like duration between retries, flush events when app goes in background, etc.\n\n|  Description | Variable | Type |\tDefault value |\n|--|--|--|--|\n| Number of events to combine in a single request | eventsPerBatch | Int | 20 |\n| Delay between two requests (in millis) | batchPeriod | Long | 10000 |\n| Flag for enabling forced flushing of events | flushOnBackground | Boolean | false |\n| Wait time after which socket gets disconnected | connectionTerminationTimerWaitTimeInMillis | Long | 5000 |\n| Flag for enabling flushing of events by background task | backgroundTaskEnabled | Boolean\t| false |\n| Initial delay for background task (in hour) | workRequestDelayInHr | Long | 1 |\n\n#### CSNetworkConfig\nHolds the configuration for network related. e.g configure timeouts for network channel.\n\n|  Description|  Variable |\tType |\tDefault value |\n|--|--|--|--|\n|  Endpoint for web socket server | endPoint | String | No Default Value |\n|  Connect timeout to be used by okhttp (in seconds) | connectTimeout | Long | 10 |\n|  Read timeout to be used by okhttp (in seconds) | readTimeout | Long | 10 |\n|  Write timeout to be used by okhttp (in seconds) | writeTimeout | Long | 10 |\n|  Interval between pings initiated by client (in seconds) | pingInterval | Long | 1 |\n|  Initial retry duration to be used for retry backoff strategy (in milliseconds) | initialRetryDurationInMs | Long | 1000 |\n|  Maximum retry duration for retry backoff strategy (in milliseconds) | maxConnectionRetryDurationInMs | Long | 6000 |\n|  Maximum retries per batch request | maxRetriesPerBatch | Long | 20 |\n|  Maximum timeout for a request to receive Ack (in milliseconds) | maxRequestAckTimeout | Long | 10000 |\n|  OkHttpClient instance that passed from client | okHttpClient | OkHttpClient | No Default Value |\n\n#### CSEventClassification\nHolds the class name to be classify into InstantEvent (QoS) or RealtimeEvent (QoS1).\n\n|  Description |  Variable | Type |\tDefault value |\n|--|--|--|--|\n|  Holds all the eventTypes | eventTypes |\tEventClassifier | [EventClassifier(identifier: \"realTime\", eventNames: []), EventClassifier(identifier: \"instant\", eventNames: [])]|\n\n### Cleanup\nDestroy instance of Clickstream, for example can be called when user logs out of the app.\n\n```kotlin\n   ClickStream.release()\n```\n\n### Push an Event\n\n#### Using Explicit Builder\n\nAs Clickstream use a proto definition on the client-side, you can build a MessageLite and send it directly through ClickstreamSDK.\n\nFor instance, you’ve defined a proto definition called `Rating.java` which has the following properties\n\n```\nrating: Float\nreason: String\n```\n\nThus we can build the rating object just by using a Builder Pattern.\n\n```kotlin\nval event = Rating.newBuilder()\n    .setRating(4.5)\n    .setReason(\"nice!\")\n    .build()\n\n// wrap event in CSEvent\nval csEvent = CSEvent(\n    guid = UUID.randomUUID().toString(),\n    timestamp = Timestamp.getDefaultInstance(),\n    message = event\n)\n\n// track the event\nClickStream.getInstance().trackEvent(csEvent)\n```\n\nCongratulations! You’re done!.\n\n#### Running Sample App\n\nIn order to running the sample app, please follow this instruction\n1. git clone git@github.com:gojekfarm/clickstream-android.git\n2. cd clickstream-android\n3. `./gradlew :app:installDebug` or via play button in the Android Studio\n\n| Figure 1 | Figure 2 |\n| ------ | ------ |\n| \u003cimg src=\"https://github.com/gojekfarm/clickstream-android/blob/main/docs/assets/clickstream_sample_1.jpg\" width=\"300\"/\u003e | \u003cimg src=\"https://github.com/gojekfarm/clickstream-android/blob/main/docs/assets/clickstream_sample_2.jpg\" width=\"300\"/\u003e |\n\n## Event Visualiser\n\nEvent visualiser is an android tool to visualise the client events being sent to Clickstream.\n\n### Adding dependency\nAdd following to your module's `build.gradle`.\n```kotlin\ndependencies {\n    val latest_version = \"x.y.z\"\n    implementation(\"com.gojek.clickstream:clickstream-event-visualiser:$latest_version\")\n    implementation(\"com.gojek.clickstream:clickstream-event-visualiser-ui:$latest_version\")\n}\n```\n### Initialising\n1. In your Application class, add `CSEventVisualiserListener` to Clickstream.\n2. Call `CSEventVisualiserUI.initialise(this)` to initialise Event visualiser.\n```kotlin\nclass App : Application() {\n    /**/\n    private fun initClickStream() {\n        ClickStream.initialize(/**/).apply {\n                /**/\n                addEventListener(CSEventVisualiserListener.getInstance())\n            }.build()\n        CSEventVisualiserUI.initialise(this)\n    }\n}\n```\n\n### Usage\n1. Call `CSEventVisualiserUI.getInstance().show()`to show a floating window and start recording all the events from clickstream.\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/ev_window.jpg\" width=\"300\"/\u003e\n\u003c/p\u003e\n\n2. Click on Settings icon (top-left corner) to show a bottom sheet with all the actions that you can take with event visualiser.\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/ev_actions.jpg\" width=\"300\"/\u003e\n\u003c/p\u003e\n\n- START CAPTURING (Starts event recording in event visualiser)\n- STOP CAPTURING (Stops event recording in event visualiser)\n- CLEAR DATA (Clears the current data in event visualiser)\n- CLOSE (Closes the event visualiser window)\n\n3. Clicking on the window will land to event home screen where all unique events are listed. You can click on any event to check event details.\n\n4. Events can have the following states -\n   * Scheduled - Events are scheduled (cached locally) by clickstream.\n   * Dispatched - Events are sent to racoon.\n   * Acknowledged - Events are acknowledged by racoon.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/ev_home.jpg\" width=\"300\"/\u003e\n\u003cimg src=\"https://github.com/gojek/clickstream-android/blob/main/docs/assets/ev_event_list.jpg\" width=\"300\"/\u003e\n\u003cimg src=\"https://github.com/gojekfarm/clickstream-android/blob/main/docs/assets/ev_event_detail.jpg\" width=\"300\"/\u003e\n\u003c/p\u003e\n\n### Excluding Event visualiser from release builds\nSince Event visualiser is a debug tool that will be used by developers and testing teams only, it should ideally **NOT** be bundled with release builds.  \nFor this purpose there are light-weight, alternative NoOp (No Operation) dependencies.\n\n#### Configuring NoOp dependency\n\n```kotlin\ndependencies {\n    val latest_version = \"x.y.z\"\n    // Use main dependency for debug build types\n    debugImplementation(\"com.gojek.clickstream:clickstream-event-visualiser:$latest_version\")\n    debugImplementation(\"com.gojek.clickstream:clickstream-event-visualiser-ui:$latest_version\")\n\n    // Use NoOp dependency for release build types\n    releaseImplementation(\"com.gojek.clickstream:clickstream-event-visualiser-noop:$latest_version\")\n    releaseImplementation(\"com.gojek.clickstream:clickstream-event-visualiser-ui-noop:$latest_version\")\n\n}\n```\n\nLicense\n--------\n    Copyright 2022 GOJEK\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgojek%2Fclickstream-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgojek%2Fclickstream-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgojek%2Fclickstream-android/lists"}