From c4fc849327ff1b9a2886fc8eaf0e3030cdcbbc3a Mon Sep 17 00:00:00 2001 From: Conor Richey Date: Wed, 5 Aug 2026 11:35:50 +0100 Subject: [PATCH 1/2] Add Amplitude plugin v1 for monitoring Amplitude analytics data --- plugins/Amplitude/v1/configValidation.json | 13 + plugins/Amplitude/v1/custom_types.json | 16 ++ .../v1/dataStreams/activeUsersHistory.json | 55 ++++ .../v1/dataStreams/cohortEventHistory.json | 58 +++++ plugins/Amplitude/v1/dataStreams/cohorts.json | 63 +++++ .../v1/dataStreams/eventCountHistory.json | 71 ++++++ .../v1/dataStreams/eventProperties.json | 41 +++ .../Amplitude/v1/dataStreams/eventTypes.json | 51 ++++ .../v1/dataStreams/realtimeActiveUsers.json | 28 +++ .../dataStreams/scripts/activeUsersHistory.js | 7 + .../dataStreams/scripts/cohortEventHistory.js | 7 + .../dataStreams/scripts/eventCountHistory.js | 38 +++ .../scripts/realtimeActiveUsers.js | 17 ++ .../v1/dataStreams/userActivity.json | 69 +++++ .../Amplitude/v1/dataStreams/userSearch.json | 39 +++ .../v1/dataStreams/validateAuth.json | 17 ++ .../defaultContent/cohortOverview.dash.json | 104 ++++++++ .../eventTypeOverview.dash.json | 155 ++++++++++++ .../Amplitude/v1/defaultContent/manifest.json | 7 + .../v1/defaultContent/overview.dash.json | 237 ++++++++++++++++++ .../Amplitude/v1/defaultContent/scopes.json | 26 ++ plugins/Amplitude/v1/docs/README.md | 45 ++++ plugins/Amplitude/v1/icon.svg | 18 ++ .../v1/indexDefinitions/default.json | 46 ++++ plugins/Amplitude/v1/metadata.json | 50 ++++ plugins/Amplitude/v1/ui.json | 40 +++ 26 files changed, 1318 insertions(+) create mode 100644 plugins/Amplitude/v1/configValidation.json create mode 100644 plugins/Amplitude/v1/custom_types.json create mode 100644 plugins/Amplitude/v1/dataStreams/activeUsersHistory.json create mode 100644 plugins/Amplitude/v1/dataStreams/cohortEventHistory.json create mode 100644 plugins/Amplitude/v1/dataStreams/cohorts.json create mode 100644 plugins/Amplitude/v1/dataStreams/eventCountHistory.json create mode 100644 plugins/Amplitude/v1/dataStreams/eventProperties.json create mode 100644 plugins/Amplitude/v1/dataStreams/eventTypes.json create mode 100644 plugins/Amplitude/v1/dataStreams/realtimeActiveUsers.json create mode 100644 plugins/Amplitude/v1/dataStreams/scripts/activeUsersHistory.js create mode 100644 plugins/Amplitude/v1/dataStreams/scripts/cohortEventHistory.js create mode 100644 plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js create mode 100644 plugins/Amplitude/v1/dataStreams/scripts/realtimeActiveUsers.js create mode 100644 plugins/Amplitude/v1/dataStreams/userActivity.json create mode 100644 plugins/Amplitude/v1/dataStreams/userSearch.json create mode 100644 plugins/Amplitude/v1/dataStreams/validateAuth.json create mode 100644 plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json create mode 100644 plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json create mode 100644 plugins/Amplitude/v1/defaultContent/manifest.json create mode 100644 plugins/Amplitude/v1/defaultContent/overview.dash.json create mode 100644 plugins/Amplitude/v1/defaultContent/scopes.json create mode 100644 plugins/Amplitude/v1/docs/README.md create mode 100644 plugins/Amplitude/v1/icon.svg create mode 100644 plugins/Amplitude/v1/indexDefinitions/default.json create mode 100644 plugins/Amplitude/v1/metadata.json create mode 100644 plugins/Amplitude/v1/ui.json diff --git a/plugins/Amplitude/v1/configValidation.json b/plugins/Amplitude/v1/configValidation.json new file mode 100644 index 00000000..b1a5380b --- /dev/null +++ b/plugins/Amplitude/v1/configValidation.json @@ -0,0 +1,13 @@ +{ + "steps": [ + { + "displayName": "Authenticate", + "dataStream": { + "name": "validateAuth" + }, + "required": true, + "error": "Could not authenticate with Amplitude. Check that your API key and secret key are correct, and that the correct region (US/EU) is selected.", + "success": "Connected to Amplitude successfully." + } + ] +} diff --git a/plugins/Amplitude/v1/custom_types.json b/plugins/Amplitude/v1/custom_types.json new file mode 100644 index 00000000..02086400 --- /dev/null +++ b/plugins/Amplitude/v1/custom_types.json @@ -0,0 +1,16 @@ +[ + { + "name": "Amplitude Event Type", + "sourceType": "Amplitude Event Type", + "icon": "bolt", + "singular": "Event Type", + "plural": "Event Types" + }, + { + "name": "Amplitude Cohort", + "sourceType": "Amplitude Cohort", + "icon": "users", + "singular": "Cohort", + "plural": "Cohorts" + } +] diff --git a/plugins/Amplitude/v1/dataStreams/activeUsersHistory.json b/plugins/Amplitude/v1/dataStreams/activeUsersHistory.json new file mode 100644 index 00000000..739f4355 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/activeUsersHistory.json @@ -0,0 +1,55 @@ +{ + "name": "activeUsersHistory", + "displayName": "Active Users History", + "description": "Daily active or new user counts over time", + "tags": ["Analytics", "Users"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/users", + "getArgs": [ + { "key": "start", "value": "{{timeframe.start.slice(0,10).replace(/-/g,'')}}" }, + { "key": "end", "value": "{{timeframe.end.slice(0,10).replace(/-/g,'')}}" }, + { "key": "i", "value": "1" }, + { "key": "m", "value": "{{metric}}" } + ], + "postRequestScript": "activeUsersHistory.js" + }, + "matches": "none", + "ui": [ + { + "type": "choiceChips", + "name": "metric", + "label": "Metric", + "options": [ + { "value": "active", "label": "Active Users" }, + { "value": "new", "label": "New Users" } + ], + "default": "active" + } + ], + "metadata": [ + { + "name": "date", + "displayName": "Date", + "shape": "date", + "role": "timestamp" + }, + { + "name": "users", + "displayName": "Users", + "shape": "number", + "role": "value" + } + ], + "timeframes": [ + "last7days", + "last30days", + "thisMonth", + "lastMonth", + "thisQuarter", + "lastQuarter", + "thisYear", + "lastYear" + ] +} diff --git a/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json b/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json new file mode 100644 index 00000000..6850b065 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json @@ -0,0 +1,58 @@ +{ + "name": "cohortEventHistory", + "displayName": "Cohort Event History", + "description": "Daily count of a chosen event fired by a cohort's members", + "tags": ["Analytics", "Events", "Cohorts"], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/events/segmentation", + "getArgs": [ + { "key": "e", "value": "{{JSON.stringify({event_type: Array.isArray(eventType) ? (eventType[0] && eventType[0].value) : eventType})}}" }, + { "key": "s", "value": "{{JSON.stringify([{prop: 'userdata_cohort', op: 'is', values: [object.rawId]}])}}" }, + { "key": "start", "value": "{{timeframe.start.slice(0,10).replace(/-/g,'')}}" }, + { "key": "end", "value": "{{timeframe.end.slice(0,10).replace(/-/g,'')}}" }, + { "key": "i", "value": "1" }, + { "key": "m", "value": "totals" } + ], + "postRequestScript": "cohortEventHistory.js" + }, + "matches": { "sourceType": { "type": "oneOf", "values": ["Amplitude Cohort"] } }, + "ui": [ + { + "type": "autocomplete", + "name": "eventType", + "label": "Event", + "data": { + "source": "dataStream", + "dataStreamName": "eventTypes", + "dataSourceConfig": {} + }, + "validation": { "required": true } + } + ], + "metadata": [ + { + "name": "date", + "displayName": "Date", + "shape": "date", + "role": "timestamp" + }, + { + "name": "eventCount", + "displayName": "Event Count", + "shape": "number", + "role": "value" + } + ], + "timeframes": [ + "last7days", + "last30days", + "thisMonth", + "lastMonth", + "thisQuarter", + "lastQuarter", + "thisYear", + "lastYear" + ] +} diff --git a/plugins/Amplitude/v1/dataStreams/cohorts.json b/plugins/Amplitude/v1/dataStreams/cohorts.json new file mode 100644 index 00000000..44d245eb --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/cohorts.json @@ -0,0 +1,63 @@ +{ + "name": "cohorts", + "displayName": "Cohorts", + "description": "Behavioral cohorts defined in the project", + "tags": ["Analytics"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/3/cohorts", + "pathToData": "cohorts" + }, + "matches": "none", + "metadata": [ + { + "name": "id", + "displayName": "ID", + "visible": false + }, + { + "name": "name", + "displayName": "Name", + "role": "label" + }, + { + "name": "description", + "displayName": "Description" + }, + { + "name": "size", + "displayName": "Size", + "shape": "number" + }, + { + "name": "type", + "displayName": "Cohort Type", + "visible": false + }, + { + "name": "published", + "displayName": "Published", + "shape": "boolean" + }, + { + "name": "archived", + "displayName": "Archived", + "shape": "boolean" + }, + { + "name": "lastComputed", + "displayName": "Last Computed", + "shape": "date" + }, + { + "name": "createdAt", + "displayName": "Created", + "shape": "date" + } + ], + "timeframes": false, + "visibility": { + "type": "hidden" + } +} diff --git a/plugins/Amplitude/v1/dataStreams/eventCountHistory.json b/plugins/Amplitude/v1/dataStreams/eventCountHistory.json new file mode 100644 index 00000000..0d3bd644 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/eventCountHistory.json @@ -0,0 +1,71 @@ +{ + "name": "eventCountHistory", + "displayName": "Event Count History", + "description": "Daily count of a specific event's occurrences", + "tags": ["Analytics", "Events"], + "baseDataSourceName": "httpRequestScopedSingle", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/events/segmentation", + "getArgs": [ + { "key": "e", "value": "{{(function(){ var v = Array.isArray(groupByProperty) ? (groupByProperty[0] && groupByProperty[0].value) : groupByProperty; var e = {event_type: object.rawId}; if (v) { e.group_by = [{type: 'event', value: v}]; } return JSON.stringify(e); })()}}" }, + { "key": "start", "value": "{{timeframe.start.slice(0,10).replace(/-/g,'')}}" }, + { "key": "end", "value": "{{timeframe.end.slice(0,10).replace(/-/g,'')}}" }, + { "key": "i", "value": "1" }, + { "key": "m", "value": "{{metric}}" } + ], + "postRequestScript": "eventCountHistory.js" + }, + "matches": { "sourceType": { "type": "oneOf", "values": ["Amplitude Event Type"] } }, + "ui": [ + { + "type": "choiceChips", + "name": "metric", + "label": "Metric", + "options": [ + { "value": "totals", "label": "Total Events" }, + { "value": "uniques", "label": "Unique Users" } + ], + "default": "totals" + }, + { + "type": "autocomplete", + "name": "groupByProperty", + "label": "Group by property (optional)", + "data": { + "source": "dataStream", + "dataStreamName": "eventProperties", + "dataSourceConfig": {} + } + } + ], + "metadata": [ + { + "name": "date", + "displayName": "Date", + "shape": "date", + "role": "timestamp" + }, + { + "name": "eventCount", + "displayName": "Event Count", + "shape": "number", + "role": "value" + }, + { + "name": "groupValue", + "displayName": "Property Value", + "shape": "string" + } + ], + "timeframes": [ + "last7days", + "last30days", + "thisMonth", + "lastMonth", + "thisQuarter", + "lastQuarter", + "thisYear", + "lastYear" + ] +} diff --git a/plugins/Amplitude/v1/dataStreams/eventProperties.json b/plugins/Amplitude/v1/dataStreams/eventProperties.json new file mode 100644 index 00000000..65524a92 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/eventProperties.json @@ -0,0 +1,41 @@ +{ + "name": "eventProperties", + "displayName": "Event Properties", + "description": "Event properties defined in the project's taxonomy schema", + "tags": ["Analytics"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/taxonomy/event-property", + "pathToData": "data", + "expandInnerObjects": true + }, + "matches": "none", + "metadata": [ + { + "name": "event_property", + "displayName": "Event Property", + "visible": false, + "role": "value" + }, + { + "name": "name", + "displayName": "Name", + "computed": true, + "valueExpression": "{{ $['event_property'] }}", + "role": "label" + }, + { + "name": "description", + "displayName": "Description" + }, + { + "name": "type", + "displayName": "Type" + } + ], + "timeframes": false, + "visibility": { + "type": "hidden" + } +} diff --git a/plugins/Amplitude/v1/dataStreams/eventTypes.json b/plugins/Amplitude/v1/dataStreams/eventTypes.json new file mode 100644 index 00000000..372c6ba1 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/eventTypes.json @@ -0,0 +1,51 @@ +{ + "name": "eventTypes", + "displayName": "Event Types", + "description": "Event types defined in the project's taxonomy schema", + "tags": ["Analytics"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/taxonomy/event", + "pathToData": "data", + "expandInnerObjects": true + }, + "matches": "none", + "metadata": [ + { + "name": "event_type", + "displayName": "Event Type", + "visible": false, + "role": "value" + }, + { + "name": "display_name", + "displayName": "Display Name", + "visible": false + }, + { + "name": "name", + "displayName": "Name", + "computed": true, + "valueExpression": "{{ $['display_name']?.__isNone ? $['event_type'] : $['display_name'] }}", + "role": "label" + }, + { + "name": "description", + "displayName": "Description" + }, + { + "name": "category.name", + "displayName": "Category" + }, + { + "name": "is_active", + "displayName": "Active", + "shape": "boolean" + } + ], + "timeframes": false, + "visibility": { + "type": "hidden" + } +} diff --git a/plugins/Amplitude/v1/dataStreams/realtimeActiveUsers.json b/plugins/Amplitude/v1/dataStreams/realtimeActiveUsers.json new file mode 100644 index 00000000..70409f03 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/realtimeActiveUsers.json @@ -0,0 +1,28 @@ +{ + "name": "realtimeActiveUsers", + "displayName": "Real-time Active Users", + "description": "Current real-time active user count", + "tags": ["Analytics", "Users"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/realtime", + "postRequestScript": "realtimeActiveUsers.js" + }, + "matches": "none", + "metadata": [ + { + "name": "activeUsers", + "displayName": "Real-time Active Users", + "shape": "number", + "role": "value" + }, + { + "name": "asOf", + "displayName": "As of", + "shape": "string", + "visible": true + } + ], + "timeframes": false +} diff --git a/plugins/Amplitude/v1/dataStreams/scripts/activeUsersHistory.js b/plugins/Amplitude/v1/dataStreams/scripts/activeUsersHistory.js new file mode 100644 index 00000000..d4a113bf --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/scripts/activeUsersHistory.js @@ -0,0 +1,7 @@ +// dataStreams/scripts/activeUsersHistory.js +// Amplitude returns two parallel arrays (dates + values) rather than one row +// per date, so a post-request script is required to zip them together. +const xValues = (data.data && data.data.xValues) || []; +const series = (data.data && data.data.series && data.data.series[0]) || []; + +result = xValues.map((date, i) => ({ date, users: series[i] })); diff --git a/plugins/Amplitude/v1/dataStreams/scripts/cohortEventHistory.js b/plugins/Amplitude/v1/dataStreams/scripts/cohortEventHistory.js new file mode 100644 index 00000000..ce539ee7 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/scripts/cohortEventHistory.js @@ -0,0 +1,7 @@ +// dataStreams/scripts/cohortEventHistory.js +// Amplitude returns two parallel arrays (dates + values) rather than one row +// per date, so a post-request script is required to zip them together. +const xValues = (data.data && data.data.xValues) || []; +const series = (data.data && data.data.series && data.data.series[0]) || []; + +result = xValues.map((date, i) => ({ date, eventCount: series[i] })); diff --git a/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js b/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js new file mode 100644 index 00000000..e9898090 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js @@ -0,0 +1,38 @@ +// dataStreams/scripts/eventCountHistory.js +// Amplitude returns two/three parallel arrays (dates + one series per group +// + group labels) rather than one row per date, so a post-request script is +// required to zip them together. +// +// Ungrouped (no groupByProperty set): data.series has exactly one array +// (one row per date, groupValue omitted) - this is today's existing, +// unchanged behavior. +// +// Grouped (groupByProperty set, via an embedded `group_by` on the `e` param): +// data.series has one array per distinct property value, and +// data.seriesLabels holds the label for each series - as an +// [eventIndex, label] tuple (since group_by is embedded per-event), not a +// bare string. Zip each series against xValues and tag every row with its +// group's label. +const xValues = (data.data && data.data.xValues) || []; +const series = (data.data && data.data.series) || []; +const seriesLabels = (data.data && data.data.seriesLabels) || []; + +if (series.length <= 1) { + // Ungrouped - identical output shape to before this change. + const values = series[0] || []; + result = xValues.map((date, i) => ({ + date, + eventCount: values[i], + groupValue: null, + })); +} else { + result = series.flatMap((values, seriesIndex) => { + const label = seriesLabels[seriesIndex]; + const groupValue = Array.isArray(label) ? label[1] : label; + return xValues.map((date, i) => ({ + date, + eventCount: values[i], + groupValue, + })); + }); +} diff --git a/plugins/Amplitude/v1/dataStreams/scripts/realtimeActiveUsers.js b/plugins/Amplitude/v1/dataStreams/scripts/realtimeActiveUsers.js new file mode 100644 index 00000000..ce0a8d9d --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/scripts/realtimeActiveUsers.js @@ -0,0 +1,17 @@ +// dataStreams/scripts/realtimeActiveUsers.js +// api/2/realtime returns rolling ~2 days of data at 5-minute granularity, +// with xValues as time-of-day labels and series[0] as "today". Later buckets +// for today may be null since the day isn't over yet - find the last non-null +// value to get the current active user count. +const xValues = (data.data && data.data.xValues) || []; +const todaySeries = (data.data && data.data.series && data.data.series[0]) || []; + +let idx = -1; +for (let i = todaySeries.length - 1; i >= 0; i--) { + if (todaySeries[i] !== null && todaySeries[i] !== undefined) { + idx = i; + break; + } +} + +result = idx >= 0 ? [{ asOf: xValues[idx], activeUsers: todaySeries[idx] }] : [{ asOf: null, activeUsers: 0 }]; diff --git a/plugins/Amplitude/v1/dataStreams/userActivity.json b/plugins/Amplitude/v1/dataStreams/userActivity.json new file mode 100644 index 00000000..63c79eea --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/userActivity.json @@ -0,0 +1,69 @@ +{ + "name": "userActivity", + "displayName": "User Activity", + "description": "Recent event activity for a specific user", + "tags": ["Analytics", "Users"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/useractivity", + "getArgs": [ + { "key": "user", "value": "{{amplitudeId}}" }, + { "key": "limit", "value": "100" } + ], + "pathToData": "events" + }, + "matches": "none", + "ui": [ + { + "name": "amplitudeId", + "label": "Amplitude ID", + "type": "text", + "help": "The numeric Amplitude ID of the user to look up (not their email or User ID). Find it using the **User Search** tile first, then copy the **Amplitude ID** value from the matching row here.", + "validation": { + "required": true + } + } + ], + "metadata": [ + { + "name": "event_time", + "displayName": "Time", + "shape": "date", + "role": "timestamp" + }, + { + "name": "event_type", + "displayName": "Event", + "role": "label" + }, + { + "name": "device_id", + "displayName": "Device ID" + }, + { + "name": "platform", + "displayName": "Platform" + }, + { + "name": "city", + "displayName": "City" + }, + { + "name": "country", + "displayName": "Country" + }, + { + "name": "event_properties", + "displayName": "Event Properties", + "shape": "json" + }, + { + "name": "user_properties", + "displayName": "User Properties", + "shape": "json" + }, + { "pattern": ".*" } + ], + "timeframes": false +} diff --git a/plugins/Amplitude/v1/dataStreams/userSearch.json b/plugins/Amplitude/v1/dataStreams/userSearch.json new file mode 100644 index 00000000..78b034f0 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/userSearch.json @@ -0,0 +1,39 @@ +{ + "name": "userSearch", + "displayName": "User Search", + "description": "Matches user, device, or Amplitude IDs against a search string", + "tags": ["Analytics", "Users"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/usersearch", + "getArgs": [{ "key": "user", "value": "{{identifier}}" }], + "pathToData": "matches" + }, + "matches": "none", + "ui": [ + { + "name": "identifier", + "label": "User ID / Device ID / Email prefix", + "type": "text", + "help": "Search for a user by their User ID, Device ID, or an email/ID prefix. Copy the **Amplitude ID** from a matching row into the **User Activity** tile's parameter to see that user's event timeline.", + "validation": { + "required": true + } + } + ], + "metadata": [ + { + "name": "user_id", + "displayName": "User ID", + "role": "label" + }, + { + "name": "amplitude_id", + "displayName": "Amplitude ID", + "shape": "number", + "role": "value" + } + ], + "timeframes": false +} diff --git a/plugins/Amplitude/v1/dataStreams/validateAuth.json b/plugins/Amplitude/v1/dataStreams/validateAuth.json new file mode 100644 index 00000000..a7b49a05 --- /dev/null +++ b/plugins/Amplitude/v1/dataStreams/validateAuth.json @@ -0,0 +1,17 @@ +{ + "name": "validateAuth", + "displayName": "Validate Auth", + "description": "Returns the project's taxonomy event categories", + "tags": ["Utility"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "endpointPath": "api/2/taxonomy/category" + }, + "matches": "none", + "metadata": [{ "pattern": ".*" }], + "timeframes": false, + "visibility": { + "type": "hidden" + } +} diff --git a/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json b/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json new file mode 100644 index 00000000..adfc26a3 --- /dev/null +++ b/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json @@ -0,0 +1,104 @@ +{ + "name": "Cohort", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": ["{{variables.[Amplitude Cohort]}}"], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "1cc9ddc5-eecc-40bc-804d-eb0e211128ef", + "x": 0, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Cohort Details", + "description": "", + "timeframe": "none", + "variables": ["{{variables.[Amplitude Cohort]}}"], + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Amplitude Cohorts]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Amplitude Cohort]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": [ + "name", + "description", + "size", + "published", + "archived", + "lastComputed", + "createdAt" + ], + "hiddenColumns": ["id", "link", "links", "label", "sourceId", "sourceType", "cohortType"] + } + } + } + } + }, + { + "i": "2d787a1a-f55b-4702-b138-136b64cbb70f", + "x": 1, + "y": 0, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Cohort Event History", + "description": "", + "variables": ["{{variables.[Amplitude Cohort]}}"], + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[cohortEventHistory]}}", + "name": "cohortEventHistory", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "eventType": [{ "value": "Dashboard Loaded", "label": "Dashboard Loaded" }] + } + }, + "scope": { + "scope": "{{scopes.[Amplitude Cohorts]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Amplitude Cohort]}}" + }, + "visualisation": { + "type": "data-stream-line-graph", + "config": { + "data-stream-line-graph": { + "xAxisColumn": "date", + "yAxisColumn": ["eventCount"], + "seriesColumn": "none", + "showLegend": false, + "legendPosition": "bottom", + "yAxisLabel": "Events", + "showYAxisLabel": true, + "showTrendLine": false + } + } + } + } + } + ] + } +} diff --git a/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json b/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json new file mode 100644 index 00000000..42d04fc2 --- /dev/null +++ b/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json @@ -0,0 +1,155 @@ +{ + "name": "Event Type", + "schemaVersion": "1.5", + "timeframe": "last30days", + "variables": ["{{variables.[Amplitude Event Type]}}"], + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "4b94c2a0-5067-485d-985b-22feff45dea5", + "x": 0, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Event Type Details", + "description": "", + "timeframe": "none", + "variables": ["{{variables.[Amplitude Event Type]}}"], + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "datastream-properties", + "name": "properties", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "scope": "{{scopes.[Amplitude Event Types]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Amplitude Event Type]}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": true, + "columnOrder": ["name", "description", "category", "is_active"], + "hiddenColumns": ["id", "link", "links", "label", "sourceId", "sourceType"] + } + } + } + } + }, + { + "i": "7cf3f9d6-6b24-471d-b20e-2372d587dfc5", + "x": 1, + "y": 0, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Event Count History", + "description": "", + "variables": ["{{variables.[Amplitude Event Type]}}"], + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[eventCountHistory]}}", + "name": "eventCountHistory", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "metric": "totals" + } + }, + "scope": { + "scope": "{{scopes.[Amplitude Event Types]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Amplitude Event Type]}}" + }, + "visualisation": { + "type": "data-stream-line-graph", + "config": { + "data-stream-line-graph": { + "xAxisColumn": "date", + "yAxisColumn": ["eventCount"], + "seriesColumn": "none", + "showLegend": false, + "legendPosition": "bottom", + "yAxisLabel": "Events", + "showYAxisLabel": true, + "showTrendLine": false + } + } + } + } + }, + { + "i": "48ad4c07-009b-4a9a-95ea-336fefdcd761", + "x": 0, + "y": 3, + "w": 4, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Event Breakdown by Property", + "description": "", + "variables": ["{{variables.[Amplitude Event Type]}}"], + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[eventCountHistory]}}", + "name": "eventCountHistory", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "metric": "totals", + "groupByProperty": [{ "value": "[Amplitude] Element Text", "label": "[Amplitude] Element Text" }] + }, + "group": { + "by": [["groupValue", "uniqueValues"]], + "aggregate": [{ "type": "sum", "names": ["eventCount"] }] + }, + "sort": { "by": [["eventCount_sum", "desc"]], "top": 10 } + }, + "scope": { + "scope": "{{scopes.[Amplitude Event Types]}}", + "workspace": "{{workspaceId}}", + "variable": "{{variables.[Amplitude Event Type]}}" + }, + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisData": "groupValue_uniqueValues", + "yAxisData": ["eventCount_sum"], + "xAxisGroup": "none", + "xAxisLabel": "", + "yAxisLabel": "", + "showXAxisLabel": true, + "showYAxisLabel": true, + "showLegend": false, + "legendPosition": "bottom", + "showGrid": true, + "horizontalLayout": "vertical", + "displayMode": "actual", + "showTotals": false, + "showValue": false, + "grouping": false, + "range": { "type": "auto" } + } + } + } + } + } + ] + } +} diff --git a/plugins/Amplitude/v1/defaultContent/manifest.json b/plugins/Amplitude/v1/defaultContent/manifest.json new file mode 100644 index 00000000..0e35e788 --- /dev/null +++ b/plugins/Amplitude/v1/defaultContent/manifest.json @@ -0,0 +1,7 @@ +{ + "items": [ + { "name": "overview", "type": "dashboard" }, + { "name": "eventTypeOverview", "type": "dashboard" }, + { "name": "cohortOverview", "type": "dashboard" } + ] +} diff --git a/plugins/Amplitude/v1/defaultContent/overview.dash.json b/plugins/Amplitude/v1/defaultContent/overview.dash.json new file mode 100644 index 00000000..e5e2ea4a --- /dev/null +++ b/plugins/Amplitude/v1/defaultContent/overview.dash.json @@ -0,0 +1,237 @@ +{ + "name": "Overview", + "schemaVersion": "1.5", + "timeframe": "last30days", + "dashboard": { + "_type": "layout/grid", + "columns": 4, + "version": 1, + "contents": [ + { + "i": "34c5570e-cbc0-43b4-881b-ccd4ad562177", + "x": 0, + "y": 0, + "w": 3, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Active Users Trend", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[activeUsersHistory]}}", + "name": "activeUsersHistory", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "metric": "active" + } + }, + "visualisation": { + "type": "data-stream-line-graph", + "config": { + "data-stream-line-graph": { + "xAxisColumn": "date", + "yAxisColumn": ["users"], + "seriesColumn": "none", + "showLegend": false, + "legendPosition": "bottom", + "yAxisLabel": "Active users", + "showYAxisLabel": true, + "showTrendLine": false + } + } + } + } + }, + { + "i": "35a44773-e55c-4242-8746-5c807f0b8830", + "x": 3, + "y": 0, + "w": 1, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Real-time Active Users", + "description": "", + "timeframe": "none", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[realtimeActiveUsers]}}", + "name": "realtimeActiveUsers", + "pluginConfigId": "{{configId}}" + }, + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": "activeUsers", + "comparisonColumn": "none" + } + } + } + } + }, + { + "i": "00663308-6093-4c0d-b53c-0bccb9d6cabf", + "x": 0, + "y": 3, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Event Types", + "description": "", + "timeframe": "none", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[eventTypes]}}", + "name": "eventTypes", + "pluginConfigId": "{{configId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": ["name", "description", "category.name", "is_active"] + } + } + } + } + }, + { + "i": "49be72d4-6ec6-4e06-90e5-8681f5bc9373", + "x": 2, + "y": 3, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "Cohorts", + "description": "", + "timeframe": "none", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[cohorts]}}", + "name": "cohorts", + "pluginConfigId": "{{configId}}" + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": ["name", "description", "size", "published"], + "hiddenColumns": ["archived", "lastComputed", "createdAt"] + } + } + } + } + }, + { + "i": "fdacd88d-155e-4367-83a3-7f24613a5886", + "x": 0, + "y": 6, + "w": 4, + "h": 1, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/text", + "title": "", + "description": "", + "visualisation": { + "config": { + "content": "User Lookup — search below to find a user's Amplitude ID, then paste it into the User Activity tile to see their event timeline", + "fontSize": 16, + "align": "left", + "autoSize": true + } + } + } + }, + { + "i": "23a3535f-a6c8-41c4-a7ae-53c3f982b7ef", + "x": 0, + "y": 7, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "1. User Search", + "description": "Search for a user, then copy their Amplitude ID into the User Activity tile", + "timeframe": "none", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[userSearch]}}", + "name": "userSearch", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "identifier": "" + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": ["user_id", "amplitude_id"] + } + } + } + } + }, + { + "i": "3ee601a5-5009-4421-a48a-a733739164c0", + "x": 2, + "y": 7, + "w": 2, + "h": 3, + "moved": false, + "static": false, + "z": 0, + "config": { + "_type": "tile/data-stream", + "title": "2. User Activity", + "description": "Paste an Amplitude ID from the User Search tile to see that user's recent events", + "timeframe": "none", + "activePluginConfigIds": ["{{configId}}"], + "dataStream": { + "id": "{{dataStreams.[userActivity]}}", + "name": "userActivity", + "pluginConfigId": "{{configId}}", + "dataSourceConfig": { + "amplitudeId": "" + } + }, + "visualisation": { + "type": "data-stream-table", + "config": { + "data-stream-table": { + "transpose": false, + "columnOrder": ["event_time", "event_type", "platform", "city", "country", "device_id"], + "hiddenColumns": ["event_properties", "user_properties"] + } + } + } + } + } + ] + } +} diff --git a/plugins/Amplitude/v1/defaultContent/scopes.json b/plugins/Amplitude/v1/defaultContent/scopes.json new file mode 100644 index 00000000..26bb3e49 --- /dev/null +++ b/plugins/Amplitude/v1/defaultContent/scopes.json @@ -0,0 +1,26 @@ +[ + { + "name": "Amplitude Event Types", + "matches": { + "sourceType": { "type": "oneOf", "values": ["Amplitude Event Type"] } + }, + "variable": { + "name": "Amplitude Event Type", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + }, + { + "name": "Amplitude Cohorts", + "matches": { + "sourceType": { "type": "oneOf", "values": ["Amplitude Cohort"] } + }, + "variable": { + "name": "Amplitude Cohort", + "allowMultipleSelection": false, + "default": "none", + "type": "object" + } + } +] diff --git a/plugins/Amplitude/v1/docs/README.md b/plugins/Amplitude/v1/docs/README.md new file mode 100644 index 00000000..879656e4 --- /dev/null +++ b/plugins/Amplitude/v1/docs/README.md @@ -0,0 +1,45 @@ +# Amplitude + +Monitor your [Amplitude](https://amplitude.com) product analytics project in SquaredUp. This plugin imports your project's event types and behavioral cohorts into the SquaredUp graph, and provides data streams for active user trends, event volume trends, cohort-filtered event activity, and individual user activity lookups. + +## What this plugin monitors + +- **Event Types** and **Cohorts** are imported as objects you can scope dashboards to, search for, and drill into. +- An **Overview** dashboard shows account-wide **active/new user trends**, **real-time active users**, a table of tracked **event types**, and a table of **cohorts**, plus a **user lookup** tile. +- An **Event Type** perspective shows the **event count trend** for that specific event. +- A **Cohort** perspective shows the cohort's **current size and status**, plus an **event trend filtered to that cohort's members**. +- A two-step **user lookup** workflow: search for a user by User ID, Device ID, or email prefix in the **User Search** tile, copy the **Amplitude ID** it returns, then paste it into the **User Activity** tile to see that user's recent event activity. These are two separate tiles because SquaredUp's dashboard framework has no way to automatically pass a search result into another tile's parameter — this is a manual copy/paste step by design, not a bug. + +## Prerequisites — getting your API key and secret key + +Amplitude API credentials are scoped to a single project, so each SquaredUp plugin instance monitors one Amplitude project. + +1. Sign in to Amplitude and open the project you want to monitor. +2. Go to **Settings → Projects**, select the project, then open its **General** settings tab. +3. Copy the **API Key** and **Secret Key** shown there. +4. Note whether your organization uses Amplitude's **US** or **EU** data center — this is usually visible in the URL you sign in at (`analytics.amplitude.com` for US, `analytics.eu.amplitude.com` for EU) or in your organization's data residency settings. + +No additional scopes need to be granted — the API key/secret key pair has access to all the read-only analytics endpoints this plugin uses. + +## Configuration fields + +| Field | What it is | Where to find it | Required | +| -------------- | ------------------------------------------------------------ | -------------------------------------------------- | -------- | +| **Region** | The data residency region your Amplitude project uses (US or EU). | The domain you sign in at, or your org's data residency settings. | Yes | +| **API Key** | Your Amplitude project's API key, used as the Basic Auth username. | Settings → Projects → [project] → General. | Yes | +| **Secret Key** | Your Amplitude project's secret key, used as the Basic Auth password. | Settings → Projects → [project] → General. | Yes | + +## What gets indexed + +| Object type | Represents | +| ------------------------ | ------------------------------------------------------------------------ | +| **Amplitude Event Type** | An event defined in the project's taxonomy schema. | +| **Amplitude Cohort** | A behavioral cohort (user segment) defined in the project. | + +## Known limitations + +- **One project per plugin instance.** Amplitude API keys are project-scoped, so monitoring multiple projects means adding this plugin multiple times, once per project. +- **Rate limits.** Amplitude enforces a concurrency limit of 5 requests across the Dashboard REST/Cohort APIs and a cost-based hourly limit. Very frequent refreshes of many tiles at once may be throttled (HTTP 429). +- **Funnel and retention analysis are not included.** These require multi-step chart configuration that doesn't map cleanly to a generic tile — this version covers active users, event trends, cohorts, and user lookups only. +- **User lookup is a manual two-step process.** There is no "browse all users" endpoint in Amplitude, and Amplitude's user-activity endpoint only accepts a numeric Amplitude ID (not an email or User ID directly) — so you search first in the User Search tile, then copy the Amplitude ID it returns into the User Activity tile yourself. SquaredUp's dashboard framework has no mechanism to bind a search result automatically into another tile's parameter. +- **Hidden taxonomy items are excluded.** Events or properties marked as hidden/visibility-restricted in Amplitude's taxonomy don't appear in the imported Event Types. diff --git a/plugins/Amplitude/v1/icon.svg b/plugins/Amplitude/v1/icon.svg new file mode 100644 index 00000000..7ed2e719 --- /dev/null +++ b/plugins/Amplitude/v1/icon.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/plugins/Amplitude/v1/indexDefinitions/default.json b/plugins/Amplitude/v1/indexDefinitions/default.json new file mode 100644 index 00000000..acd33e6c --- /dev/null +++ b/plugins/Amplitude/v1/indexDefinitions/default.json @@ -0,0 +1,46 @@ +{ + "steps": [ + { + "name": "eventTypes", + "dataStream": { + "name": "eventTypes" + }, + "timeframe": "none", + "objectMapping": { + "id": "event_type", + "name": "name", + "type": { + "value": "Amplitude Event Type" + }, + "properties": [ + "description", + { "category": "category.name" }, + "is_active" + ] + } + }, + { + "name": "cohorts", + "dataStream": { + "name": "cohorts" + }, + "timeframe": "none", + "objectMapping": { + "id": "id", + "name": "name", + "type": { + "value": "Amplitude Cohort" + }, + "properties": [ + "description", + "size", + { "cohortType": "type" }, + "published", + "archived", + "lastComputed", + "createdAt" + ] + } + } + ] +} diff --git a/plugins/Amplitude/v1/metadata.json b/plugins/Amplitude/v1/metadata.json new file mode 100644 index 00000000..12af1f99 --- /dev/null +++ b/plugins/Amplitude/v1/metadata.json @@ -0,0 +1,50 @@ +{ + "name": "amplitude", + "displayName": "Amplitude", + "version": "1.1.0", + "author": { + "name": "conor.richey", + "type": "community" + }, + "description": "Monitor your Amplitude project in SquaredUp - track active users, event trends, cohorts, and look up individual user activity.", + "category": "Analytics", + "type": "hybrid", + "schemaVersion": "2.1", + "importNotSupported": false, + "restrictedToPlatforms": [], + "keywords": [ + "amplitude", + "analytics", + "product analytics", + "events", + "cohorts", + "active users", + "user activity" + ], + "objectTypes": [ + "Amplitude Event Type", + "Amplitude Cohort" + ], + "links": [ + { + "category": "documentation", + "url": "https://github.com/squaredup/plugins/blob/main/plugins/Amplitude/v1/docs/README.md", + "label": "Help adding this plugin" + }, + { + "category": "source", + "url": "https://github.com/squaredup/plugins/tree/main/plugins/Amplitude", + "label": "Repository" + } + ], + "base": { + "plugin": "WebAPI", + "majorVersion": "1", + "config": { + "baseUrl": "{{region === 'eu' ? 'https://analytics.eu.amplitude.com' : 'https://amplitude.com'}}", + "authMode": "basic", + "basicAuthUsername": "{{apiKey}}", + "basicAuthPassword": "{{secretKey}}" + } + } +} diff --git a/plugins/Amplitude/v1/ui.json b/plugins/Amplitude/v1/ui.json new file mode 100644 index 00000000..f3108d6f --- /dev/null +++ b/plugins/Amplitude/v1/ui.json @@ -0,0 +1,40 @@ +[ + { + "type": "radio", + "name": "region", + "label": "Region", + "help": "The data residency region for your Amplitude project. Choose EU if your project uses Amplitude's EU data center, otherwise US.", + "defaultValue": "us", + "options": [ + { + "value": "us", + "label": "US (amplitude.com)" + }, + { + "value": "eu", + "label": "EU (analytics.eu.amplitude.com)" + } + ], + "validation": { + "required": true + } + }, + { + "type": "password", + "name": "apiKey", + "label": "API Key", + "help": "Your Amplitude project's API key. Find it at **Settings → Projects → [your project] → General**.", + "validation": { + "required": true + } + }, + { + "type": "password", + "name": "secretKey", + "label": "Secret Key", + "help": "Your Amplitude project's secret key, found alongside the API key at **Settings → Projects → [your project] → General**.", + "validation": { + "required": true + } + } +] From 823b34cb4efdc13ad390d48ddc36e21c8d1277fa Mon Sep 17 00:00:00 2001 From: Conor Richey Date: Wed, 5 Aug 2026 13:21:18 +0100 Subject: [PATCH 2/2] Address CodeRabbit review feedback - Fix eventCountHistory grouping bug: determine grouped vs ungrouped from context.config.groupByProperty instead of series.length, which incorrectly dropped the group label whenever a grouped property only returned one distinct value. - Simplify getArgs request construction in eventCountHistory.json and cohortEventHistory.json, dropping an embedded IIFE and a redundant Array.isArray check (autocomplete fields always return an array). - Rename validateAuth stream display name to noun-based 'Authentication Validation'. - Add example placeholders to userSearch, userActivity, and the plugin's apiKey/secretKey fields. - Remove hardcoded, project-specific default values (a SquaredUp internal event property and event name) from the Event Type and Cohort overview dashboards. Not applying two other suggestions from the same review pass: - Renaming 'Amplitude Event Type'/'Amplitude Cohort' source types to drop the plugin-name prefix goes against the established convention used by every other multi-object-type plugin in this repo. - No 'map' transformation mechanism exists in this plugin schema for eventTypes/eventProperties valueExpression columns; the current fallback ternary matches the documented pattern. --- .../Amplitude/v1/dataStreams/cohortEventHistory.json | 2 +- .../Amplitude/v1/dataStreams/eventCountHistory.json | 2 +- .../v1/dataStreams/scripts/eventCountHistory.js | 10 +++++++++- plugins/Amplitude/v1/dataStreams/userActivity.json | 1 + plugins/Amplitude/v1/dataStreams/userSearch.json | 1 + plugins/Amplitude/v1/dataStreams/validateAuth.json | 2 +- .../v1/defaultContent/cohortOverview.dash.json | 5 +---- .../v1/defaultContent/eventTypeOverview.dash.json | 3 +-- plugins/Amplitude/v1/ui.json | 2 ++ 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json b/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json index 6850b065..ff6d8139 100644 --- a/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json +++ b/plugins/Amplitude/v1/dataStreams/cohortEventHistory.json @@ -8,7 +8,7 @@ "httpMethod": "get", "endpointPath": "api/2/events/segmentation", "getArgs": [ - { "key": "e", "value": "{{JSON.stringify({event_type: Array.isArray(eventType) ? (eventType[0] && eventType[0].value) : eventType})}}" }, + { "key": "e", "value": "{{JSON.stringify({event_type: eventType && eventType[0] && eventType[0].value})}}" }, { "key": "s", "value": "{{JSON.stringify([{prop: 'userdata_cohort', op: 'is', values: [object.rawId]}])}}" }, { "key": "start", "value": "{{timeframe.start.slice(0,10).replace(/-/g,'')}}" }, { "key": "end", "value": "{{timeframe.end.slice(0,10).replace(/-/g,'')}}" }, diff --git a/plugins/Amplitude/v1/dataStreams/eventCountHistory.json b/plugins/Amplitude/v1/dataStreams/eventCountHistory.json index 0d3bd644..2d670929 100644 --- a/plugins/Amplitude/v1/dataStreams/eventCountHistory.json +++ b/plugins/Amplitude/v1/dataStreams/eventCountHistory.json @@ -8,7 +8,7 @@ "httpMethod": "get", "endpointPath": "api/2/events/segmentation", "getArgs": [ - { "key": "e", "value": "{{(function(){ var v = Array.isArray(groupByProperty) ? (groupByProperty[0] && groupByProperty[0].value) : groupByProperty; var e = {event_type: object.rawId}; if (v) { e.group_by = [{type: 'event', value: v}]; } return JSON.stringify(e); })()}}" }, + { "key": "e", "value": "{{JSON.stringify(groupByProperty && groupByProperty[0] ? {event_type: object.rawId, group_by: [{type: 'event', value: groupByProperty[0].value}]} : {event_type: object.rawId})}}" }, { "key": "start", "value": "{{timeframe.start.slice(0,10).replace(/-/g,'')}}" }, { "key": "end", "value": "{{timeframe.end.slice(0,10).replace(/-/g,'')}}" }, { "key": "i", "value": "1" }, diff --git a/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js b/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js index e9898090..133db821 100644 --- a/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js +++ b/plugins/Amplitude/v1/dataStreams/scripts/eventCountHistory.js @@ -13,11 +13,19 @@ // [eventIndex, label] tuple (since group_by is embedded per-event), not a // bare string. Zip each series against xValues and tag every row with its // group's label. +// +// Whether the request was grouped is read from context.config.groupByProperty +// (the tile's own selection), not from series.length - a grouped property +// that only has one distinct value in range still returns exactly one +// series, and series.length alone can't tell that apart from "ungrouped". const xValues = (data.data && data.data.xValues) || []; const series = (data.data && data.data.series) || []; const seriesLabels = (data.data && data.data.seriesLabels) || []; -if (series.length <= 1) { +const groupByProperty = context.config && context.config.groupByProperty; +const isGrouped = Boolean(groupByProperty && groupByProperty[0] && groupByProperty[0].value); + +if (!isGrouped) { // Ungrouped - identical output shape to before this change. const values = series[0] || []; result = xValues.map((date, i) => ({ diff --git a/plugins/Amplitude/v1/dataStreams/userActivity.json b/plugins/Amplitude/v1/dataStreams/userActivity.json index 63c79eea..0d8d3fc6 100644 --- a/plugins/Amplitude/v1/dataStreams/userActivity.json +++ b/plugins/Amplitude/v1/dataStreams/userActivity.json @@ -19,6 +19,7 @@ "name": "amplitudeId", "label": "Amplitude ID", "type": "text", + "placeholder": "123456789", "help": "The numeric Amplitude ID of the user to look up (not their email or User ID). Find it using the **User Search** tile first, then copy the **Amplitude ID** value from the matching row here.", "validation": { "required": true diff --git a/plugins/Amplitude/v1/dataStreams/userSearch.json b/plugins/Amplitude/v1/dataStreams/userSearch.json index 78b034f0..0b1afa48 100644 --- a/plugins/Amplitude/v1/dataStreams/userSearch.json +++ b/plugins/Amplitude/v1/dataStreams/userSearch.json @@ -16,6 +16,7 @@ "name": "identifier", "label": "User ID / Device ID / Email prefix", "type": "text", + "placeholder": "user@example.com", "help": "Search for a user by their User ID, Device ID, or an email/ID prefix. Copy the **Amplitude ID** from a matching row into the **User Activity** tile's parameter to see that user's event timeline.", "validation": { "required": true diff --git a/plugins/Amplitude/v1/dataStreams/validateAuth.json b/plugins/Amplitude/v1/dataStreams/validateAuth.json index a7b49a05..0b9a5da2 100644 --- a/plugins/Amplitude/v1/dataStreams/validateAuth.json +++ b/plugins/Amplitude/v1/dataStreams/validateAuth.json @@ -1,6 +1,6 @@ { "name": "validateAuth", - "displayName": "Validate Auth", + "displayName": "Authentication Validation", "description": "Returns the project's taxonomy event categories", "tags": ["Utility"], "baseDataSourceName": "httpRequestUnscoped", diff --git a/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json b/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json index adfc26a3..b50a4329 100644 --- a/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json +++ b/plugins/Amplitude/v1/defaultContent/cohortOverview.dash.json @@ -72,10 +72,7 @@ "dataStream": { "id": "{{dataStreams.[cohortEventHistory]}}", "name": "cohortEventHistory", - "pluginConfigId": "{{configId}}", - "dataSourceConfig": { - "eventType": [{ "value": "Dashboard Loaded", "label": "Dashboard Loaded" }] - } + "pluginConfigId": "{{configId}}" }, "scope": { "scope": "{{scopes.[Amplitude Cohorts]}}", diff --git a/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json b/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json index 42d04fc2..18511793 100644 --- a/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json +++ b/plugins/Amplitude/v1/defaultContent/eventTypeOverview.dash.json @@ -111,8 +111,7 @@ "name": "eventCountHistory", "pluginConfigId": "{{configId}}", "dataSourceConfig": { - "metric": "totals", - "groupByProperty": [{ "value": "[Amplitude] Element Text", "label": "[Amplitude] Element Text" }] + "metric": "totals" }, "group": { "by": [["groupValue", "uniqueValues"]], diff --git a/plugins/Amplitude/v1/ui.json b/plugins/Amplitude/v1/ui.json index f3108d6f..18ba7b1b 100644 --- a/plugins/Amplitude/v1/ui.json +++ b/plugins/Amplitude/v1/ui.json @@ -23,6 +23,7 @@ "type": "password", "name": "apiKey", "label": "API Key", + "placeholder": "1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p", "help": "Your Amplitude project's API key. Find it at **Settings → Projects → [your project] → General**.", "validation": { "required": true @@ -32,6 +33,7 @@ "type": "password", "name": "secretKey", "label": "Secret Key", + "placeholder": "0z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k", "help": "Your Amplitude project's secret key, found alongside the API key at **Settings → Projects → [your project] → General**.", "validation": { "required": true