Tools And Features Hogql
PostHogOfficialCreated by PostHog
- Skill
- Tool integration
- Data and AI
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
HogQL is PostHog's SQL dialect, designed as a wrapper around ClickHouse SQL to simplify data access and analytics within the PostHog platform. This skill provides the essential reference material for constructing queries, including how to access event and person properties, utilize PostHog-specific functions, and integrate UI-based filters into your SQL insights. It emphasizes performance and efficiency, offering guidelines on aggregation, time-range filtering, and query structure to help users build effective analytics dashboards.
What it does
- Provides syntax patterns for querying events, persons, and sessions.
- Explains how to access event and person properties using specific dot notation.
- Details the use of the {filters} placeholder for dynamic dashboard filtering.
- Lists supported ClickHouse functions and aggregation methods for data analysis.
- Offers performance optimization tips like using uniq() over count(distinct).
- Provides guidance on using cohort and action-based filtering in SQL.
When to use it
- When you need to create custom SQL insights in PostHog.
- When you want to perform complex data analysis beyond standard UI-based reports.
- When you need to optimize existing queries for better performance.
- When you are building dashboards that require dynamic date ranges or user-defined filters.
Advantages
- Simplifies complex ClickHouse SQL for common analytics tasks.
- Enables seamless integration with PostHog's UI-based filtering system.
- Provides access to specialized PostHog functions like windowFunnel and sequenceMatch.
- Promotes efficient query patterns to reduce load on the underlying database.
Usage examples
- “Write a HogQL query to count pageviews by browser.”
- SELECT properties.$browser AS browser, count() FROM events WHERE event = '$pageview' AND {filters} GROUP BY browser
- “How do I count unique users in a HogQL query?”
- Use the uniq() function instead of count(distinct) for better performance, for example: SELECT uniq(person_id) FROM events WHERE {filters}
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/posthog/tools-and-features-hogql/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip tools-and-features-hogql.zip -d .agents/skills
Documentation by PostHog
HogQL queries for PostHog
This skill helps you write HogQL queries for PostHog analytics. HogQL is PostHog's SQL dialect, a wrapper around ClickHouse SQL with simplified property access and PostHog-specific functions.
Reference files
references/expressions.md- Sql expressions - docsreferences/aggregations.md- Supported aggregations - docsreferences/clickhouse-functions.md- Supported clickhouse functions - docsreferences/data-access.md- Accessing data using sql - docsreferences/variables.md- Sql variables - docsreferences/useful-functions.md- Useful sql functions - docsreferences/posthog.md- PostHog table schemas (events, persons, groups, sessions)references/sessions.md- Sessions - docs
Consult the documentation for SQL syntax, available functions, and query patterns.
Key principles
Property access: Use
properties.$property_namefor event properties andperson.properties.$property_namefor person propertiesNull handling: HogQL has simplified null handling compared to raw ClickHouse SQL
Filters placeholder: Use
{filters}in queries to allow UI-based filtering in PostHog dashboardsAggregations: Prefer ClickHouse aggregation functions like
count(),uniq(),avg(),sum()
Common patterns
Event queries
SELECT event, count()
FROM events
WHERE {filters}
GROUP BY event
ORDER BY count() DESCProperty breakdowns
SELECT properties.$browser AS browser, count()
FROM events
WHERE event = '$pageview' AND {filters}
GROUP BY browserPerson properties
SELECT person.properties.email, count()
FROM events
WHERE {filters}
GROUP BY person.properties.emailFramework guidelines
Use properties.$name syntax for event properties, person.properties.$name for person properties
Use bracket notation for special characters like properties['$feature/cool-flag']
For cohorts, filter with person_id IN COHORT 'cohort-name'
For actions, use matchesAction('action-name') in WHERE clauses
Include {filters} placeholder in WHERE clauses to enable UI-based filtering in dashboards
Use {variables.name} for reusable SQL variables across dashboards
Access dashboard date range with {filters.dateRange.from} and {filters.dateRange.to}
ALWAYS include a time range filter - shorter is faster (e.g., timestamp >= now() - INTERVAL 7 DAY)
Prefer uniq() over count(distinct) for counting unique values - it's more efficient
Don't scan the same table multiple times - use materialized views for reusable subsets
Use timestamp-based pagination instead of OFFSET for large datasets
Name queries descriptively for easier debugging in query_log
Use dateTrunc() for time-based grouping (e.g., dateTrunc('day', timestamp))
For funnel queries, use windowFunnel() or sequenceMatch() functions
Test queries in the PostHog SQL editor before using them in insights or the API
Files
- ATTRIBUTION.mdAdded by AutoGineer972 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md3.0 KiB
- references/aggregations.md3.8 KiB
- references/clickhouse-functions.md12.3 KiB
- references/data-access.md4.4 KiB
- references/expressions.md7.8 KiB
- references/posthog.md13.3 KiB
- references/sessions.md12.5 KiB
- references/useful-functions.md13.1 KiB
- references/variables.md2.8 KiB
references/useful-functions.md
Useful SQL functions - Docs
Our SQL flavor includes many functions to aggregate and manipulate queried data. Below are some examples of some of the most popular SQL functions you can use in your insights.
Aggregate functions
These aggregate results for columns across all rows. They include:
avg(): Calculates the average numeric value of a column.sum(): Calculates the total (sum) numeric value of a column.max(),min(): Finds the maximum or minimum value of a column.
SQL
PostHog AI
SELECT
avg(properties.$screen_height),
sum(properties.$screen_height),
max(properties.$screen_height),
min(properties.$screen_height)
FROM events
WHERE event = '$pageview' AND properties.$screen_height IS NOT NULLYou can find a full list of these in supported aggregations.
Count
Use count() to count the number of rows in a particular column. count(*) counts all rows, while count(column_name) counts the number of non-null values in a column.
Regular functions
Our SQL flavor provides many functions for accessing, modifying, and calculating data from queries. Along with the ones listed below, many basics include calculation operators (+, -, /, *), type conversions (toInt, toString), conditional statements (if, multiIf), and rounding (floor, round).
You can find a full list of these in supported ClickHouse functions.
Date and time
now(),today(),yesterday(): Returns the current time, date, or yesterday’s date respectively.interval: A length of time for use in arithmetic operations with other dates and times.toDayOfWeek,toHour,toMinute: Converts date number of day of week (1-7), hour in 24-hour time (0-23), and minute in hour (0-59).toStartOfYear,toStartOfMonth,toMonday,toStartOfDay,toStartOfMinute: rounds date down to the nearest year, month, Monday, day, hour, or minute respectivelydateDiff('unit', startdate, enddate): Returns the count inunitbetweenstartdateandenddate.formatDateTime: Formats a time according to a MySQL datetime format string.parseDateTimeBestEffort: Converts most human-readable dates into a datetime.
SQL
PostHog AI
SELECT
formatDateTime(now(), '%a %b %T') AS current_time,
toDayOfWeek(now()) AS current_day_of_week,
dateDiff('day', timestamp, now()) AS days_since_event,
parseDateTimeBestEffort('4-Dec-2023') AS converted_date
FROM events
WHERE timestamp > now() - interval 1 dayIf you want to access dashboard or insight date filters, you can use the variables filters.dateRange.from and filters.dateRange.to.
Read more examples in How to do time-based breakdowns (hour, minute, real time) and Using SQL for advanced time and date filters.
String
extract: Extracts a fragment of a string using a regular expression.concat: Concatenates strings listed without separator.splitByChar,splitByString,splitByRegexp,splitByWhitespace: splits a string into substring separated by a specified character, string, regular expression, or whitespace character respectively.match: Return whether the string matches a regular expression pattern.replaceOne,replaceRegexpOne: Replace the first occurrence of matching a substring or regular expression pattern respectively with a replacement string.trim: Remove specified characters (or whitespace) from the start or end of a string.upper,lower: Converts a string to uppercase or lowercase.
SQL
PostHog AI
select
extract(elements_chain, '[:|"]attr__class="(.*?)"') as class_name,
concat(properties.$os, ' version: ', properties.$os_version),
replaceRegexpOne(properties.$current_url, '^/', 'site/') AS modified_current_url
from events
where event = '$autocapture'Read more in How to analyze autocapture events with SQL.
JSON
You can access nested data in JSON and objects directly.
SQL
PostHog AI
select properties.$set.$geoip_country_name
from eventsYou can parse JSON with JSONExtractRaw() to return a value.
SQL
PostHog AI
SELECT
JSONExtractRaw(properties.$set) as set_properties
FROM events
WHERE properties.$set IS NOT NULLSpecialized JSONExtract functions exist for different data types including:
JSONExtractFloatJSONExtractArrayRawJSONExtractStringJSONExtractBool
Array
arrayElement(arr, n): Retrieves the element with the index of n from the arrayarr.arrayJoin(arr): Takes a row and generates multiple rows for the number of elements in the array. It copies all the column values, except the column where this function is applied. It replaces the applied column with the corresponding array value.
SQL
PostHog AI
SELECT flag, count()
FROM (
SELECT arrayJoin(JSONExtractArrayRaw(assumeNotNull(properties.$active_feature_flags))) as flag
FROM events
WHERE event = '$pageview' and timestamp > '2023-08-01'
)
GROUP BY flag
ORDER BY count() descRead more in How to filter and breakdown arrays with SQL.
Sparkline
A sparkline is a tiny graph contained in one cell of your query result. As an argument, it takes an array of integers.
SQL
PostHog AI
SELECT sparkline(range(1, 10)) FROM (SELECT 1)You can use it to visualize queries, such as a 24-hour $pageview count for different $current_url values.
SQL
PostHog AI
SELECT
pageview,
sparkline(arrayMap(h -> countEqual(groupArray(hour), h), range(0,23))),
count() as pageview_count
FROM
(
SELECT
properties.$current_url as pageview,
toHour(timestamp) AS hour
FROM
events
WHERE
timestamp > now () - interval 1 day
and event = '$pageview'
) subquery
GROUP BY
pageview
ORDER BY
pageview_count descYou can also use it for art.
SQL
PostHog AI
select
sparkline(arrayMap(a -> cos(toSecond(timestamp) + a/4), range(100 + 5 * toSecond(timestamp))))
from eventsSemVer
If you have a SemVer version number, you can use the sortableSemVer() function to get a version number that you can use for sorting purposes.
SELECT DISTINCT properties.$lib_version FROM events WHERE event = '$pageview' AND timestamp >= now() - INTERVAL 1 DAY ORDER BY sortableSemVer(properties.$lib_version) DESC LIMIT 10
Session replays
You can create a button to view the replay for a session by using the recordingButton() function with the session_id. For example, to get a list of recent replays, you can use:
SQL
PostHog AI
SELECT
person.properties.email,
min_first_timestamp AS start,
recordingButton(session_id)
FROM
raw_session_replay_events
WHERE
min_first_timestamp >= now() - INTERVAL 1 DAY
AND min_first_timestamp <= now()
ORDER BY
min_first_timestamp DESC
LIMIT 10Actions
You can use actions in SQL by using the matchesAction() function with the name of your action. For example, to get a count of the action clicked homepage button, you can do:
SQL
PostHog AI
SELECT count()
FROM events
WHERE matchesAction('clicked homepage button')Translation
You can translate a language code to a language name using the languageCodeToName() function. You can see what the mapping looks like in our codebase
SQL
PostHog AI
SELECT
languageCodeToName('en') AS english, -- English
languageCodeToName('fr') AS french, -- French
languageCodeToName('pt') AS portuguese, -- Portuguese
languageCodeToName('ru') AS russian, -- Russian
languageCodeToName('zh') AS chinese -- ChineseHTML tags and links
These HTML tags are currently supported, but for security reasons, none of them support attributes right now:
<div>,<p>,<span>,<pre>,<code><em>,<strong>,<b>,<i>,<u><h1>,<h2>,<h3>,<h4>,<h5>,<h6><ul>,<ol>,<li><table>,<thead>,<tbody>,<tr>,<th>,<td><blockquote>,<hr>
Most useful is the <a> tag for creating links. URLs are automatically clickable in the Table visualization, but you can also set a custom link using an <a> tag.
SQL
PostHog AI
select
properties.$pathname,
<a href={f'https://posthog.com/{properties.$pathname}'} target='_blank'>Link</a> as link
from events
where event = '$pageview'Text effects
Plain text is so boring, so we added some text effects to make it cooler. Wrap any text in <blink> to make it blink, <marquee> to make it horizontally scroll, and <redacted> to hide it unless hovered.
SQL
PostHog AI
select
<span>is this <blink>{event}</blink> real?</span>,
<marquee>so real, yes!</marquee>,
<redacted>but this one is hidden</redacted>
from eventsCommunity questions
Ask a question
Was this page useful?
HelpfulCould be better
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- PostHog
- Publisher
- PostHog (Official)
- Source
- PostHog/skills · skills/posthog/tools-and-features/skills/hogql · commit a5d30e7
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- PostHog/skills
AutoGineer is not affiliated with or endorsed by PostHog or PostHog.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download tools-and-features-hogql.zip