Skip to content

fix(amplitude): correct wire formats and add funnels/retention analytics#5355

Merged
waleedlatif1 merged 2 commits into
stagingfrom
worktree-amplitude-validate
Jul 2, 2026
Merged

fix(amplitude): correct wire formats and add funnels/retention analytics#5355
waleedlatif1 merged 2 commits into
stagingfrom
worktree-amplitude-validate

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Fixed Identify/Group Identify APIs sending JSON instead of the form-urlencoded body Amplitude requires
  • Fixed Send Event sending snake_case product_id/revenue_type instead of Amplitude's camelCase productId/revenueType
  • Fixed Get Revenue parsing a response shape that never matched the real Revenue LTV API (was always returning empty data)
  • Added EU data residency support across all tools (EU projects were silently rejected by the US-only hosts)
  • Added missing filters/formula/segment params to Event Segmentation, groupBy/segment to Active Users and Revenue
  • Added first_used/last_used to User Activity output, non_active/flow_hidden to List Events output
  • Added real-time/hourly interval options to Event Segmentation
  • Added new Funnels and Retention tools for conversion and retention analysis
  • Updated brand colors to current Amplitude guide

Type of Change

  • Bug fix
  • New feature

Testing

Verified every fix against Amplitude's live API docs with 3 independent verification passes (wire format, response shape, block/tool alignment, backwards compatibility). bun run lint and tsc --noEmit both clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 2, 2026 5:03pm

Request Review

@cursor

cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Fixes change live ingestion and identify behavior (body format and event field names), and Get Revenue’s output shape is a breaking change for workflows that depended on the old empty/wrong parsing; EU routing affects all regional customers once they set residency.

Overview
This PR fixes several Amplitude integrations that were calling the wrong hosts or sending payloads Amplitude rejects, and expands analytics coverage in the workflow block and tools.

Wire-format and response fixes: Identify and Group Identify now POST application/x-www-form-urlencoded bodies (with identification JSON-stringified) instead of JSON. Send Event maps revenue fields as camelCase productId / revenueType. Get Revenue no longer assumes a generic time-series plus xValues; it returns the LTV shape (dates / values per series) and drops the incorrect xValues output.

EU data residency: New getIngestionHost / getDashboardHost helpers route ingestion and dashboard REST calls to EU hosts when dataResidency is eu. The block exposes a Data Residency advanced field (hidden for US-only User Profile).

New operations: Funnels and Retention tools and block operations are added end-to-end (registry, types, UI fields, funnel skill template).

Richer query APIs: Event Segmentation gains filters (embedded in the e param), formula validation, second group-by, segment, and real-time/hourly intervals. Active Users, Revenue, Funnels, and Retention gain groupBy / segment where applicable. List Events and User Activity expose additional API fields; block outputs and send-event metadata are aligned.

Cosmetic: Amplitude block brand colors are updated.

Reviewed by Cursor Bugbot for commit bf99662. Configure here.

Comment thread apps/sim/tools/amplitude/funnels.ts
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes several incorrect wire formats in Amplitude tools and adds new Funnels and Retention analytics operations. The Identify/Group Identify endpoints are corrected from JSON to form-urlencoded body, productId/revenueType fields are fixed from snake_case to camelCase in Send Event, and the Revenue LTV response parsing is corrected to match the actual Amplitude API shape.

  • Wire format fixes: identify_user and group_identify now properly build URLSearchParams bodies with Content-Type: application/x-www-form-urlencoded; the tool executor's isPreformattedContent path handles this correctly.
  • New tools: amplitude_funnels and amplitude_retention are added with full input validation (the funnels tool validates event array items are plain objects; the retention tool validates startEvent/returnEvent as JSON objects and validates retentionBrackets when mode is "bracket").
  • EU residency: A new utils.ts centralises host selection; all dashboard and ingestion tools switch to their EU URLs when dataResidency === 'eu'.

Confidence Score: 5/5

All four wire-format bugs are correctly patched and the two new tools are well-validated; safe to merge.

