Skip to content

INS-286: Use PostHog to track template page visits and downloads#146

Merged
CarmenDou merged 1 commit into
mainfrom
feat/marketplace-download-tracking
May 28, 2026
Merged

INS-286: Use PostHog to track template page visits and downloads#146
CarmenDou merged 1 commit into
mainfrom
feat/marketplace-download-tracking

Conversation

@CarmenDou
Copy link
Copy Markdown
Contributor

@CarmenDou CarmenDou commented May 28, 2026

Summary by cubic

Track marketplace template downloads in PostHog by emitting marketplace_template_downloaded after a successful download, including orgId and template slug. Kept the marketplace counter (fire-and-forget), clarified docs that PostHog is the analytics source of truth, and updated the test regex to allow the new event call.

Written for commit 63db66f. Summary will update on new commits.

Review in cubic

Note

Track marketplace_template_downloaded PostHog event on successful marketplace template download

When insforge create is invoked with a valid --marketplace slug and the GitHub template download succeeds, a marketplace_template_downloaded PostHog event is emitted with the template slug as a property. This fires before the existing reportMarketplaceDownload DB counter call, which is now documented as backing the on-page download count rather than analytics.

Macroscope summarized 63db66f.

Summary by CodeRabbit

  • New Features

    • Enhanced analytics event tracking when downloading marketplace templates, now capturing template selection details.
  • Tests

    • Updated marketplace template wiring test to accommodate variable code patterns.
  • Documentation

    • Clarified analytics systems responsible for tracking download metrics and their respective data roles.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Walkthrough

The PR adds analytics event emission for marketplace template downloads. When a template downloads successfully, the CLI now captures a marketplace_template_downloaded event with the marketplace slug before invoking the existing counter ping, and documentation is clarified to distinguish the DB counter from PostHog analytics tracking.

Changes

Marketplace template download analytics

Layer / File(s) Summary
Analytics event and documentation
src/commands/create.ts
When marketplace template download succeeds, captureEvent records the marketplace_template_downloaded event with the marketplace slug before reportMarketplaceDownload. The reportMarketplaceDownload JSDoc is updated to clarify that the DB counter shows the template page number while PostHog is the analytics source of truth.
Test structural assertion update
src/commands/create.marketplace.test.ts
The regex that validates reportMarketplaceDownload is gated behind the downloaded check is expanded to tolerate the additional code span introduced by the new captureEvent call.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • InsForge/CLI#137: Both PRs modify the marketplace flow in src/commands/create.ts around reportMarketplaceDownload (including its gating on the downloaded result) and adjust src/commands/create.marketplace.test.ts expectations for the corresponding wiring.

  • InsForge/CLI#142: Both PRs modify src/commands/create.ts and src/commands/create.marketplace.test.ts around when/how reportMarketplaceDownload is invoked (and its wiring/expectations), so the main PR's loosened "downloaded" gating assertion is directly downstream of the retrieved PR's reportMarketplaceDownload call/contract changes.

Suggested reviewers

  • jwfing

Poem

🐰 A marketplace event hops in with style,
Capturing downloads mile after mile,
PostHog and counters now share the tale,
Tests flex their regex without fail,
Analytics flourish, the feature sets sail! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title mentions tracking template page visits and downloads, but the changeset only implements download tracking via PostHog; page visit tracking is not addressed. Clarify whether page visit tracking is included in this PR or revise the title to focus solely on download tracking to match the actual implementation.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/marketplace-download-tracking

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@CarmenDou CarmenDou changed the title feat(posthog): track marketplace_template_downloaded on marketplace INS-286: Use PostHog to track template page visits and downloads May 28, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 28, 2026

Greptile Summary

