Identify employee traffic
Some Parse.ly customers tag their employees' pageviews in the tracker via extra_data (e.g., extra_data['Internal'] = true set on logged-in users). Parse.ly's dashboard uses that tag for segment filtering, but the DPL stream is raw – tagged events still arrive. This flow finds that tag (when present and unambiguous) and saves it to bucket.json. Subsequent staircase runs apply the filter automatically and surface a one-line note in the report.
Customers who use Parse.ly's account-level IP blocklist instead (the more common pattern) need nothing from this flow – their DPL events are already filtered upstream.
The user may ask to clear the saved filter instead of detecting one (e.g. "remove the employee filter", or the --clear argument on harnesses with slash commands).
Output discipline
Terse. The detection script prints its own one-line result; output it verbatim and stop.
Steps
Resolve the plugin root. Every bash snippet below assumes
$plugin_rootis set in that shell invocation; re-run this line whenever you start a new shell:plugin_root="${CLAUDE_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT:-<plugin-root>}}" plugin_python="${AGENTIC_ANALYTICS_VENV:-${AGENTIC_ANALYTICS_DATA_DIR:-$HOME/.local/share/agentic-analytics}/venv}/bin/python" [ -x "$plugin_python" ] || plugin_python="python3"<plugin-root>is the plugin's install directory – the directory two levels above this SKILL.md file. In a dev checkout of the source repo that'splugin/.$plugin_pythonis the plugin's isolated venv (created by the init flow at$AGENTIC_ANALYTICS_DATA_DIR/venv, default~/.local/share/agentic-analytics/venv); it falls back topython3if the venv doesn't exist yet.Load bucket config. Read
${XDG_CONFIG_HOME:-~/.config}/agentic-analytics/bucket.json. It contains:bucket– S3 bucket holding the customer's DPL events.cache_dir– a slug identifying the customer's data (e.g.acme).
If the file is missing, tell the user to run the init flow first (
/agentic-analytics:initon harnesses with slash commands, or "set up agentic analytics" in chat) and stop.Handle a clear request. If the user asked to clear, remove any saved filter and stop:
"$plugin_python" "$plugin_root/skills/identify-employees/scripts/detect_employee_filter.py" \ --bucket-config "${XDG_CONFIG_HOME:-$HOME/.config}/agentic-analytics/bucket.json" \ --clearOutput the script's one-line result and stop.
Run detection. Otherwise sample events from the catalog and write any unambiguous filter to
bucket.json. Pass--site <site>to scope the sample to a specific site (when the user provides one – via a slash-command argument on harnesses that have them, or in chat); omit it to sample across all sites:"$plugin_python" "$plugin_root/skills/identify-employees/scripts/detect_employee_filter.py" \ --bucket-config "${XDG_CONFIG_HOME:-$HOME/.config}/agentic-analytics/bucket.json" \ [--site <site>]Output the script's one-line result verbatim. Three possibilities:
- Match found: "Detected employee traffic tagged with
extra_data['<key>'] = <value>(X% of N sampled pageviews). Will filter this out of audience reports so it doesn't skew your results. Tell me if this is incorrect." - No match: "No unambiguous employee-traffic tag detected in N sampled pageviews. No filter applied."
- Lake empty: "No pageview events found in the lake[ for site '']. Run /agentic-analytics:staircase or /agentic-analytics:refresh-cache first." – tell the user to run the staircase report or the refresh-cache flow first to populate the lake, then re-run this flow.
Don't add framing or summary.
- Match found: "Detected employee traffic tagged with
Notes
- The filter is auto-applied only when unambiguous (matched case-insensitively): known key name in
internal,is_internal,is_employee,employee,staff,internal_user/internalUser,internal_traffic; boolean-ish value (true/1/yes); and tagged share between 0.1% and 25% of sampled pageviews. Ambiguous setups (multiple distinct values on the same key, or a share outside that range) are silently skipped. - Re-running this flow after the customer changes their tracker is the right way to refresh the detected filter.
- A clear request removes any saved filter and exits without scanning – useful when detection got the wrong key and you want to start over.
- This flow does not touch Parse.ly's per-account IP blocklist, which is the canonical mechanism for customers who go that route (managed by Parse.ly Support, applied upstream of the DPL).