The form-urlencoded body fix is confirmed correct by the executor's isPreformattedContent path. The camelCase revenue-field fix matches Amplitude's HTTP API v2 schema. EU host selection is centralised and the URL values match Amplitude's documented residency endpoints. The new Funnels and Retention tools validate their required JSON params with descriptive errors before any network call, consistent with the filters fix in event_segmentation. The dataResidency field flows through finalInputs spread in the generic handler without needing explicit case entries. No logic regressions identified.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/tools/amplitude/utils.ts New utility file providing getDashboardHost/getIngestionHost; EU URL values match Amplitude's documented residency endpoints.
apps/sim/tools/amplitude/send_event.ts Fixes productId/revenueType from snake_case to camelCase per HTTP API v2 spec; adds EU residency support via getIngestionHost.
apps/sim/tools/amplitude/identify_user.ts Correctly switches body to form-urlencoded (URLSearchParams); the executor's isPreformattedContent path handles string bodies of this Content-Type correctly.
apps/sim/tools/amplitude/group_identify.ts Same form-urlencoded fix as identify_user; identification array is JSON-stringified into the URLSearchParams as Amplitude requires.
apps/sim/tools/amplitude/funnels.ts New tool; validates events as a non-empty plain-object array, appends each step as a separate ?e= param; response mapped to stepByStep/cumulative/dayFunnels structure.
apps/sim/tools/amplitude/retention.ts New tool; parses and re-serialises startEvent/returnEvent with clear errors; validates retentionBrackets only when mode is 'bracket'; response mapped from data.series/seriesMeta.
apps/sim/tools/amplitude/event_segmentation.ts Adds filters/formula/segment/groupBy2 params; filters are now validated as a JSON array and embedded in the event object with a clear error on failure; EU residency added.
apps/sim/tools/amplitude/get_revenue.ts Fixes response parsing by reading data.series/data.seriesLabels from the correct revenue LTV shape; removes xValues which was never returned by this endpoint.
apps/sim/blocks/blocks/amplitude.ts Adds Funnels/Retention to block dropdown, EU residency dropdown, and all new operation-specific UI fields; dataResidency flows through inputs spread in generic-handler without needing explicit case entries.
apps/sim/tools/amplitude/types.ts Adds AmplitudeFunnelsParams/Response and AmplitudeRetentionParams/Response; revenue response type is corrected to the actual LTV shape; dataResidency added to base interfaces.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant UI as Block UI
    participant GH as GenericBlockHandler
    participant T as ToolConfig (amplitude_*)
    participant Amp as Amplitude API

    UI->>GH: inputs (incl. apiKey, secretKey, dataResidency, operation-specific fields)
    GH->>GH: config.params(inputs) → transformedParams
    GH->>GH: "finalInputs = { ...inputs, ...transformedParams }"

    alt send_event / identify / group_identify
        GH->>T: executeTool(finalInputs)
        T->>T: getIngestionHost(dataResidency)
        Note over T: US → api2.amplitude.com / EU → api.eu.amplitude.com
        T->>Amp: POST /2/httpapi (JSON, fixed camelCase productId/revenueType)
        T->>Amp: POST /identify (form-urlencoded, fixed from JSON)
        T->>Amp: POST /groupidentify (form-urlencoded, fixed from JSON)
    else funnels / retention / segmentation / revenue / active_users
        GH->>T: executeTool(finalInputs)
        T->>T: getDashboardHost(dataResidency)
        Note over T: US → amplitude.com / EU → analytics.eu.amplitude.com
        T->>T: validate events/startEvent/returnEvent JSON
        T->>Amp: "GET /api/2/funnels?e=...&start=...&end=..."
        T->>Amp: "GET /api/2/retention?se=...&re=...&start=...&end=..."
        Amp-->>T: "{ data: { series, ... } }"
        T-->>GH: "{ success: true, output: { ... } }"
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant UI as Block UI
    participant GH as GenericBlockHandler
    participant T as ToolConfig (amplitude_*)
    participant Amp as Amplitude API

    UI->>GH: inputs (incl. apiKey, secretKey, dataResidency, operation-specific fields)
    GH->>GH: config.params(inputs) → transformedParams
    GH->>GH: "finalInputs = { ...inputs, ...transformedParams }"

    alt send_event / identify / group_identify
        GH->>T: executeTool(finalInputs)
        T->>T: getIngestionHost(dataResidency)
        Note over T: US → api2.amplitude.com / EU → api.eu.amplitude.com
        T->>Amp: POST /2/httpapi (JSON, fixed camelCase productId/revenueType)
        T->>Amp: POST /identify (form-urlencoded, fixed from JSON)
        T->>Amp: POST /groupidentify (form-urlencoded, fixed from JSON)
    else funnels / retention / segmentation / revenue / active_users
        GH->>T: executeTool(finalInputs)
        T->>T: getDashboardHost(dataResidency)
        Note over T: US → amplitude.com / EU → analytics.eu.amplitude.com
        T->>T: validate events/startEvent/returnEvent JSON
        T->>Amp: "GET /api/2/funnels?e=...&start=...&end=..."
        T->>Amp: "GET /api/2/retention?se=...&re=...&start=...&end=..."
        Amp-->>T: "{ data: { series, ... } }"
        T-->>GH: "{ success: true, output: { ... } }"
    end
