Skip to content

Commit f913711

Browse files
STRATCONN-6541 [Appcues] server side integration (#3581)
* Add Appcues (Actions) server-side destination Create new Appcues destination with single 'send' action that supports: - Track events (with event_name, properties) - Identify calls (with user_traits) - Group calls (with groupId, group_traits) The action can send up to 3 requests per Segment event based on populated fields. Supports both US and EU regional endpoints. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Refactor Appcues destination with code organization improvements - Move types to types.ts and functions to functions.ts - Rename event_name field to event for consistency - Use spread operator syntax instead of conditional assignments - Add context, integrations, timestamp, and messageId fields - Add conditional default mapping for user_traits (context.traits first, then traits) - Remove default mapping for group_traits - Update tests to cover new fields and conditional mappings Co-Authored-By: Claude Opus 4.6 <[email protected]> * Refactor Appcues send action to separate concerns - Move field definitions to send/fields.ts - Move perform function logic to functions.ts as performSend() - Simplify send/index.ts to only contain action configuration This improves code organization and makes the action easier to maintain. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Move types and functions into send action folder - Move types.ts and functions.ts into send/ folder (action-specific) - Create separate types for track, identify, and group requests - Replace 'any' with 'unknown' for better type safety - BaseAppcuesRequest shared fields across all request types - AppcuesTrackRequest, AppcuesIdentifyRequest, AppcuesGroupRequest for specific request types Co-Authored-By: Claude Opus 4.6 <[email protected]> * Refine types and naming conventions - Make AppcuesIdentifyRequest traits optional - Rename performSend to send for clarity - Change fields type from ActionDefinition['fields'] to Record<string, InputField> - Remove unused imports in fields.ts Co-Authored-By: Claude Opus 4.6 <[email protected]> * Hide endpoint URLs behind region selection - Create constants.ts with REGION_ENDPOINTS mapping - Change authentication field from 'endpoint' to 'region' - Store only region identifiers ('US', 'EU') in settings - Map region to actual URL at runtime in send function - Add validation for invalid regions - Update all tests to use region instead of full URLs - Add test for invalid region error handling Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add event type field with conditional requirements - Add required 'type' field with choices: track, page, screen, identify, group - Add 'name' field that only displays for page/screen events - Make 'event' required when type is 'track' - Make 'groupId' required when type is 'group' - Add AppcuesPageRequest and AppcuesScreenRequest types - Update send function to build appropriate request based on type - Always send identify call if user_traits is populated (for non-identify events) - Always send group call if groupId and group_traits are populated (for non-group events) - Add comprehensive tests for all event types and combinations - Add error handling for missing required fields and invalid types Co-Authored-By: Claude Opus 4.6 <[email protected]> * Make required attribute conditional for event and groupId fields - Change event field required from boolean to conditional object - Change groupId field required from boolean to conditional object - Both now use same conditions as depends_on for consistency - event is required only when type is 'track' - groupId is required only when type is 'group' - Keeps depends_on rules for field visibility unchanged Co-Authored-By: Claude Opus 4.6 <[email protected]> * Make properties field visible only for track, page, and screen events - Add depends_on rule to properties field - Field now only displays when type is track, page, or screen - Hidden for identify and group event types Co-Authored-By: Claude Opus 4.6 <[email protected]> * Make groupId optional for group events - Remove required attribute from groupId field - Update send function to skip group request if groupId is not provided - Update test to verify no request is sent when groupId is missing - Keep depends_on rule for field visibility (only shows for type = group) Co-Authored-By: Claude Opus 4.6 <[email protected]> * Make user_traits field visible only for track, page, screen, and identify events - Add depends_on rule to user_traits field - Field now only displays when type is track, page, screen, or identify - Hidden for group event type Co-Authored-By: Claude Opus 4.6 <[email protected]> * Refactor send function to reduce redundancy - Replace switch statement with if/else if chain for better readability - Make additional event logic more explicit with clear comments - Use array.includes() for track/page/screen check - Clarify event sending rules: - Primary event always sent based on type - Additional identify sent for track, page, screen if user_traits present - Additional group sent for non-group types if groupId and group_traits present Co-Authored-By: Claude Opus 4.6 <[email protected]> * Merge redundant identify and group conditions - Merge identify logic: single condition handles both identify type and track/page/screen with user_traits - Merge group logic: single condition handles both group type and other types with groupId and group_traits - Replace if/else if chain with independent if statements for each event type - Move invalid type validation to end after all event processing - Reduces code duplication and makes logic flow clearer Co-Authored-By: Claude Opus 4.6 <[email protected]> * Update group event logic to match identify pattern - Group events now sent for type === 'group' OR track/page/screen with groupId - Remove depends_on visibility restriction from groupId field (always visible) - group_traits already has no visibility restriction (always visible) - Group call includes optional group_traits when present - Mirrors identify logic: track/page/screen can trigger both identify and group Co-Authored-By: Claude Opus 4.6 <[email protected]> * Remove comments and update error handling - Remove all code comments - Add back event name validation for track events - Use PayloadValidationError for all validation errors - Remove invalid type validation (handled by field choices) - Keep endpoint validation with PayloadValidationError Co-Authored-By: Claude Opus 4.6 <[email protected]> * Condense nested group condition into single statement - Combine nested if statements into single condition - Check groupId && (type === 'group' || type in track/page/screen) - Removes redundant inner groupId check Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add presets for all 5 event types - Create presets.ts with 5 presets: Track, Page, Screen, Identify, Group - Each preset subscribes to its corresponding event type - All presets use defaultValues from send action fields - Group preset includes custom mapping for group_traits to $.traits - Import and register presets in destination index.ts Co-Authored-By: Claude Opus 4.6 <[email protected]> * Simplify integrations field description - Update description from "Integrations object to control which destinations receive this event" to "Integrations object" - Update both fields.ts and generated-types.ts Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix unit tests to match current implementation - Remove invalid event type test (validation removed from code) - Simplify groupId test to not expect error (groupId now optional) - Remove duplicate test cases - Update test names for clarity - All 12 tests now match current send function behavior Co-Authored-By: Claude Opus 4.6 <[email protected]> * Code complete * remobing registration --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
1 parent 592a698 commit f913711

11 files changed

Lines changed: 998 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Destination from '../index'
2+
3+
describe('Appcues (Actions)', () => {
4+
it('should be a valid destination', () => {
5+
expect(Destination.name).toBe('Appcues (Actions)')
6+
expect(Destination.slug).toBe('actions-appcues')
7+
expect(Destination.mode).toBe('cloud')
8+
expect(Destination.actions.send).toBeDefined()
9+
})
10+
11+
it('should have correct authentication fields', () => {
12+
expect(Destination.authentication.scheme).toBe('custom')
13+
expect(Destination.authentication.fields.apiKey).toBeDefined()
14+
expect(Destination.authentication.fields.region).toBeDefined()
15+
})
16+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const APPCUES_US_ENDPOINT = 'https://segment.appcues.com/v1/segment'
2+
export const APPCUES_EU_ENDPOINT = 'https://segment.eu.appcues.com/v1/segment'
3+
4+
export const REGION_ENDPOINTS: Record<string, string> = {
5+
US: APPCUES_US_ENDPOINT,
6+
EU: APPCUES_EU_ENDPOINT
7+
}

packages/destination-actions/src/destinations/appcues/generated-types.ts

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { DestinationDefinition } from '@segment/actions-core'
2+
import type { Settings } from './generated-types'
3+
import send from './send'
4+
import { presets } from './presets'
5+
6+
const destination: DestinationDefinition<Settings> = {
7+
name: 'Appcues (Actions)',
8+
slug: 'actions-appcues',
9+
mode: 'cloud',
10+
description: 'Send events to Appcues.',
11+
12+
authentication: {
13+
scheme: 'custom',
14+
fields: {
15+
apiKey: {
16+
label: 'API Key',
17+
description: 'Your Appcues API key.',
18+
type: 'password',
19+
required: true
20+
},
21+
region: {
22+
label: 'Region',
23+
description: 'Select the region for your Appcues account.',
24+
type: 'string',
25+
required: true,
26+
choices: [
27+
{ label: 'US', value: 'US' },
28+
{ label: 'EU', value: 'EU' }
29+
],
30+
default: 'US'
31+
}
32+
}
33+
},
34+
35+
presets,
36+
37+
actions: {
38+
send
39+
}
40+
}
41+
42+
export default destination
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { DestinationDefinition } from '@segment/actions-core'
2+
import { defaultValues } from '@segment/actions-core'
3+
import send from './send'
4+
5+
export const presets: DestinationDefinition['presets'] = [
6+
{
7+
name: 'Track Calls',
8+
subscribe: 'type = "track"',
9+
partnerAction: 'send',
10+
mapping: defaultValues(send.fields),
11+
type: 'automatic'
12+
},
13+
{
14+
name: 'Page Calls',
15+
subscribe: 'type = "page"',
16+
partnerAction: 'send',
17+
mapping: defaultValues(send.fields),
18+
type: 'automatic'
19+
},
20+
{
21+
name: 'Screen Calls',
22+
subscribe: 'type = "screen"',
23+
partnerAction: 'send',
24+
mapping: defaultValues(send.fields),
25+
type: 'automatic'
26+
},
27+
{
28+
name: 'Identify Calls',
29+
subscribe: 'type = "identify"',
30+
partnerAction: 'send',
31+
mapping: defaultValues(send.fields),
32+
type: 'automatic'
33+
},
34+
{
35+
name: 'Group Calls',
36+
subscribe: 'type = "group"',
37+
partnerAction: 'send',
38+
mapping: {
39+
...defaultValues(send.fields),
40+
group_traits: {
41+
'@path': '$.traits'
42+
}
43+
},
44+
type: 'automatic'
45+
}
46+
]

0 commit comments

Comments
 (0)