private/core-analytics/Send-RecastOSDeployEvent.ps1


    function Send-RecastOSDeployEvent {
        <#
        .SYNOPSIS
        Sends an OSDeploy analytics event to PostHog
 
        .DESCRIPTION
        Builds a compact JSON capture payload containing the PostHog project API key,
        event name, caller-supplied properties, an ISO 8601 timestamp with the local
        system offset, and a distinct identifier. The identifier is an unsalted SHA-256
        hash of the local Win32_ComputerSystemProduct UUID. A newly generated GUID is
        used when the hash is empty.
 
        The function adds distinct_id to the supplied property set and sends the payload
        to the PostHog capture endpoint over HTTPS with a two-second timeout and no
        retry. The REST response is suppressed. Payload or request failures are written
        to the verbose stream and are not rethrown. Device UUID retrieval and hashing
        occur before that error handler and can produce a terminating error.
 
        .PARAMETER EventName
        Specifies the event name sent to PostHog. Default is RecastOSDeploy-dev.
 
        .PARAMETER ApiKey
        Specifies the PostHog project API key included in the capture payload. Default
        is the OSDeploy PostHog project key defined by this function.
 
        .PARAMETER Properties
        Specifies event properties to include in the payload. The function combines this
        hashtable with a generated distinct_id property before submission. Do not supply
        distinct_id because duplicate keys cause payload construction to fail.
 
        .EXAMPLE
        PS> Send-RecastOSDeployEvent -EventName 'Build-OSDeployBoot' -Properties @{ BootGuid = '4f8da130-8b4d-4d62-9b37-28b72462dc4d' } -Verbose
 
        Sends a Build-OSDeployBoot event with the supplied build identifier and writes
        verbose success or request-failure status.
 
        .INPUTS
        None. This function does not accept pipeline input.
 
        .OUTPUTS
        None.
 
        .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-09-03
 
        Requires Get-CimInstance, access to Win32_ComputerSystemProduct, and network
        access to https://us.i.posthog.com/capture/. The device hash is a stable,
        pseudonymous identifier rather than anonymous data. The function does not prompt
        for consent or provide an analytics opt-out.
        #>

        param(
            [Parameter()]
            [string]$EventName = 'RecastOSDeploy-dev',
            [Parameter()]
            [string]$ApiKey = 'phc_2h7nQJCo41Hc5C64B2SkcEBZOvJ6mHr5xAHZyjPl3ZK',
            [Parameter()]
            [hashtable]$Properties
    )
    #=================================================
    # Unique identifier for this device, used for telemetry and license enforcement
    $deviceUUID = (Get-CimInstance -ClassName Win32_ComputerSystemProduct).UUID
    # Convert the UUID to a hash value to protect user privacyand ensure a consistent identifier across events
    $deviceUUIDHash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($deviceUUID))).Replace("-", "")
    if (-not [string]::IsNullOrWhiteSpace($deviceUUIDHash)) {
        [string]$distinctId = $deviceUUIDHash
    }
    else {
        [string]$distinctId = [System.Guid]::NewGuid().ToString()
    }


    try {
        $payload = [ordered]@{
            api_key    = $ApiKey
            event      = $EventName
            properties = $Properties + @{
                distinct_id = $distinctId
            }
            timestamp  = (Get-Date).ToString('o')
        }

        $body = $payload | ConvertTo-Json -Depth 4 -Compress
        Invoke-RestMethod -Method Post `
            -Uri 'https://us.i.posthog.com/capture/' `
            -Body $body `
            -ContentType 'application/json' `
            -TimeoutSec 2 `
            -ErrorAction Stop | Out-Null

        Write-Verbose "[$($MyInvocation.MyCommand.Name)] [OSDeploy] Event sent: $EventName"
    }
    catch {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] [OSDeploy] Failed to send event: $($_.Exception.Message)"
    }
}