Loading

Reviews (8): Last reviewed commit: "fix(amplitude): validate retention brack..." | Re-trigger Greptile

Comment thread apps/sim/tools/amplitude/funnels.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/amplitude/funnels.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/amplitude/event_segmentation.ts
Comment thread apps/sim/tools/amplitude/funnels.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/amplitude/funnels.ts
Comment thread apps/sim/tools/amplitude/funnels.ts Outdated
Comment thread apps/sim/tools/amplitude/funnels.ts
Comment thread apps/sim/tools/amplitude/event_segmentation.ts
Comment thread apps/sim/tools/amplitude/retention.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/amplitude.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 90056e1. Configure here.

…tention

- Fix Identify/Group Identify sending JSON instead of the form-urlencoded body Amplitude requires
- Fix Send Event using snake_case product_id/revenue_type instead of Amplitude's camelCase productId/revenueType
- Fix Get Revenue parsing a response shape that never matched the real Revenue LTV API
- Add EU data residency support across all tools
- Add missing filters/formula/segment params to Event Segmentation, groupBy/segment to Active Users and Revenue
- Add first_used/last_used to User Activity output, non_active/flow_hidden to List Events output
- Add real-time/hourly interval options to Event Segmentation
- Add Funnels and Retention tools for conversion and retention analysis
- Harden JSON-shape validation across funnels/segmentation/retention (fail loudly on malformed or partial input instead of silently degrading)
- Expose every tool output field (user_profile, send_event, user_search) on the block so nothing is unreachable downstream
- Update brand colors to current Amplitude guide
@waleedlatif1 waleedlatif1 force-pushed the worktree-amplitude-validate branch from 90056e1 to 15e7c14 Compare July 2, 2026 16:55
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/tools/amplitude/retention.ts Outdated
Comment thread apps/sim/tools/amplitude/retention.ts Outdated
Comment thread apps/sim/tools/amplitude/get_active_users.ts
Comment thread apps/sim/tools/amplitude/event_segmentation.ts
…dd segmentation 2nd group-by

- Retention now validates retentionBrackets as a JSON array and requires it when retentionMode is "bracket", matching the block UI's requirement
- Event Segmentation now throws if metric is "formula" but no formula is provided, matching the block UI's requirement
- Event Segmentation now supports a documented second group-by property via groupBy2/g2
- Corrected Get Active Users' group-by copy — Amplitude's docs don't document a second-property syntax for /api/2/users the way they do for segmentation's g2, so the field no longer overpromises "max two"
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit bf99662. Configure here.

@waleedlatif1 waleedlatif1 merged commit 0507acf into staging Jul 2, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-amplitude-validate branch July 2, 2026 17:26
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.

1 participant