This PR adds a marketplace_template_downloaded PostHog event fired immediately after a successful marketplace template download, gated by the same if (downloaded) boolean that protects the existing download counter. The companion comment on reportMarketplaceDownload is updated to reflect that PostHog is now the analytics source of truth.

  • create.ts: captureEvent(orgId, 'marketplace_template_downloaded', { template: opts.marketplace }) is inserted inside the if (downloaded) block, consistent with how other captureEvent calls in the file use orgId as the distinct ID.
  • create.marketplace.test.ts: The structural regex window is widened from {0,80} to {0,200} to accommodate the new captureEvent line between the if (downloaded) guard and reportMarketplaceDownload, but no matching assertion is added to verify the new event is also inside that guard.

Confidence Score: 4/5

The production change is minimal and low-risk; the analytics call is correctly gated and consistent with existing patterns.

The new captureEvent call is correctly placed inside the if (downloaded) guard and matches the style of every other call site in the file. The only gap is in the test: the regex window was widened to pass but no assertion was added to verify the new event is itself inside the guard, leaving that invariant untested going forward.

src/commands/create.marketplace.test.ts — the guard-assertion gap for the new event

Important Files Changed

Filename Overview
src/commands/create.ts Adds captureEvent('marketplace_template_downloaded') inside the existing if (downloaded) guard; consistent with other captureEvent call sites using orgId as distinctId. Comment on reportMarketplaceDownload updated to reflect PostHog is now used.
src/commands/create.marketplace.test.ts Widens the regex window from {0,80} to {0,200} to accommodate the new captureEvent insertion; no assertion added to verify the new event is also gated by the downloaded boolean.

Sequence Diagram

sequenceDiagram
    participant CLI as create command
    participant GH as downloadGitHubTemplate
    participant PH as PostHog (captureEvent)
    participant MW as Marketplace API (reportMarketplaceDownload)

    CLI->>GH: downloadGitHubTemplate(slug, config, json)
    GH-->>CLI: downloaded (true/false)
    alt "downloaded === true"
        CLI->>PH: "captureEvent(orgId, 'marketplace_template_downloaded', { template: slug })"
        CLI-->>MW: void reportMarketplaceDownload(slug)  [fire-and-forget]
    end
Loading

Reviews (1): Last reviewed commit: "feat(posthog): track marketplace_templat..." | Re-trigger Greptile

// the marketplace's install count.
expect(createSource).toMatch(/const downloaded = await downloadGitHubTemplate/);
expect(createSource).toMatch(/if \(downloaded\)[\s\S]{0,80}reportMarketplaceDownload/);
expect(createSource).toMatch(/if \(downloaded\)[\s\S]{0,200}reportMarketplaceDownload/);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test guards the new captureEvent call against the downloaded boolean

The existing test was widened to {0,200} so reportMarketplaceDownload still passes, but there is no corresponding assertion that captureEvent(orgId, 'marketplace_template_downloaded', …) is also inside the if (downloaded) block. If the captureEvent call were accidentally moved outside that guard, the test suite would not catch it, silently recording phantom analytics events for failed downloads — the exact failure mode the surrounding comment warns about.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/commands/create.marketplace.test.ts (1)

96-96: 💤 Low value

Consider tightening the regex bound to 150 characters.

The change from {0,80} to {0,200} accommodates the new captureEvent call, but 200 is generous. The actual intervening code (captureEvent + reportMarketplaceDownload) is roughly 120-150 characters. Using {0,150} would provide adequate margin while keeping the structural assertion more precise.

