Lightweight C++ SDK for PostHog analytics with crash reporting.
Cross-platform: macOS (arm64, x86_64), Windows (x64, x86, arm64), Linux (x86_64, aarch64)
include(FetchContent)
FetchContent_Declare(
posthog
GIT_REPOSITORY https://github.com/bskl-xyz/posthog-cpp.git
GIT_TAG main
)
# Disable bundled curl if your project already provides it
set(POSTHOG_USE_CURL OFF CACHE INTERNAL "")
FetchContent_MakeAvailable(posthog)
target_link_libraries(your_app PRIVATE posthog)#include <posthog/posthog.h>
int main() {
PostHog::Config config;
config.apiKey = "phc_xxx";
config.appName = "MyApp";
config.appVersion = "1.0.0";
config.host = "https://us.i.posthog.com"; // or https://eu.i.posthog.com
PostHog::Client client(config);
client.initialize();
// Track events
client.track("app_started", {
{"feature", "analytics"}
});
// Track exceptions (captures stack trace with function names)
try {
riskyOperation();
} catch (const std::exception& e) {
client.trackException("RuntimeError", e.what(), "component_name");
}
client.shutdown();
return 0;
}- Event tracking — custom events with properties
- Exception tracking — captures stack traces at runtime (function names resolved)
- Crash reporting — intercepts SIGSEGV, SIGABRT, SIGBUS, SIGFPE, SIGILL (signal-safe)
- Machine ID — unique anonymous identifier per device
- Async queue — non-blocking event dispatch with background thread
- Bundled dependencies — nlohmann/json included, libcurl optional
Crash handler saves stack trace to disk during crash (network unavailable in signal handlers). On next app launch, the report is sent to PostHog.
PostHog::Client client(config);
client.initialize();
// Install crash handler (uses default directory based on config.appName)
client.installCrashHandler();
// Or specify custom directory (must exist or parent must exist)
client.installCrashHandler("/path/to/crash/dir");
// Optional: add metadata for crash reports
client.setCrashMetadata({
{"build_id", "abc123"},
{"license_type", "pro"},
{"last_action", "importing_file"}
});Based on config.appName:
| Platform | Path |
|---|---|
| Windows | %APPDATA%\{appName}\CrashReports |
| macOS | ~/Library/Application Support/{appName}/CrashReports |
| Linux | ~/.local/share/{appName}/crash_reports |
- Crash occurs → signal handler saves raw addresses to
pending_crash.txt - Next launch →
installCrashHandler()detects the file and sends$exceptionevent - PostHog → shows crash in Error Tracking
Crash stack traces contain only memory addresses. To get function names and line numbers:
python scripts/symbolize.py \
--executable /path/to/MyApp \
--load-address 0x104504000 \
--addresses 0x104507698 0x104505bf4 0x104506a10Requirements:
- Original executable (same build that crashed)
- Debug symbols:
.dSYM(macOS),.pdb(Windows), or debug build (Linux) - Load address from crash report (
load_addressproperty in PostHog)
Output:
0x104507698 -> main (main.cpp:42)
0x104505bf4 -> processData (processor.cpp:128)
trackException() |
Crash Handler | |
|---|---|---|
| When | Runtime (try/catch) | Signal (SIGSEGV, etc.) |
| Function names | ✅ Resolved | ❌ Addresses only |
| Line numbers | ❌ No | ❌ No (needs symbolization) |
| Sent immediately | ✅ Yes | ❌ Next launch |
By default, posthog-cpp sends:
- Events you explicitly track via
track()andtrackException() - OS info — platform, architecture, OS version (e.g., "Mac OS X arm64 15.5")
- Machine ID — SHA256 hash of MAC address, used as
distinct_id - Crash reports — signal name, stack trace addresses, exception codes
- SDK version —
posthog_cpp_versionproperty
The library does not access files, projects, screen content, or keystrokes.
Users can disable all analytics by creating an empty file:
When this file exists, initialize() sets enabled = false and no events are sent.
You can also disable analytics programmatically:
config.enabled = false; // at init time
client.setEnabled(false); // at runtimeIf you distribute software that uses posthog-cpp, you are the data controller under GDPR. This means:
- Disclose what you collect — add a privacy section to your product page or documentation
- Provide opt-out — the
~/.posthog_optoutmechanism is available, mention it in your docs - Minimize data — only track what you need; avoid sending personal information (usernames, emails) as event properties
- MAC-based machine ID is a pseudonymized hardware identifier (GDPR Article 4(5)) — it's still considered personal data. Consider using
config.distinctIdwith a random persistent UUID if you want to avoid hardware fingerprinting - Crash reports typically fall under "legitimate interest" (GDPR Article 6(1)(f)), but disclosure is still recommended
Example privacy notice for your product:
This software collects anonymous usage analytics (launches, crashes, OS version) to improve stability. No personal files or project data is accessed. Data is processed via PostHog (EU servers, GDPR compliant). To disable, create an empty file at
~/.posthog_optout.
Visual Studio 2022 v17.10 introduced a breaking change with std::mutex. The library includes a workaround, but it may not work in all scenarios (including GitHub Actions).
Workaround: Add to your project:
target_compile_definitions(your_app PRIVATE _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)If your project already uses libcurl, disable bundled curl:
set(POSTHOG_USE_CURL OFF CACHE INTERNAL "")
FetchContent_MakeAvailable(posthog)The library will use whichever curl target is available (libcurl_static or CURL::libcurl).
See include/posthog/posthog.h for full API (Doxygen comments).
Main classes:
PostHog::Config— client configurationPostHog::Client— analytics client
Header-only utilities:
posthog/machine_id.h— cross-platform machine IDposthog/stacktrace.h— stack trace captureposthog/crash_handler.h— signal handler
See LICENSE
If you appreciate this free software and would like to leave a donation, you can do so here (adjust the quantity to change the $ amount)!
Note: PostHog is a trademark of PostHog Inc. This library is not affiliated with, endorsed by, or sponsored by PostHog Inc.
