mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
feat(triggers): add Gong webhook triggers for call events (#3984)
* feat(triggers): add Gong webhook triggers for call events * fix(triggers): reorder Gong trigger spread and dropdown options * fix(triggers): resolve Biome lint errors in Gong trigger files * json
This commit is contained in:
@@ -4106,8 +4106,19 @@
|
||||
}
|
||||
],
|
||||
"operationCount": 18,
|
||||
"triggers": [],
|
||||
"triggerCount": 0,
|
||||
"triggers": [
|
||||
{
|
||||
"id": "gong_webhook",
|
||||
"name": "Gong Webhook",
|
||||
"description": "Generic webhook trigger for all Gong events"
|
||||
},
|
||||
{
|
||||
"id": "gong_call_completed",
|
||||
"name": "Gong Call Completed",
|
||||
"description": "Trigger workflow when a call is completed and processed in Gong"
|
||||
}
|
||||
],
|
||||
"triggerCount": 2,
|
||||
"authType": "none",
|
||||
"category": "tools",
|
||||
"integrationType": "sales-intelligence",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { GongIcon } from '@/components/icons'
|
||||
import { AuthMode, type BlockConfig, IntegrationType } from '@/blocks/types'
|
||||
import type { GongResponse } from '@/tools/gong/types'
|
||||
import { getTrigger } from '@/triggers'
|
||||
|
||||
export const GongBlock: BlockConfig<GongResponse> = {
|
||||
type: 'gong',
|
||||
@@ -15,7 +16,10 @@ export const GongBlock: BlockConfig<GongResponse> = {
|
||||
tags: ['meeting', 'sales-engagement', 'speech-to-text'],
|
||||
bgColor: '#8039DF',
|
||||
icon: GongIcon,
|
||||
triggerAllowed: true,
|
||||
subBlocks: [
|
||||
...getTrigger('gong_webhook').subBlocks,
|
||||
...getTrigger('gong_call_completed').subBlocks,
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
@@ -568,4 +572,8 @@ Return ONLY the timestamp string in ISO 8601 format - no explanations, no quotes
|
||||
description: 'Gong API response data',
|
||||
},
|
||||
},
|
||||
triggers: {
|
||||
enabled: true,
|
||||
available: ['gong_webhook', 'gong_call_completed'],
|
||||
},
|
||||
}
|
||||
|
||||
25
apps/sim/lib/webhooks/providers/gong.ts
Normal file
25
apps/sim/lib/webhooks/providers/gong.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type {
|
||||
FormatInputContext,
|
||||
FormatInputResult,
|
||||
WebhookProviderHandler,
|
||||
} from '@/lib/webhooks/providers/types'
|
||||
|
||||
export const gongHandler: WebhookProviderHandler = {
|
||||
async formatInput({ body }: FormatInputContext): Promise<FormatInputResult> {
|
||||
const b = body as Record<string, unknown>
|
||||
const callData = b.callData as Record<string, unknown> | undefined
|
||||
const metaData = (callData?.metaData as Record<string, unknown>) || {}
|
||||
const content = callData?.content as Record<string, unknown> | undefined
|
||||
|
||||
return {
|
||||
input: {
|
||||
isTest: b.isTest ?? false,
|
||||
callData,
|
||||
metaData,
|
||||
parties: (callData?.parties as unknown[]) || [],
|
||||
context: (callData?.context as unknown[]) || [],
|
||||
trackers: (content?.trackers as unknown[]) || [],
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { firefliesHandler } from '@/lib/webhooks/providers/fireflies'
|
||||
import { genericHandler } from '@/lib/webhooks/providers/generic'
|
||||
import { githubHandler } from '@/lib/webhooks/providers/github'
|
||||
import { gmailHandler } from '@/lib/webhooks/providers/gmail'
|
||||
import { gongHandler } from '@/lib/webhooks/providers/gong'
|
||||
import { googleFormsHandler } from '@/lib/webhooks/providers/google-forms'
|
||||
import { grainHandler } from '@/lib/webhooks/providers/grain'
|
||||
import { hubspotHandler } from '@/lib/webhooks/providers/hubspot'
|
||||
@@ -48,6 +49,7 @@ const PROVIDER_HANDLERS: Record<string, WebhookProviderHandler> = {
|
||||
generic: genericHandler,
|
||||
gmail: gmailHandler,
|
||||
github: githubHandler,
|
||||
gong: gongHandler,
|
||||
google_forms: googleFormsHandler,
|
||||
fathom: fathomHandler,
|
||||
grain: grainHandler,
|
||||
|
||||
68
apps/sim/triggers/gong/call_completed.ts
Normal file
68
apps/sim/triggers/gong/call_completed.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { GongIcon } from '@/components/icons'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import { buildCallOutputs, gongSetupInstructions } from './utils'
|
||||
|
||||
/**
|
||||
* Gong Call Completed Trigger
|
||||
*
|
||||
* Secondary trigger - does NOT include the dropdown (the generic webhook trigger has it).
|
||||
* Fires when a call matching the configured rule is processed in Gong.
|
||||
*/
|
||||
export const gongCallCompletedTrigger: TriggerConfig = {
|
||||
id: 'gong_call_completed',
|
||||
name: 'Gong Call Completed',
|
||||
provider: 'gong',
|
||||
description: 'Trigger workflow when a call is completed and processed in Gong',
|
||||
version: '1.0.0',
|
||||
icon: GongIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'webhookUrlDisplay',
|
||||
title: 'Webhook URL',
|
||||
type: 'short-input',
|
||||
readOnly: true,
|
||||
showCopyButton: true,
|
||||
useWebhookUrl: true,
|
||||
placeholder: 'Webhook URL will be generated',
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_call_completed',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerSave',
|
||||
title: '',
|
||||
type: 'trigger-save',
|
||||
hideFromPreview: true,
|
||||
mode: 'trigger',
|
||||
triggerId: 'gong_call_completed',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_call_completed',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: gongSetupInstructions('Call Completed'),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_call_completed',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: buildCallOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
2
apps/sim/triggers/gong/index.ts
Normal file
2
apps/sim/triggers/gong/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { gongCallCompletedTrigger } from './call_completed'
|
||||
export { gongWebhookTrigger } from './webhook'
|
||||
84
apps/sim/triggers/gong/utils.ts
Normal file
84
apps/sim/triggers/gong/utils.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { TriggerOutput } from '@/triggers/types'
|
||||
|
||||
/**
|
||||
* Shared trigger dropdown options for all Gong triggers
|
||||
*/
|
||||
export const gongTriggerOptions = [
|
||||
{ label: 'General Webhook (All Events)', id: 'gong_webhook' },
|
||||
{ label: 'Call Completed', id: 'gong_call_completed' },
|
||||
]
|
||||
|
||||
/**
|
||||
* Generate setup instructions for a specific Gong event type
|
||||
*/
|
||||
export function gongSetupInstructions(eventType: string): string {
|
||||
const instructions = [
|
||||
'<strong>Note:</strong> You need admin access to Gong to set up webhooks. See the <a href="https://help.gong.io/docs/create-a-webhook-rule" target="_blank" rel="noopener noreferrer">Gong webhook documentation</a> for details.',
|
||||
'Copy the <strong>Webhook URL</strong> above.',
|
||||
'In Gong, go to <strong>Admin center > Settings > Ecosystem > Automation rules</strong>.',
|
||||
'Click <strong>"+ Add Rule"</strong> to create a new automation rule.',
|
||||
`Configure rule filters to match <strong>${eventType}</strong> calls.`,
|
||||
'Under Actions, select <strong>"Fire webhook"</strong>.',
|
||||
'Paste the Webhook URL into the destination field.',
|
||||
'Choose an authentication method (URL includes key or Signed JWT header).',
|
||||
'Save the rule and click <strong>"Save"</strong> above to activate your trigger.',
|
||||
]
|
||||
|
||||
return instructions
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3">${index === 0 ? instruction : `<strong>${index}.</strong> ${instruction}`}</div>`
|
||||
)
|
||||
.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* Build output schema for call events.
|
||||
* Gong webhooks deliver call data including metadata, participants, context, and content analysis.
|
||||
*/
|
||||
export function buildCallOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
isTest: {
|
||||
type: 'boolean',
|
||||
description: 'Whether this is a test webhook from the Gong UI',
|
||||
},
|
||||
callData: {
|
||||
type: 'json',
|
||||
description: 'Full call data object',
|
||||
},
|
||||
metaData: {
|
||||
id: { type: 'string', description: 'Gong call ID' },
|
||||
url: { type: 'string', description: 'URL to the call in Gong' },
|
||||
title: { type: 'string', description: 'Call title' },
|
||||
scheduled: { type: 'string', description: 'Scheduled start time (ISO 8601)' },
|
||||
started: { type: 'string', description: 'Actual start time (ISO 8601)' },
|
||||
duration: { type: 'number', description: 'Call duration in seconds' },
|
||||
primaryUserId: { type: 'string', description: 'Primary Gong user ID' },
|
||||
direction: { type: 'string', description: 'Call direction (Conference, Call, etc.)' },
|
||||
system: { type: 'string', description: 'Meeting system (Zoom, Teams, etc.)' },
|
||||
scope: { type: 'string', description: 'Call scope (External or Internal)' },
|
||||
media: { type: 'string', description: 'Media type (Video or Audio)' },
|
||||
language: { type: 'string', description: 'Call language code' },
|
||||
},
|
||||
parties: {
|
||||
type: 'array',
|
||||
description: 'Array of call participants with name, email, title, and affiliation',
|
||||
},
|
||||
context: {
|
||||
type: 'array',
|
||||
description: 'Array of CRM context objects (Salesforce opportunities, accounts, etc.)',
|
||||
},
|
||||
trackers: {
|
||||
type: 'array',
|
||||
description: 'Array of tracked topics/keywords with counts',
|
||||
},
|
||||
} as Record<string, TriggerOutput>
|
||||
}
|
||||
|
||||
/**
|
||||
* Build output schema for generic webhook events.
|
||||
* Uses the same call output structure since Gong webhooks primarily deliver call data.
|
||||
*/
|
||||
export function buildGenericOutputs(): Record<string, TriggerOutput> {
|
||||
return buildCallOutputs()
|
||||
}
|
||||
77
apps/sim/triggers/gong/webhook.ts
Normal file
77
apps/sim/triggers/gong/webhook.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { GongIcon } from '@/components/icons'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
import { buildGenericOutputs, gongSetupInstructions, gongTriggerOptions } from './utils'
|
||||
|
||||
/**
|
||||
* Gong Generic Webhook Trigger
|
||||
*
|
||||
* Primary trigger - includes the dropdown for selecting trigger type.
|
||||
* Accepts all webhook events from Gong automation rules.
|
||||
*/
|
||||
export const gongWebhookTrigger: TriggerConfig = {
|
||||
id: 'gong_webhook',
|
||||
name: 'Gong Webhook',
|
||||
provider: 'gong',
|
||||
description: 'Generic webhook trigger for all Gong events',
|
||||
version: '1.0.0',
|
||||
icon: GongIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'selectedTriggerId',
|
||||
title: 'Trigger Type',
|
||||
type: 'dropdown',
|
||||
mode: 'trigger',
|
||||
options: gongTriggerOptions,
|
||||
value: () => 'gong_webhook',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'webhookUrlDisplay',
|
||||
title: 'Webhook URL',
|
||||
type: 'short-input',
|
||||
readOnly: true,
|
||||
showCopyButton: true,
|
||||
useWebhookUrl: true,
|
||||
placeholder: 'Webhook URL will be generated',
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_webhook',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerSave',
|
||||
title: '',
|
||||
type: 'trigger-save',
|
||||
hideFromPreview: true,
|
||||
mode: 'trigger',
|
||||
triggerId: 'gong_webhook',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_webhook',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: gongSetupInstructions('All Events'),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'gong_webhook',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: buildGenericOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -89,6 +89,7 @@ import {
|
||||
githubWorkflowRunTrigger,
|
||||
} from '@/triggers/github'
|
||||
import { gmailPollingTrigger } from '@/triggers/gmail'
|
||||
import { gongCallCompletedTrigger, gongWebhookTrigger } from '@/triggers/gong'
|
||||
import { googleFormsWebhookTrigger } from '@/triggers/googleforms'
|
||||
import {
|
||||
grainHighlightCreatedTrigger,
|
||||
@@ -281,6 +282,8 @@ export const TRIGGER_REGISTRY: TriggerRegistry = {
|
||||
fathom_new_meeting: fathomNewMeetingTrigger,
|
||||
fathom_webhook: fathomWebhookTrigger,
|
||||
gmail_poller: gmailPollingTrigger,
|
||||
gong_call_completed: gongCallCompletedTrigger,
|
||||
gong_webhook: gongWebhookTrigger,
|
||||
grain_webhook: grainWebhookTrigger,
|
||||
grain_item_added: grainItemAddedTrigger,
|
||||
grain_item_updated: grainItemUpdatedTrigger,
|
||||
|
||||
Reference in New Issue
Block a user