🎯 Proposed tighter bound
-    expect(createSource).toMatch(/if \(downloaded\)[\s\S]{0,200}reportMarketplaceDownload/);
+    expect(createSource).toMatch(/if \(downloaded\)[\s\S]{0,150}reportMarketplaceDownload/);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/create.marketplace.test.ts` at line 96, The test's regex in the
assertion on createSource is too loose ({0,200}); narrow the character bound to
{0,150} to better match the actual intervening code (captureEvent followed by
reportMarketplaceDownload). Update the expectation that references createSource
(the line using expect(createSource).toMatch(...)) so the pattern uses /if
\(downloaded\)[\s\S]{0,150}reportMarketplaceDownload/ to keep the structural
check precise while still allowing the new captureEvent call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/commands/create.marketplace.test.ts`:
- Line 96: The test's regex in the assertion on createSource is too loose
({0,200}); narrow the character bound to {0,150} to better match the actual
intervening code (captureEvent followed by reportMarketplaceDownload). Update
the expectation that references createSource (the line using
expect(createSource).toMatch(...)) so the pattern uses /if
\(downloaded\)[\s\S]{0,150}reportMarketplaceDownload/ to keep the structural
check precise while still allowing the new captureEvent call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95ca8973-1fb3-4aad-8e96-b42d195a56d6

📥 Commits

Reviewing files that changed from the base of the PR and between 6a0502b and 63db66f.

📒 Files selected for processing (2)
  • src/commands/create.marketplace.test.ts
  • src/commands/create.ts

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

Copy link
Copy Markdown
Member

@jwfing jwfing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — INS-286: PostHog marketplace_template_downloaded tracking

Summary: Small, focused addition that emits a PostHog event on successful marketplace template download, correctly guarded by the existing downloaded boolean, with a matching doc-comment correction. No blocking issues.


Requirements context

No /docs/superpowers/ directory exists in this repo — assessing against the PR description and the old doc comment that read "PostHog is intentionally not used (per spec §6.3)". The PR description is clear: emit marketplace_template_downloaded after a successful download, keep the DB counter, update docs to reflect PostHog as the analytics source of truth.


Findings

Critical

(none)

Suggestion

Software Engineering — missing dedicated test for the new event (src/commands/create.marketplace.test.ts)

The test file uses structural source-text assertions as its established pattern — there are already tests verifying the presence and shape of captureEvent(orgId, 'template_selected', ...) (lines 99–107) and the counter guard (lines 91–97). The PR adds a new observable behavior (a new captureEvent call with a specific event name and property), but only widens the existing counter-guard regex ({0,80}{0,200}) rather than adding a new assertion.

Following the existing pattern, a complementary test like the following would pin the new behavior and prevent silent removal:

it('emits marketplace_template_downloaded inside the downloaded guard', () => {
  expect(createSource).toMatch(
    /if \(downloaded\)[\s\S]{0,200}captureEvent\(orgId, 'marketplace_template_downloaded'/,
  );
  // verify template property is forwarded
  const callIdx = createSource.indexOf("captureEvent(orgId, 'marketplace_template_downloaded'");
  const closingParen = createSource.indexOf(');', callIdx);
  expect(createSource.slice(callIdx, closingParen)).toMatch(/template.*opts\.marketplace/);
});

The insforge-development skill requires "every new behavior has at least one test"; the widened regex in the existing test happens to keep passing, but it no longer directly asserts the new call exists.

Information

  • src/commands/create.ts:748–756 (doc comment): The correction from "PostHog is intentionally not used (per spec §6.3)" to "PostHog is the source of truth for download analytics" is correct and important — the old note would have actively misled future readers. Good housekeeping.
  • Event ordering (create.ts:385–388): captureEvent fires before void reportMarketplaceDownload(...). Both are fire-and-forget and either order works, but firing analytics first (before the counter) is a reasonable default — a failed counter call cannot suppress the analytics event.
  • orgId as distinct ID (create.ts:385): orgId is resolved in step 1 of the action (line 194–216) and is always set before the download block (step 7) executes — no null-identity risk here.

Verdict

approved (informational — human approval required via the approve flow)

Zero Critical findings. One Suggestion to add an explicit structural test for the new event, consistent with the test patterns already present in create.marketplace.test.ts.

Copy link
Copy Markdown
Member

@jwfing jwfing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, approved.

@CarmenDou CarmenDou merged commit 3c44819 into main May 28, 2026
4 checks passed
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.

2 participants