Beacon C++ SDK

The Beacon C++ SDK provides native integration for Windows desktop applications, server processes, and cross-platform C++ projects.

Installation

Add Beacon to your CMakeLists.txt:

include(FetchContent)
FetchContent_Declare(
  beacon_sdk
  GIT_REPOSITORY https://github.com/softagility/beacon-sdk-cpp.git
  GIT_TAG        v1.0.1
)
FetchContent_MakeAvailable(beacon_sdk)
 
target_link_libraries(your_app PRIVATE beacon_sdk)

Build from Source

git clone https://github.com/softagility/beacon-sdk-cpp.git
cd beacon-sdk-cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

Dependencies (libcurl, nlohmann_json, SQLite3) are fetched automatically via CMake FetchContent if not found on the system.

vcpkg

A vcpkg port is planned for a future release. For now, use CMake FetchContent or build from source.

System Requirements

  • C++17 or later
  • Windows 10+, Linux (glibc 2.28+), or macOS 12+
  • CMake 3.25+
  • libcurl, nlohmann_json, SQLite3 — resolved automatically by CMake FetchContent if not present
  • OpenSSL development headers — required on Linux and macOS via find_package(OpenSSL). On Windows, TLS uses Schannel and no extra dependency is needed.

The SDK selects the TLS backend based on platform: Schannel on Windows, OpenSSL on Linux and macOS.

Configuration

#include <beacon/beacon.hpp>
 
int main()
{
    auto tracker = beacon::Tracker::configure([](beacon::Options& opts) {
        opts.api_key = "your-api-key";
        opts.api_base_url = "https://api.beacon.softagility.com";
        opts.app_name = "MyApp";
        opts.app_version = "1.2.0";
    });
 
    tracker->identify("user-123");
    tracker->startSession();
 
    // Your application code here...
 
    tracker->endSession();
    return 0;
}

You can also pass an Options struct directly:

beacon::Options opts;
opts.api_key = "your-api-key";
opts.api_base_url = "https://api.beacon.softagility.com";
opts.app_name = "MyApp";
opts.app_version = "1.2.0";
 
auto tracker = beacon::Tracker::configure(opts);

Configuration Options

OptionTypeDefaultDescription
api_keystd::stringYour Beacon API key (required)
api_base_urlstd::stringBeacon API base URL (required)
app_namestd::stringYour product’s slug as registered in the Beacon dashboard (e.g., "inventory-manager"). Must match exactly or events are rejected with UNRECOGNIZED_PRODUCT. (required)
app_versionstd::stringYour application’s version string. (required)
enabledbooltrueEnable or disable tracking globally
flush_interval_secondsint60Batch send interval in seconds (1-3600)
max_batch_sizeint25Events per batch, clamped to 1-1000
max_queue_size_mbint10Maximum offline queue size in MB (1-1000)
max_breadcrumbsint25Breadcrumb ring buffer size (0-200)
loggerstd::shared_ptr<beacon::ILogger>nullptrOptional logger for SDK diagnostics
eventsEventDefinitionBuilderBuilder for registering known event categories and names. Optional; populated via tracker->exportEventManifest().

Identifying Users

Before tracking events or sessions, identify the current actor:

tracker->identify("user-123");

Once identified, all subsequent calls use this actor. You can also pass an explicit actor ID to tracking methods.

Tracking Events

Events are organized by category and name, with optional properties.

Basic Event

Properties are passed as std::unordered_map<std::string, std::string>. The C++ API doesn’t accept braced initializer lists directly — wrap explicitly:

tracker->track("ui", "button_clicked",
    std::unordered_map<std::string, std::string>{
        {"button_name", "export"},
        {"screen", "dashboard"}
    });

With Explicit Actor

tracker->track("reports", "report_exported", "user-456",
    std::unordered_map<std::string, std::string>{
        {"format", "pdf"},
        {"row_count", "1500"}
    });

Session Management

// Start a session (uses the identified actor)
tracker->startSession();
 
// Or start with an explicit actor ID
tracker->startSession("user-123");
 
// End the current session
tracker->endSession();

Exception Tracking

Track exceptions with severity levels. Breadcrumbs from recent track() calls are attached automatically.

try
{
    process_order(order);
}
catch (const std::exception& ex)
{
    tracker->trackException(ex, beacon::ExceptionSeverity::NonFatal);
    throw;
}

Severity options: beacon::ExceptionSeverity::Fatal and beacon::ExceptionSeverity::NonFatal.

Flushing Events

Events are batched and sent on a timer or when the batch size is reached. To flush manually:

bool success = tracker->flush(); // Blocks up to 30 seconds

Check the last flush result:

beacon::FlushStatus status = tracker->last_flush_status();

Offline Persistence

Events are persisted to a local SQLite database when the network is unavailable. The queue syncs automatically when connectivity returns.

  • Persists across application restarts
  • Thread-safe queue with a configurable size limit (max_queue_size_mb)
  • Best-effort durable retry: events are retained through transient network failures, but if the queue reaches the configured cap, the oldest events are evicted. Permanent HTTP errors (non-retriable 4xx other than 401/402/429) discard the affected events.
  • Call tracker->flush() at shutdown to deliver pending events before the process exits.

Privacy Controls

The SDK supports opt-out and opt-in for user consent:

tracker->opt_out();   // stops tracking, clears queue
tracker->opt_in();    // resumes tracking

Opt-out state persists across application restarts via the offline-persistence database.

Reset

Clear all in-memory state (session, queue, breadcrumbs, actor ID) and generate a new anonymous device ID:

tracker->reset();

Use this on logout to separate user sessions.

Event Manifest

Register known events for import into the Beacon portal’s allowlist:

tracker->exportEventManifest("events.json");

Singleton Access

After calling configure(), retrieve the tracker instance anywhere with:

auto tracker = beacon::Tracker::instance();

Call beacon::Tracker::reset_for_testing() in test teardown to clear the singleton.

Thread Safety

beacon::Tracker is fully thread-safe. Share a single instance across threads.

Lifetime Management

configure() stores the tracker in an internal static shared_ptr, so a local auto tracker going out of scope does not destroy the tracker — it only releases your local reference. The destructor (when it eventually runs) persists in-memory events to disk and joins worker threads, but does not perform a network flush, end the active session, or send any final HTTP requests.

To shut down cleanly, call endSession() and flush() explicitly before your application exits:

auto tracker = beacon::Tracker::configure(configurator);
tracker->identify("user-123");
tracker->startSession();
 
// Track events...
 
// Explicit shutdown
tracker->endSession();
tracker->flush();   // blocks up to 30s waiting for the network round-trip

Without an explicit flush(), in-memory events are persisted to disk and delivered on the next session.

Next Steps