Chapter 150 · LLM Analytics Setup
Subchapter 150.5
references/calculating-costs.mdMarkdown8 KBView on GitHub
PostHog calculates cost based on the number of input (prompt) and output (completion) tokens generated by specific AI models, plus additional cost components like per-request and per-web-search pricing when applicable.
We use OpenRouter’s pricing data as our primary source to match your model and calculate costs. OpenRouter provides comprehensive pricing information for models across different providers, and we use both the $ai_provider and $ai_model properties from your events to find the exact pricing.
If OpenRouter doesn’t have pricing data for a specific model, we fall back to our manually maintained pricing database for additional model support.
The total cost ($ai_total_cost_usd) is calculated from multiple components:
For cached LLM responses, our pricing models include cached token pricing which we automatically apply.
We also take into account the reasoning / thinking tokens for models that support it.
Different LLM providers report cache tokens differently:
$ai_input_tokens. For example, if you have 100 input tokens and 50 cached tokens, $ai_input_tokens is 100.$ai_input_tokens. Using the same example, $ai_input_tokens is 150.PostHog auto-detects which counting style to use based on the $ai_provider and $ai_model properties. For Anthropic and Claude models, PostHog assumes exclusive counting. For all other providers, it assumes inclusive counting.
If you’re manually capturing events or using a framework wrapper that normalizes token counts differently, override the auto-detection by setting the $ai_cache_reporting_exclusive property:
$ai_cache_reporting_exclusive: true - Cache tokens are separate from input tokens (Anthropic-style)$ai_cache_reporting_exclusive: false - Input tokens already include cache tokensWhen not set, PostHog resolves this automatically and writes the resolved value back to the event for downstream consumers.
You can override PostHog’s automatic cost calculation by providing custom pricing for your LLM models. This is useful when:
If you know your pricing per token, you can set the following custom properties (opens in a new tab) when calling your LLM:
$ai_input_token_price (required): Price per input/prompt token$ai_output_token_price (required): Price per output/completion token$ai_cache_read_token_price (optional): Price per cached token read$ai_cache_write_token_price (optional): Price per cached token write$ai_request_price (optional): Price per request (for models that charge per request)$ai_web_search_price (optional): Price per web search (for models that charge per search)Important: Token prices should be per individual token, not per million tokens. For example, if your provider charges $0.03 per 1M tokens, you would set $ai_input_token_price: 0.00000003 (0.03 / 1,000,000).
PostHog AI
import { OpenAI } from '@posthog/ai'
import { PostHog } from 'posthog-node'
const phClient = new PostHog(
'<ph_project_token>',
{ host: 'https://us.i.posthog.com' }
)
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
posthog: phClient
})
const response = await openai.responses.create({
model: 'my-custom-model',
messages: [{ role: 'user', content: 'Hello' }],
posthogProperties: {
$ai_input_token_price: 0.00000003, // $0.03 per 1M tokens = $0.00000003 per token
$ai_output_token_price: 0.00000006, // $0.06 per 1M tokens = $0.00000006 per token
// Optional: cache pricing
$ai_cache_read_token_price: 0.000000015,
$ai_cache_write_token_price: 0.0000000375
}
})from posthog.ai.openai import OpenAI
from posthog import Posthog
posthog = Posthog(
"<ph_project_token>",
host="https://us.i.posthog.com"
)
client = OpenAI(
api_key="sk-...",
posthog_client=posthog
)
response = client.responses.create(
model="my-custom-model",
messages=[{"role": "user", "content": "Hello"}],
posthog_properties={
"$ai_input_token_price": 0.00000003, # $0.03 per 1M tokens = $0.00000003 per token
"$ai_output_token_price": 0.00000006, # $0.06 per 1M tokens = $0.00000006 per token
# Optional: cache pricing
"$ai_cache_read_token_price": 0.000000015,
"$ai_cache_write_token_price": 0.0000000375
}
)Both $ai_input_token_price and $ai_output_token_price must be provided for custom pricing to take effect. PostHog will then calculate the total cost based on the token counts and your custom prices.
If you’re manually capturing (opens in a new tab) LLM events and have already calculated the total costs yourself, you can send them directly:
$ai_input_cost_usd: Total cost for input/prompt tokens in USD$ai_output_cost_usd: Total cost for output/completion tokens in USD$ai_request_cost_usd: Total cost for requests in USD$ai_web_search_cost_usd: Total cost for web searches in USDPostHog AI
// After making your LLM call and calculating costs
posthog.capture('$ai_generation', {
$ai_trace_id: traceId,
$ai_model: 'my-custom-model',
$ai_provider: 'my-provider',
$ai_input_tokens: inputTokens,
$ai_output_tokens: outputTokens,
$ai_input_cost_usd: 0.0042,
$ai_output_cost_usd: 0.0028
// ... other required properties
})# After making your LLM call and calculating costs
posthog.capture(
event='$ai_generation',
properties={
'$ai_trace_id': trace_id,
'$ai_model': 'my-custom-model',
'$ai_provider': 'my-provider',
'$ai_input_tokens': input_tokens,
'$ai_output_tokens': output_tokens,
'$ai_input_cost_usd': 0.0042,
'$ai_output_cost_usd': 0.0028
# ... other required properties
}
)PostHog will use these values directly without any additional calculation.
Cost calculation follows this precedence order:
$ai_input_cost_usd, $ai_output_cost_usd, $ai_request_cost_usd, $ai_web_search_cost_usd): These values are used directly without any additional calculation$ai_input_token_price, $ai_output_token_price, $ai_request_price, $ai_web_search_price): PostHog calculates costs from token counts and usage metrics using your custom pricesWhen PostHog calculates costs automatically, it sets the following metadata properties on the event to help you understand how costs were determined:
| Property | Description | Examples |
|---|---|---|
| $ai_model_cost_used | The model identifier used for cost calculation. May differ from the requested model when a variant or alias is resolved. | openai/gpt-4o-mini |
| $ai_cost_model_source | Where the cost data for this model was sourced from. | openrouter, manual, custom, passthrough |
| $ai_cost_model_provider | The provider used to look up the cost for this model. | openai, anthropic, custom |
These properties are useful for debugging cost discrepancies or understanding which pricing was applied when using model aliases or custom configurations.
You can find the code for this on GitHub (opens in a new tab).
Ask a question
HelpfulCould be better