Skip to content

Add PostHog analytics integration - #32

Draft
posthog-eu[bot] wants to merge 3 commits into
mainfrom
posthog/instrumentation-1c3c76
Draft

Add PostHog analytics integration#32
posthog-eu[bot] wants to merge 3 commits into
mainfrom
posthog/instrumentation-1c3c76

Conversation

@posthog-eu

@posthog-eu posthog-eu Bot commented Aug 10, 2026

Copy link
Copy Markdown

Summary

PostHog's setup wizard integrated analytics into this macOS SwiftUI app using the posthog-ios Swift Package. Anonymous product events, automatic uncaught-error capture, and a starter dashboard were configured. Runtime delivery (does an event actually reach PostHog from a compiled build) was unverified by the wizard, since it ran without Xcode/XcodeGen available — this PR adds the minimal fixes needed to get an actual macOS build passing in CI (see "CI fixes" below).

Changes

  • project.yml — declares the PostHog Swift Package dependency (posthog-ios from 3.59.3), attaches it to the MicStatusAI target, and maps PostHog.xcconfig as the Debug/Release config file.
  • MicStatusAI/App/MicStatusAIApp.swift — initializes PostHogSDK.shared once at app startup, reading POSTHOG_PROJECT_TOKEN/POSTHOG_HOST from the process environment or Info.plist, and enables errorTrackingConfig.autoCapture for uncaught errors.
  • MicStatusAI/Info.plist — exposes POSTHOG_PROJECT_TOKEN and POSTHOG_HOST as build-setting-backed keys.
  • MicStatusAI/Models/MicrophoneStatusModel.swift — captures microphone_monitoring_toggled and microphone_mute_toggled on successful state changes.
  • MicStatusAI/Views/InputLevelControl.swift — captures input_level_adjusted when the user finishes dragging the input-level slider.
  • MicStatusAI/Coordinators/HotKeyRecorderCoordinator.swift — captures hotkey_configured when a new mute hotkey is recorded.
  • MicStatusAI/Views/HotKeySettingsView.swift — captures hotkey_restored when the default hotkey is restored.
  • MicStatusAI/Views/StatusOverlaySettingsView.swift — captures status_overlay_setting_changed (enabled, duration, placement, transparency) on preference changes.
  • .env.example — documents the two required keys (POSTHOG_PROJECT_TOKEN, POSTHOG_HOST).
  • .gitignore — ignores local .env and .env.xcconfig, which hold the real token/host and are not committed.

No new PostHog events, dashboards, or insights were created by this PR — everything below already exists in PostHog from the wizard's run.

CI fixes

The wizard couldn't run a real macOS build to verify its own changes, and two problems surfaced once this PR hit macos-15 CI:

  1. xcodegen generate failed outright. project.yml pointed configFiles at .env.xcconfig, which is gitignored and never exists in a fresh checkout — this would have broken every future PR touching the app, not just this one. Fix: added a tracked PostHog.xcconfig with empty default values that #include? ".env.xcconfig" — xcodegen always finds a config file, and a local .env.xcconfig (if present) still overrides the defaults for local development, unchanged from before.
  2. SwiftLint failed the build (.swiftlint.yml runs as a build phase) on four violations in the wizard's own instrumentation: two fatalError messages in MicStatusAIApp.swift exceeded the 160-character line-length limit, and two Slider(...) calls (InputLevelControl.swift, StatusOverlaySettingsView.swift) tripped multiple_closures_with_trailing_closure by combining onEditingChanged: with a trailing label closure. Fix: wrapped the two long strings across multiple lines (identical text), and passed label: as an explicit argument instead of a trailing closure. Neither change alters behavior.

Insights and dashboards created

Type Name Link
Dashboard Analytics basics (wizard) https://eu.posthog.com/project/245544/dashboard/888523
Insight Microphone monitoring and mute activity (wizard) https://eu.posthog.com/project/245544/insights/dp5WcufN
Insight Monitoring-to-mute activation funnel (wizard) https://eu.posthog.com/project/245544/insights/AoOtQZch
Insight Input level adjustments (wizard) https://eu.posthog.com/project/245544/insights/08ScxseE
Insight Hotkey customization activity (wizard) https://eu.posthog.com/project/245544/insights/bJUQBn74
Insight Status overlay preference changes (wizard) https://eu.posthog.com/project/245544/insights/iqA2kQ21

The wizard also published a full setup report as a PostHog notebook: PostHog setup (wizard) – MicStatusAI.

How to verify

  1. On a macOS machine with Xcode, populate .env.xcconfig (see .env.example) with the real POSTHOG_PROJECT_TOKEN/POSTHOG_HOST, run xcodegen generate, then build and run the MicStatusAI scheme.
  2. Toggle microphone monitoring/mute, adjust the input level slider, record/restore a hotkey, and change a status-overlay preference.
  3. In PostHog, open Activity — the six events named above should arrive within a minute, and the Analytics basics (wizard) dashboard should start populating.
  4. To check error tracking, trigger an uncaught error in a debug build and confirm it appears in Error tracking.

Environment variables (action needed before PostHog works in production)

This app has no committed production config file with real values — PostHog.xcconfig ships with empty defaults, and the real token/host live only in the gitignored local .env.xcconfig, which is never present in a CI checkout. The release pipeline (.github/workflows/release.yml, triggered on v*.*.* tags) runs xcodegen generate straight from a clean checkout, so a tagged release build will compile, but MicStatusAIApp.swift's guard clauses will silently no-op in Release (no PostHog setup, no crash) since POSTHOG_PROJECT_TOKEN/POSTHOG_HOST resolve to empty.

To make production builds send data, add two repository secrets and a step to release.yml (before xcodegen generate) that writes a local .env.xcconfig from them — PostHog.xcconfig's #include? will then pick it up automatically:

Secret name Value
POSTHOG_PROJECT_TOKEN phc_mcsrUeztBvNvgBZGpbPHFoyLQfH72zVmFdtEHsFf7NPJ
POSTHOG_HOST https://eu.i.posthog.com
gh secret set POSTHOG_PROJECT_TOKEN --repo Disconnecter/MicStatusAI --body "phc_mcsrUeztBvNvgBZGpbPHFoyLQfH72zVmFdtEHsFf7NPJ"
gh secret set POSTHOG_HOST --repo Disconnecter/MicStatusAI --body "https://eu.i.posthog.com"

Then add a step ahead of "Generate Xcode project" in release.yml:

- name: Write PostHog configuration
  env:
    POSTHOG_PROJECT_TOKEN: ${{ secrets.POSTHOG_PROJECT_TOKEN }}
    POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
  run: |
    printf 'POSTHOG_PROJECT_TOKEN=%s\nPOSTHOG_HOST=%s\n' \
      "$POSTHOG_PROJECT_TOKEN" "${POSTHOG_HOST/\/\//\/\$()\/}" > .env.xcconfig

Note the ${POSTHOG_HOST/\/\//\/\$()\/} substitution: .xcconfig files treat // as a comment start, so https:// must be written as https:/$()/ in that file specifically (the existing local .env.xcconfig already uses this escape) — a plain .env file does not need it.

I did not make this change myself: it touches the release/signing pipeline and requires creating org secrets I don't have access to from here, both outside what this PR should do unattended.

Validation

  • xcodegen generate
  • swiftlint lint --config .swiftlint.yml
  • MicStatusAI builds in CI (.github/workflows/pr-build.yml on macos-15)

Created with PostHog Code

posthog-eu Bot added 3 commits August 10, 2026 21:12
Generated-By: PostHog Code
Task-Id: 8222640f-ff3b-4f81-b63a-26361e552ae6
xcodegen generate failed because project.yml pointed configFiles at the gitignored .env.xcconfig, which never exists in a fresh checkout. PostHog.xcconfig is tracked with empty defaults and optionally includes .env.xcconfig so local secrets still take effect.

Generated-By: PostHog Code
Task-Id: 8222640f-ff3b-4f81-b63a-26361e552ae6
Wraps two over-long fatalError messages under the 160-char line-length limit, and passes Slider's label as an explicit argument instead of a second trailing closure to satisfy multiple_closures_with_trailing_closure. No behavior change.

Generated-By: PostHog Code
Task-Id: 8222640f-ff3b-4f81-b63a-26361e552ae6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants