feat(cdp): template customizability by the code_language (#35129)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
|
Before Width: | Height: | Size: 439 KiB After Width: | Height: | Size: 912 KiB |
|
Before Width: | Height: | Size: 428 KiB After Width: | Height: | Size: 889 KiB |
|
Before Width: | Height: | Size: 447 KiB After Width: | Height: | Size: 879 KiB |
|
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 866 KiB |
|
Before Width: | Height: | Size: 385 KiB After Width: | Height: | Size: 858 KiB |
|
Before Width: | Height: | Size: 375 KiB After Width: | Height: | Size: 836 KiB |
|
Before Width: | Height: | Size: 339 KiB After Width: | Height: | Size: 770 KiB |
|
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 756 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
@@ -50,6 +50,7 @@ export const nonHogFunctionTemplatesLogic = kea<nonHogFunctionTemplatesLogicType
|
||||
</>
|
||||
),
|
||||
hog: '',
|
||||
code_language: 'hog',
|
||||
inputs_schema: [],
|
||||
filters: null,
|
||||
masking: null,
|
||||
@@ -71,6 +72,7 @@ export const nonHogFunctionTemplatesLogic = kea<nonHogFunctionTemplatesLogicType
|
||||
</>
|
||||
),
|
||||
hog: '',
|
||||
code_language: 'hog',
|
||||
inputs_schema: [],
|
||||
filters: null,
|
||||
masking: null,
|
||||
@@ -100,6 +102,7 @@ export const nonHogFunctionTemplatesLogic = kea<nonHogFunctionTemplatesLogicType
|
||||
icon_url: BATCH_EXPORT_ICON_MAP[service],
|
||||
status: 'stable',
|
||||
hog: '',
|
||||
code_language: 'hog',
|
||||
inputs_schema: [],
|
||||
filters: null,
|
||||
masking: null,
|
||||
|
||||
@@ -129,8 +129,6 @@ export function HogFunctionConfiguration({
|
||||
}
|
||||
|
||||
const isLegacyPlugin = (template?.id || hogFunction?.template?.id)?.startsWith('plugin-')
|
||||
const isSegmentPlugin = (template?.id || hogFunction?.template?.id)?.startsWith('segment-')
|
||||
const isNativePlugin = (template?.id || hogFunction?.template?.id)?.startsWith('native-')
|
||||
|
||||
const headerButtons = (
|
||||
<>
|
||||
@@ -212,12 +210,9 @@ export function HogFunctionConfiguration({
|
||||
)
|
||||
const canEditSource =
|
||||
displayOptions.canEditSource ??
|
||||
// Never allow editing for legacy plugins
|
||||
(!isLegacyPlugin &&
|
||||
!isNativePlugin &&
|
||||
!isSegmentPlugin &&
|
||||
(['destination', 'email', 'site_destination', 'site_app', 'source_webhook'].includes(type) ||
|
||||
(type === 'transformation' && canEditTransformationHogCode)))
|
||||
(['email', 'site_destination', 'site_app', 'source_webhook'].includes(type) ||
|
||||
(type === 'transformation' && canEditTransformationHogCode) ||
|
||||
(type === 'destination' && (template?.code_language || hogFunction?.template?.code_language) === 'hog'))
|
||||
const showTesting =
|
||||
displayOptions.showTesting ?? ['destination', 'internal_destination', 'transformation', 'email'].includes(type)
|
||||
|
||||
@@ -330,8 +325,9 @@ export function HogFunctionConfiguration({
|
||||
<LemonTextArea disabled={loading} />
|
||||
</LemonField>
|
||||
|
||||
{isLegacyPlugin || isSegmentPlugin ? null : hogFunction?.template &&
|
||||
!hogFunction.template.id.startsWith('template-blank-') ? (
|
||||
{hogFunction?.template?.code_language === 'hog' &&
|
||||
hogFunction?.template &&
|
||||
!hogFunction.template.id.startsWith('template-blank-') ? (
|
||||
<LemonDropdown
|
||||
showArrow
|
||||
overlay={
|
||||
|
||||
@@ -28,6 +28,7 @@ const HOG_TEMPLATE: HogFunctionTemplateType = {
|
||||
name: 'HTTP Webhook',
|
||||
description: 'Sends a webhook templated by the incoming event data',
|
||||
hog: "let res := fetch(inputs.url, {\n 'headers': inputs.headers,\n 'body': inputs.body,\n 'method': inputs.method\n});\n\nif (inputs.debug) {\n print('Response', res.status, res.body);\n}",
|
||||
code_language: 'hog',
|
||||
inputs_schema: [
|
||||
{
|
||||
key: 'url',
|
||||
|
||||
@@ -84,6 +84,7 @@ const NEW_FUNCTION_TEMPLATE: HogFunctionTemplateType = {
|
||||
name: '',
|
||||
description: '',
|
||||
inputs_schema: [],
|
||||
code_language: 'hog',
|
||||
hog: "print('Hello, world!');",
|
||||
status: 'stable',
|
||||
}
|
||||
|
||||
@@ -5235,6 +5235,7 @@ export type HogFunctionTemplateType = Pick<
|
||||
free: boolean
|
||||
mapping_templates?: HogFunctionMappingTemplateType[]
|
||||
description?: string | JSX.Element
|
||||
code_language: 'javascript' | 'hog'
|
||||
}
|
||||
|
||||
export type HogFunctionTemplateWithSubTemplateType = HogFunctionTemplateType & {
|
||||
|
||||
@@ -142,6 +142,7 @@ export const createHogFunctionTemplate = (
|
||||
type: 'destination',
|
||||
name: 'Hog Function Template',
|
||||
description: 'Hog Function Template',
|
||||
code_language: 'hog',
|
||||
hog: 'Hog Function Template',
|
||||
inputs_schema: [],
|
||||
category: [],
|
||||
@@ -167,7 +168,7 @@ export const insertHogFunctionTemplate = async (
|
||||
name: template.name,
|
||||
description: template.description,
|
||||
code: template.hog,
|
||||
code_language: 'hog',
|
||||
code_language: template.code_language,
|
||||
status: template.status,
|
||||
free: template.free,
|
||||
category: template.category,
|
||||
|
||||
@@ -192,6 +192,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.test_property := 'test_value'
|
||||
@@ -283,6 +284,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.test_property := 'test_value'
|
||||
@@ -299,6 +301,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.test_property := null
|
||||
@@ -367,6 +370,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
return event
|
||||
`,
|
||||
@@ -381,6 +385,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
return event
|
||||
`,
|
||||
@@ -395,6 +400,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template that adds a test property',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
return event
|
||||
`,
|
||||
@@ -472,6 +478,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Success Template',
|
||||
description: 'A template that should succeed',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.success := true
|
||||
@@ -489,6 +496,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Failing Template',
|
||||
description: 'A template that should fail',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Return invalid result (not an object with properties)
|
||||
return "invalid"
|
||||
@@ -552,6 +560,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Input Setter',
|
||||
description: 'A template that sets the inputs',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.inputs := {
|
||||
@@ -645,6 +654,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Success Template',
|
||||
description: 'A template that should succeed',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.success := true
|
||||
@@ -1330,6 +1340,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.test_property := true
|
||||
@@ -1372,6 +1383,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A simple test template',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.test_property := true
|
||||
@@ -1485,6 +1497,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Disabled Test Template',
|
||||
description: 'A test template that should be skipped due to disabled state',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.should_not_be_set := true
|
||||
@@ -1542,6 +1555,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Healthy Test Template',
|
||||
description: 'A test template that should execute because state is healthy',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.should_be_set := true
|
||||
@@ -1600,6 +1614,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Test Template',
|
||||
description: 'A test template that should execute despite disabled state because hogwatcher is off',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.should_be_set := true
|
||||
@@ -1655,6 +1670,7 @@ describe('HogTransformer', () => {
|
||||
name: 'Capture Template',
|
||||
description: 'A template that captures an event',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let returnEvent := event
|
||||
returnEvent.properties.captured := true
|
||||
|
||||
@@ -15,6 +15,7 @@ export const customerioPlugin: LegacyDestinationPlugin = {
|
||||
description: 'This plugin will send events to Customer.io.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/customerio-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const hubspotPlugin: LegacyDestinationPlugin = {
|
||||
description: 'This plugin will send events to Hubspot.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/hubspot-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const intercomPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send event data to Intercom on PostHog events.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/posthog-intercom-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const pacePlugin: LegacyDestinationPlugin = {
|
||||
'Pace is a tool that equips sellers with relevant insights at the right time so they can spend time growing revenue. It allows them to convert, retain, and grow customers by prioritizing time and effort on the users who need it most.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/pace-posthog-integration/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const avoPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Export PostHog events to Avo inspector.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/posthog-avo-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const brazePlugin: LegacyDestinationPlugin = {
|
||||
description: 'Import analytics from Braze and export PostHog events to Braze.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/posthog-braze-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const engagePlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send user and event data to Engage for personalized engagement.',
|
||||
icon_url: 'https://raw.githubusercontent.com/engage-so/posthog-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const gcsPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Sends events to GCS on ingestion.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/posthog-gcs-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const laudspeakerPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send event data to Laudspeaker',
|
||||
icon_url: 'https://raw.githubusercontent.com/laudspeaker/laudspeaker-posthog-plugin/master/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const patternsPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send events data to Patterns App',
|
||||
icon_url: 'https://raw.githubusercontent.com/patterns-app/posthog-patterns-app/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const replicatorPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Replicate PostHog event stream in another PostHog instance',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/posthog-plugin-replicator/master/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const pubsubPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Sends events to a Pub/Sub topic on ingestion.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/pubsub-plugin/master/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const rudderstackPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send event data to RudderStack',
|
||||
icon_url: 'https://raw.githubusercontent.com/rudderlabs/rudderstack-posthog-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const salesforcePlugin: LegacyDestinationPlugin = {
|
||||
description: 'Relay PostHog events to Salesforce',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/salesforce-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const sendgridPlugin: LegacyDestinationPlugin = {
|
||||
description: 'Send emails and user data to Sendgrid when you identify users using PostHog.',
|
||||
icon_url: 'https://raw.githubusercontent.com/PostHog/sendgrid-plugin/main/logo.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const pluginStonlyCleanCampaignName: LegacyTransformationPlugin = {
|
||||
description: 'Clean campaign name',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ export const currencyNormalizationPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Normalizes currency amounts. NOTE: This plugin is deprecated.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/currency-normalization-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const downsamplingPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Reduces event volume coming into PostHog',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/downsampling-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const dropEventsOnPropertyPlugin: LegacyTransformationPlugin = {
|
||||
'This plugin will drop any events that have a specific key. If you supply a value, it will drop any event with the combination of they key and the value. You will not be billed for any events that this plugin drops.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/drop-events-on-property-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const firstTimeEventTrackerPlugin: LegacyTransformationPlugin = {
|
||||
'This plugin will flatten all nested properties into a single property. You will not be billed for any events that this plugin drops.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/flatten-properties-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ export const flattenPropertiesPlugin: LegacyTransformationPlugin = {
|
||||
'This plugin will flatten all nested properties into a single property. You will not be billed for any events that this plugin drops.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/flatten-properties-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ export const languageUrlSplitterApp: LegacyTransformationPlugin = {
|
||||
description: 'Replace the language from the URL with a custom value',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ export const phShotgunProcessEventApp: LegacyTransformationPlugin = {
|
||||
description: 'Process Shotgun events',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@ export const pluginAdvancedGeoip: LegacyTransformationPlugin = {
|
||||
'This plugin will add advanced geoip properties to your events. You will not be billed for any events that this plugin drops.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/advanced-geoip-plugin/main/logo.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const pluginNetdataEventProcessing: LegacyTransformationPlugin = {
|
||||
description: 'Event processing for Netdata',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ export const pluginStonlyUtmExtractor: LegacyTransformationPlugin = {
|
||||
description: 'UTM extractor',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogAnonymization: LegacyTransformationPlugin = {
|
||||
description: 'Anonymize your data.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogAppUnduplicator: LegacyTransformationPlugin = {
|
||||
description: 'Prevent duplicates in your data when ingesting.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ export const posthogAppUrlParametersToEventProperties: LegacyTransformationPlugi
|
||||
icon_url:
|
||||
'https://raw.githubusercontent.com/posthog/posthog-app-url-parameters-to-event-properties/main/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogFilterOutPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Filter out events where property values satisfy the given condition',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/posthog-filter-out-plugin/main/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogPluginGeoip: LegacyTransformationPlugin = {
|
||||
description: 'Enrich events with GeoIP data',
|
||||
icon_url: '/static/transformations/geoip.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogPluginSnowplowRefererParser: LegacyTransformationPlugin = {
|
||||
description: 'UTM referrer snowplow parser',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ export const posthogRouteCensorPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Removes segments of URLs based on route patterns.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ export const posthogUrlNormalizerPlugin: LegacyTransformationPlugin = {
|
||||
'Normalize the format of urls in your application allowing you to more easily compare them in insights.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/posthog-url-normalizer-plugin/main/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ export const propertyFilterPlugin: LegacyTransformationPlugin = {
|
||||
description: 'This plugin will set all configured properties to null inside an ingested event.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/property-filter-plugin/dev/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ export const semverFlattenerPlugin: LegacyTransformationPlugin = {
|
||||
description: 'This plugin will flatten semver versions in the specified properties.',
|
||||
icon_url: '/static/transformations/semver-flattener.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ export const taxonomyPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Standardize your event names into a single pattern.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/taxonomy-plugin/main/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ export const timestampParserPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Parse your event timestamps into useful date properties.',
|
||||
icon_url: 'https://raw.githubusercontent.com/posthog/timestamp-parser-plugin/main/logo.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ export const urlParserPlugin: LegacyTransformationPlugin = {
|
||||
description: 'Parse your event URLs into useful properties.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: [],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [],
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@ export const userAgentPlugin: LegacyTransformationPlugin = {
|
||||
"Enhances events with user agent details. User Agent plugin allows you to populate events with the $browser, $browser_version for PostHog Clients that don't typically populate these properties",
|
||||
icon_url: '/static/transformations/user-agent.png',
|
||||
category: ['Transformation'],
|
||||
code_language: 'javascript',
|
||||
hog: `return event`,
|
||||
inputs_schema: [
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
exports[`segment templates template segment-actions-absmartly matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to ABsmartly",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -357,6 +358,7 @@ exports[`segment templates template segment-actions-absmartly matches expected r
|
||||
exports[`segment templates template segment-actions-accoil-analytics matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Accoil Analytics",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -803,6 +805,7 @@ exports[`segment templates template segment-actions-accoil-analytics matches exp
|
||||
exports[`segment templates template segment-actions-acoustic matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Acoustic",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -1096,6 +1099,7 @@ Last-Modified: 02.01.2024 10.30.43
|
||||
exports[`segment templates template segment-actions-acoustic-campaign matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Acoustic Campaign",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -1432,6 +1436,7 @@ Last-Modified: 06.28.2023 16.15.37
|
||||
exports[`segment templates template segment-actions-airship matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Airship",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -1649,6 +1654,7 @@ exports[`segment templates template segment-actions-airship matches expected res
|
||||
exports[`segment templates template segment-actions-algolia-insights matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Algolia Insights",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -2380,6 +2386,7 @@ exports[`segment templates template segment-actions-algolia-insights matches exp
|
||||
exports[`segment templates template segment-actions-amplitude matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Amplitude",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -4566,6 +4573,7 @@ exports[`segment templates template segment-actions-amplitude matches expected r
|
||||
exports[`segment templates template segment-actions-angler-ai matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Angler AI",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -7902,6 +7910,7 @@ exports[`segment templates template segment-actions-angler-ai matches expected r
|
||||
exports[`segment templates template segment-actions-attentive matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Attentive",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -8020,6 +8029,7 @@ exports[`segment templates template segment-actions-attentive matches expected r
|
||||
exports[`segment templates template segment-actions-blend-ai matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Blend Ai",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -8137,6 +8147,7 @@ exports[`segment templates template segment-actions-blend-ai matches expected re
|
||||
exports[`segment templates template segment-actions-canny matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Canny",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -8309,6 +8320,7 @@ exports[`segment templates template segment-actions-canny matches expected resul
|
||||
exports[`segment templates template segment-actions-canvas matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Canvas",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -8924,6 +8936,7 @@ exports[`segment templates template segment-actions-canvas matches expected resu
|
||||
exports[`segment templates template segment-actions-clevertap matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to CleverTap",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -9102,6 +9115,7 @@ exports[`segment templates template segment-actions-clevertap matches expected r
|
||||
exports[`segment templates template segment-actions-cloud-gwen matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to GWEN",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -9258,6 +9272,7 @@ exports[`segment templates template segment-actions-cloud-gwen matches expected
|
||||
exports[`segment templates template segment-actions-drip matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Drip",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -9479,6 +9494,7 @@ exports[`segment templates template segment-actions-drip matches expected result
|
||||
exports[`segment templates template segment-actions-fullstory-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Fullstory Cloud Mode",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -9682,6 +9698,7 @@ exports[`segment templates template segment-actions-fullstory-cloud matches expe
|
||||
exports[`segment templates template segment-actions-gameball matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Gameball",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -10280,6 +10297,7 @@ exports[`segment templates template segment-actions-gameball matches expected re
|
||||
exports[`segment templates template segment-actions-hilo matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Hilo",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -10705,6 +10723,7 @@ exports[`segment templates template segment-actions-hilo matches expected result
|
||||
exports[`segment templates template segment-actions-hyperengage matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Hyperengage",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -11441,6 +11460,7 @@ exports[`segment templates template segment-actions-hyperengage matches expected
|
||||
exports[`segment templates template segment-actions-insider-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Insider Cloud Mode",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -11706,6 +11726,7 @@ exports[`segment templates template segment-actions-insider-cloud matches expect
|
||||
exports[`segment templates template segment-actions-iterable matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Iterable",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -12116,6 +12137,7 @@ exports[`segment templates template segment-actions-iterable matches expected re
|
||||
exports[`segment templates template segment-actions-kameleoon matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Kameleoon",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -12598,6 +12620,7 @@ exports[`segment templates template segment-actions-kameleoon matches expected r
|
||||
exports[`segment templates template segment-actions-koala-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Koala (Cloud)",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -12834,6 +12857,7 @@ exports[`segment templates template segment-actions-koala-cloud matches expected
|
||||
exports[`segment templates template segment-actions-launchdarkly matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to LaunchDarkly",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -13035,6 +13059,7 @@ exports[`segment templates template segment-actions-launchdarkly matches expecte
|
||||
exports[`segment templates template segment-actions-launchpad matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Launchpad",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -13602,6 +13627,7 @@ exports[`segment templates template segment-actions-launchpad matches expected r
|
||||
exports[`segment templates template segment-actions-livelike-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to LiveLike",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -13966,6 +13992,7 @@ exports[`segment templates template segment-actions-livelike-cloud matches expec
|
||||
exports[`segment templates template segment-actions-m3ter matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to m3ter",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -14168,6 +14195,7 @@ exports[`segment templates template segment-actions-m3ter matches expected resul
|
||||
exports[`segment templates template segment-actions-mixpanel matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Mixpanel",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -16205,6 +16233,7 @@ exports[`segment templates template segment-actions-mixpanel matches expected re
|
||||
exports[`segment templates template segment-actions-moloco-rmp matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Moloco MCM",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -18116,6 +18145,7 @@ exports[`segment templates template segment-actions-moloco-rmp matches expected
|
||||
exports[`segment templates template segment-actions-optimizely-data-platform matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Optimizely Data Platform",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -19055,6 +19085,7 @@ exports[`segment templates template segment-actions-optimizely-data-platform mat
|
||||
exports[`segment templates template segment-actions-pinterest-conversions-api matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Pinterest Conversions API",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -21314,6 +21345,7 @@ exports[`segment templates template segment-actions-pinterest-conversions-api ma
|
||||
exports[`segment templates template segment-actions-pipedrive matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Pipedrive",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -21780,6 +21812,7 @@ exports[`segment templates template segment-actions-pipedrive matches expected r
|
||||
exports[`segment templates template segment-actions-playerzero-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to PlayerZero Cloud",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -21880,6 +21913,7 @@ exports[`segment templates template segment-actions-playerzero-cloud matches exp
|
||||
exports[`segment templates template segment-actions-podscribe matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Podscribe",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -22287,6 +22321,7 @@ exports[`segment templates template segment-actions-podscribe matches expected r
|
||||
exports[`segment templates template segment-actions-prodeology matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Prodeology",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -22690,6 +22725,7 @@ exports[`segment templates template segment-actions-prodeology matches expected
|
||||
exports[`segment templates template segment-actions-pushwoosh matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Pushwoosh",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -22995,6 +23031,7 @@ exports[`segment templates template segment-actions-pushwoosh matches expected r
|
||||
exports[`segment templates template segment-actions-recombee matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Recombee",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -24216,6 +24253,7 @@ exports[`segment templates template segment-actions-recombee matches expected re
|
||||
exports[`segment templates template segment-actions-revx matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to RevX Cloud",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -24516,6 +24554,7 @@ exports[`segment templates template segment-actions-revx matches expected result
|
||||
exports[`segment templates template segment-actions-ripe-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Ripe Cloud Mode",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -24995,6 +25034,7 @@ exports[`segment templates template segment-actions-ripe-cloud matches expected
|
||||
exports[`segment templates template segment-actions-saleswings matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Saleswings",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -25510,6 +25550,7 @@ exports[`segment templates template segment-actions-saleswings matches expected
|
||||
exports[`segment templates template segment-actions-schematic matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Schematic",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -25720,6 +25761,7 @@ exports[`segment templates template segment-actions-schematic matches expected r
|
||||
exports[`segment templates template segment-actions-sprig matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Sprig Cloud",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -25927,6 +25969,7 @@ exports[`segment templates template segment-actions-sprig matches expected resul
|
||||
exports[`segment templates template segment-actions-stackadapt-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to StackAdapt",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -26137,6 +26180,7 @@ exports[`segment templates template segment-actions-stackadapt-cloud matches exp
|
||||
exports[`segment templates template segment-actions-topsort matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Topsort",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -26560,6 +26604,7 @@ exports[`segment templates template segment-actions-topsort matches expected res
|
||||
exports[`segment templates template segment-actions-usermaven matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Usermaven",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -27501,6 +27546,7 @@ exports[`segment templates template segment-actions-usermaven matches expected r
|
||||
exports[`segment templates template segment-actions-usermotion matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to UserMotion",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -27759,6 +27805,7 @@ exports[`segment templates template segment-actions-usermotion matches expected
|
||||
exports[`segment templates template segment-actions-userpilot-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Userpilot Cloud",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -27988,6 +28035,7 @@ exports[`segment templates template segment-actions-userpilot-cloud matches expe
|
||||
exports[`segment templates template segment-actions-voyage matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Voyage",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -28208,6 +28256,7 @@ exports[`segment templates template segment-actions-voyage matches expected resu
|
||||
exports[`segment templates template segment-actions-vwo-cloud matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to VWO Cloud Mode",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -28623,6 +28672,7 @@ exports[`segment templates template segment-actions-vwo-cloud matches expected r
|
||||
exports[`segment templates template segment-actions-xtremepush matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Xtremepush",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -28845,6 +28895,7 @@ exports[`segment templates template segment-actions-xtremepush matches expected
|
||||
exports[`segment templates template segment-calliper-cloud-actions matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Calliper Cloud",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -29362,6 +29413,7 @@ exports[`segment templates template segment-calliper-cloud-actions matches expec
|
||||
exports[`segment templates template segment-encharge-cloud-actions matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Encharge",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -30089,6 +30141,7 @@ exports[`segment templates template segment-encharge-cloud-actions matches expec
|
||||
exports[`segment templates template segment-inleads-ai matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Inleads AI",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -30767,6 +30820,7 @@ exports[`segment templates template segment-inleads-ai matches expected result 1
|
||||
exports[`segment templates template segment-metronome-actions matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Metronome",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -30881,6 +30935,7 @@ exports[`segment templates template segment-metronome-actions matches expected r
|
||||
exports[`segment templates template segment-outfunnel matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Outfunnel",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
@@ -31251,6 +31306,7 @@ exports[`segment templates template segment-outfunnel matches expected result 1`
|
||||
exports[`segment templates template segment-voucherify-actions matches expected result 1`] = `
|
||||
{
|
||||
"category": [],
|
||||
"code_language": "javascript",
|
||||
"description": "Send event data to Voucherify",
|
||||
"free": false,
|
||||
"hog": "return event",
|
||||
|
||||
@@ -509,6 +509,7 @@ export const SEGMENT_DESTINATIONS = Object.entries(destinations)
|
||||
default: false,
|
||||
},
|
||||
],
|
||||
code_language: 'javascript',
|
||||
hog: 'return event',
|
||||
mapping_templates: (destination.presets ?? [])
|
||||
.filter((preset) => preset.type === 'automatic' && preset.subscribe)
|
||||
|
||||
@@ -1088,5 +1088,6 @@ export const allComingSoonTemplates: HogFunctionTemplate[] = destinationDefiniti
|
||||
status: 'coming_soon' as const,
|
||||
type: 'destination' as const,
|
||||
hog: `return event;`,
|
||||
code_language: 'javascript',
|
||||
inputs_schema: [],
|
||||
}))
|
||||
|
||||
@@ -76,6 +76,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Send conversion events to Google Ads',
|
||||
icon_url: '/static/services/google-ads.png',
|
||||
category: ['Advertisement'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
if (empty(inputs.gclid)) {
|
||||
print('Empty \`gclid\`. Skipping...')
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Creates an issue for a Linear team',
|
||||
icon_url: '/static/services/linear.png',
|
||||
category: ['Error tracking'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let description :=f'{event.properties.description}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Track how many Reddit users interact with your website.',
|
||||
icon_url: '/static/services/reddit.png',
|
||||
category: ['Advertisement'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
if (empty(inputs.accountId) or empty(inputs.conversionsAccessToken)) {
|
||||
throw Error('Account ID and access token are required')
|
||||
|
||||
@@ -95,6 +95,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Send conversion events to Snapchat Ads',
|
||||
icon_url: '/static/services/snapchat.png',
|
||||
category: ['Advertisement'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
if (empty(inputs.pixelId) or empty(inputs.oauth.access_token)) {
|
||||
throw Error('Pixel ID and access token are required')
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { HogFunctionType } from '~/cdp/types'
|
||||
import { isLegacyPluginHogFunction, isNativeHogFunction, isSegmentPluginHogFunction } from '~/cdp/utils'
|
||||
|
||||
import { HOG_FUNCTION_TEMPLATES } from '..'
|
||||
|
||||
describe('Hog Function Templates Code Language', () => {
|
||||
it.each(HOG_FUNCTION_TEMPLATES)('should have correct code_language for template $id', (template) => {
|
||||
if (
|
||||
isNativeHogFunction({ template_id: template.id } as HogFunctionType) ||
|
||||
isSegmentPluginHogFunction({ template_id: template.id } as HogFunctionType) ||
|
||||
isLegacyPluginHogFunction({ template_id: template.id } as HogFunctionType) ||
|
||||
template.id.startsWith('coming-soon-')
|
||||
) {
|
||||
expect(template.code_language).toBe('javascript')
|
||||
} else {
|
||||
expect(template.code_language).toBe('hog')
|
||||
}
|
||||
})
|
||||
|
||||
it.each(HOG_FUNCTION_TEMPLATES)('should have hog property set for template $id', (template) => {
|
||||
expect(template.hog).toBeDefined()
|
||||
expect(typeof template.hog).toBe('string')
|
||||
})
|
||||
})
|
||||
@@ -73,6 +73,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Send conversion events to TikTok Ads',
|
||||
icon_url: '/static/services/tiktok.png',
|
||||
category: ['Advertisement'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
if (empty(inputs.pixelId) or empty(inputs.accessToken)) {
|
||||
throw Error('Pixel ID and access token are required')
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Sends a webhook templated by the incoming event data',
|
||||
icon_url: '/static/posthog-icon.svg',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
let payload := {
|
||||
'headers': inputs.headers,
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Capture an event via a custom incoming webhook',
|
||||
icon_url: '/static/services/webhook.svg',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
|
||||
if(inputs.debug) {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'Filters out events from known bot user agents. This transformation will drop the event if a bot is detected.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// List of known bot user agents
|
||||
let known_bot_filter_list := ['bot', 'crawler', 'spider', 'feedfetcher-google',
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'This is a starter template for custom transformations',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// This is a blank template for custom transformations
|
||||
// The function receives 'event' as a global object and expects it to be returned
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Drop events based on defined filters.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
return null`,
|
||||
inputs_schema: [],
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Filter out specific properties from the event by setting them to null or removing them completely.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Check if the event has properties
|
||||
if (empty(event.properties)) {
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Adds geoip data to the event',
|
||||
icon_url: '/static/transformations/geoip.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Define the properties to be added to the event
|
||||
let geoipProperties := {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'Hashes sensitive fields with SHA256 using a salt. This helps protect user privacy while maintaining data consistency.',
|
||||
icon_url: '/static/hedgehog/police-hog.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Function to hash a value with SHA256
|
||||
fun hashValue(value, salt) {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'This transformation sets the last octet of an IP address to zero (e.g., 12.214.31.144 → 12.214.31.0), protecting user privacy and reducing disclosure risk.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Check if the event has an IP address
|
||||
if (empty(event.properties?.$ip)) {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'This transformation hashes sensitive personal data (PII) like email, phone numbers, etc. using SHA-256 to protect user privacy.',
|
||||
icon_url: '/static/hedgehog/builder-hog-02.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Get the properties to hash from inputs and split by comma
|
||||
let propertiesToHash := []
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'This transformation removes null properties from the event properties object. If the object nesting exceeds 3 levels, deeper levels will be returned unchanged.',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Check if the event has properties
|
||||
if (empty(event.properties)) {
|
||||
|
||||
@@ -9,6 +9,7 @@ export const template: HogFunctionTemplate = {
|
||||
description: 'Masks sensitive information in URL parameters (query strings) of specified properties',
|
||||
icon_url: '/static/hedgehog/builder-hog-01.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
// Function to check if parameter matches any mask pattern
|
||||
fun isParameterInList(paramName, paramsString) {
|
||||
|
||||
@@ -10,6 +10,7 @@ export const template: HogFunctionTemplate = {
|
||||
'Normalizes URLs by replacing dynamic path segments (containing numbers or capital letters) with :id placeholders. This helps group similar URLs together for analysis.',
|
||||
icon_url: '/static/hedgehog/reading-hog.png',
|
||||
category: ['Custom'],
|
||||
code_language: 'hog',
|
||||
hog: `
|
||||
|
||||
// Function to normalize a path segment
|
||||
|
||||
@@ -49,6 +49,7 @@ export const HOG_FUNCTION_TEMPLATES_TRANSFORMATIONS: HogFunctionTemplate[] = [
|
||||
|
||||
export const NATIVE_HOG_FUNCTIONS: NativeTemplate[] = [nativeWebhook].map((plugin) => ({
|
||||
...plugin,
|
||||
code_language: 'javascript',
|
||||
hog: 'return event;',
|
||||
inputs_schema: [
|
||||
...plugin.inputs_schema,
|
||||
|
||||
@@ -361,6 +361,7 @@ export type HogFunctionTemplate = {
|
||||
mapping_templates?: HogFunctionMappingTemplate[]
|
||||
masking?: HogFunctionMasking
|
||||
icon_url?: string
|
||||
code_language: 'javascript' | 'hog'
|
||||
}
|
||||
|
||||
export type HogFunctionTemplateCompiled = HogFunctionTemplate & {
|
||||
@@ -406,7 +407,7 @@ export type Response = {
|
||||
headers: Record<string, any>
|
||||
}
|
||||
|
||||
export type NativeTemplate = Omit<HogFunctionTemplate, 'hog'> & {
|
||||
export type NativeTemplate = Omit<HogFunctionTemplate, 'hog' | 'code_language'> & {
|
||||
perform: (
|
||||
request: (
|
||||
url: string,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"icon_url": "/static/posthog-icon.svg",
|
||||
"category": ["Custom"],
|
||||
"hog": "\nlet payload := {\n 'headers': inputs.headers,\n 'body': inputs.body,\n 'method': inputs.method\n}\n\nif (inputs.debug) {\n print('Request', inputs.url, payload)\n}\n\nlet res := fetch(inputs.url, payload);\n\nif (inputs.debug) {\n print('Response', res.status, res.body);\n}\n",
|
||||
"code_language": "hog",
|
||||
"inputs_schema": [
|
||||
{
|
||||
"key": "url",
|
||||
@@ -138,6 +139,7 @@
|
||||
"id": "template-blank-transformation",
|
||||
"name": "Custom transformation",
|
||||
"hog": "// This is a blank template for custom transformations\n// The function receives 'event' as a global object and expects it to be returned\n// If you return null then the event will be discarded\nreturn event",
|
||||
"code_language": "hog",
|
||||
"inputs_schema": [],
|
||||
"category": ["Custom"],
|
||||
"description": "This is a starter template for custom transformations",
|
||||
@@ -152,6 +154,7 @@
|
||||
"id": "template-geoip",
|
||||
"name": "GeoIP",
|
||||
"hog": "// Define the properties to be added to the event\nlet geoipProperties := {\n 'city_name': null,\n 'city_confidence': null,\n 'subdivision_2_name': null,\n 'subdivision_2_code': null,\n 'subdivision_1_name': null,\n 'subdivision_1_code': null,\n 'country_name': null,\n 'country_code': null,\n 'continent_name': null,\n 'continent_code': null,\n 'postal_code': null,\n 'latitude': null,\n 'longitude': null,\n 'accuracy_radius': null,\n 'time_zone': null\n}\n// Check if the event has an IP address\nif (event.properties?.$geoip_disable or empty(event.properties?.$ip)) {\n print('geoip disabled or no ip.')\n return event\n}\nlet ip := event.properties.$ip\nif (ip == '127.0.0.1') {\n print('spoofing ip for local development', ip)\n ip := '89.160.20.129'\n}\nlet response := geoipLookup(ip)\nif (not response) {\n print('geoip lookup failed for ip', ip)\n return event\n}\nlet location := {}\nif (response.city) {\n location['city_name'] := response.city.names?.en\n}\nif (response.country) {\n location['country_name'] := response.country.names?.en\n location['country_code'] := response.country.isoCode\n}\nif (response.continent) {\n location['continent_name'] := response.continent.names?.en\n location['continent_code'] := response.continent.code\n}\nif (response.postal) {\n location['postal_code'] := response.postal.code\n}\nif (response.location) {\n location['latitude'] := response.location?.latitude\n location['longitude'] := response.location?.longitude\n location['accuracy_radius'] := response.location?.accuracyRadius\n location['time_zone'] := response.location?.timeZone\n}\nif (response.subdivisions) {\n for (let index, subdivision in response.subdivisions) {\n location[f'subdivision_{index + 1}_code'] := subdivision.isoCode\n location[f'subdivision_{index + 1}_name'] := subdivision.names?.en\n }\n}\nprint('geoip location data for ip:', location) \nlet returnEvent := event\nreturnEvent.properties := returnEvent.properties ?? {}\nreturnEvent.properties.$set := returnEvent.properties.$set ?? {}\nreturnEvent.properties.$set_once := returnEvent.properties.$set_once ?? {}\nfor (let key, value in geoipProperties) {\n if (value != null) {\n returnEvent.properties.$set[f'$geoip_{key}'] := value\n returnEvent.properties.$set_once[f'$initial_geoip_{key}'] := value\n }\n returnEvent.properties.$set[f'$geoip_{key}'] := value\n returnEvent.properties.$set_once[f'$initial_geoip_{key}'] := value\n}\nfor (let key, value in location) {\n returnEvent.properties[f'$geoip_{key}'] := value\n returnEvent.properties.$set[f'$geoip_{key}'] := value\n returnEvent.properties.$set_once[f'$initial_geoip_{key}'] := value\n}\nreturn returnEvent",
|
||||
"code_language": "hog",
|
||||
"inputs_schema": [],
|
||||
"category": ["Custom"],
|
||||
"description": "Adds geoip data to the event",
|
||||
@@ -163,6 +166,7 @@
|
||||
"status": "alpha",
|
||||
"free": true,
|
||||
"type": "transformation",
|
||||
"code_language": "hog",
|
||||
"id": "template-ip-anonymization",
|
||||
"name": "IP Anonymization",
|
||||
"hog": "// Check if the event has an IP address\nif (empty(event.properties?.$ip)) {\n print('No IP address found in event')\n return event\n}\n\nlet ip := event.properties.$ip\nlet parts := splitByString('.', ip)\n\n// Check if we have exactly 4 parts for IPv4\nif (length(parts) != 4) {\n print('Invalid IP address format: wrong number of octets')\n return event\n}\n\n// Validate each octet is a number between 0 and 255\nfor (let i := 1; i \u003C= 4; i := i + 1) {\n let octet := toInt(parts[i])\n if (octet = null or octet \u003C 0 or octet \u003E 255) {\n print('Invalid IP address: octets must be numbers between 0 and 255')\n return event\n }\n}\n\n// Replace the last octet with '0'\nlet anonymizedIp := concat(parts[1], '.', parts[2], '.', parts[3], '.0')\n \nlet returnEvent := event\nreturnEvent.properties.$ip := anonymizedIp\nreturn returnEvent",
|
||||
@@ -177,6 +181,7 @@
|
||||
"status": "alpha",
|
||||
"free": true,
|
||||
"type": "transformation",
|
||||
"code_language": "hog",
|
||||
"id": "template-remove-null-properties",
|
||||
"name": "Remove Null Properties",
|
||||
"hog": "// Check if the event has properties\nif (empty(event.properties)) {\n return event\n}\n\nlet returnEvent := event\nreturnEvent.properties := cleanNullValues(event.properties)\nreturn returnEvent",
|
||||
@@ -192,6 +197,7 @@
|
||||
"free": false,
|
||||
"type": "transformation",
|
||||
"id": "template-url-masking",
|
||||
"code_language": "hog",
|
||||
"name": "URL Parameter Masking",
|
||||
"hog": "// Function to check if parameter matches any mask pattern\nfun isParameterInList(paramName, paramsString) {\n let paramsList := splitByString(',', paramsString)\n for (let pattern in paramsList) {\n if (lower(paramName) =~ lower(trim(pattern))) {\n return true\n }\n }\n return false\n}\n\n// Function to mask URL parameters\nfun maskURLParameters(url, paramsToMask, maskValue) {\n // If URL is empty or not a string, return as is\n if (empty(url) or typeof(url) != 'string') {\n return url\n }\n\n try {\n // Split URL into base and query string\n let parts := splitByString('?', url, 2)\n if (length(parts) \u003C 2) {\n return url\n }\n \n let baseUrl := parts[1]\n let queryString := parts[2]\n \n // Handle malformed URLs that start with ?\n if (empty(baseUrl)) {\n return url\n }\n \n // Split query string into parameters\n let params := splitByString('&', queryString)\n let maskedParams := []\n \n // Process each parameter\n for (let param in params) {\n if (not empty(param)) {\n let keyValue := splitByString('=', param, 2)\n let paramName := keyValue[1]\n \n // Handle parameters without values (e.g., ?key&foo=bar)\n if (length(keyValue) \u003C 2) {\n if (isParameterInList(paramName, paramsToMask)) {\n maskedParams := arrayPushBack(maskedParams, concat(paramName, '=', maskValue))\n } else {\n maskedParams := arrayPushBack(maskedParams, paramName)\n }\n } else {\n if (isParameterInList(paramName, paramsToMask)) {\n maskedParams := arrayPushBack(maskedParams, concat(paramName, '=', maskValue))\n } else {\n maskedParams := arrayPushBack(maskedParams, param)\n }\n }\n }\n }\n \n // Reconstruct URL with masked parameters\n return concat(baseUrl, '?', arrayStringConcat(maskedParams, '&'))\n } catch (error) {\n print('Error masking URL parameters:', error)\n return url\n }\n}\n\n// Create a copy of the event to modify\nlet maskedEvent := event\n\n// Process each URL property\nfor (let propName, paramsToMask in inputs.urlProperties) {\n if (not empty(event.properties?.[propName])) {\n maskedEvent.properties[propName] := maskURLParameters(\n event.properties[propName],\n paramsToMask,\n inputs.maskWith\n )\n }\n}\n\nreturn maskedEvent",
|
||||
"inputs_schema": [
|
||||
@@ -228,6 +234,7 @@
|
||||
"free": true,
|
||||
"type": "transformation",
|
||||
"id": "template-pii-hashing",
|
||||
"code_language": "hog",
|
||||
"name": "PII Data Hashing",
|
||||
"hog": "// Get the properties to hash from inputs and split by comma\nlet propertiesToHash := []\nif (notEmpty(inputs.propertiesToHash)) {\n propertiesToHash := splitByString(',', inputs.propertiesToHash)\n}\nlet hashDistinctId := inputs.hashDistinctId\nlet salt := inputs.salt\n\nif (empty(propertiesToHash) and not hashDistinctId) {\n return event\n}\n\n// Create a deep copy of the event to modify\nlet returnEvent := event\n\n// Helper function to get nested property value\nfun getNestedValue(obj, path) {\n let parts := splitByString('.', path)\n let current := obj\n \n for (let part in parts) {\n if (current = null) {\n return null\n }\n current := current[part]\n }\n return current\n}\n\n// Helper function to set nested property value\nfun setNestedValue(obj, path, value) {\n let parts := splitByString('.', path)\n let current := obj\n \n // Navigate to the parent object of the target property\n for (let i := 1; i \u003C length(parts); i := i + 1) {\n let part := parts[i]\n if (current[part] = null) {\n current[part] := {}\n }\n current := current[part]\n }\n \n // Set the value on the last part\n let lastPart := parts[length(parts)]\n current[lastPart] := value\n}\n\n// Hash distinct_id if enabled also potentially using a salt\nif (hashDistinctId and notEmpty(event.distinct_id)) {\n if(notEmpty(salt)) {\n returnEvent.distinct_id := sha256Hex(concat(toString(event.distinct_id), salt))\n } else {\n returnEvent.distinct_id := sha256Hex(toString(event.distinct_id))\n }\n}\n\n// Hash each property value potentially using a salt\nfor (let _, path in propertiesToHash) {\n let value := getNestedValue(event.properties, trim(path)) // Trim to handle spaces after commas\n if (notEmpty(value)) {\n if(notEmpty(salt)) {\n let hashedValue := sha256Hex(concat(toString(value), salt))\n setNestedValue(returnEvent.properties, trim(path), hashedValue)\n } else {\n let hashedValue := sha256Hex(toString(value))\n setNestedValue(returnEvent.properties, trim(path), hashedValue)\n }\n }\n}\n\nreturn returnEvent",
|
||||
"inputs_schema": [
|
||||
@@ -269,6 +276,7 @@
|
||||
"status": "alpha",
|
||||
"free": false,
|
||||
"type": "transformation",
|
||||
"code_language": "hog",
|
||||
"id": "template-bot-detection",
|
||||
"name": "Filter Bot Events",
|
||||
"hog": "// List of known bot user agents\nlet known_bot_filter_list := ['bot', 'crawler', 'spider', 'feedfetcher-google',\n'mediapartners-google', 'apis-google', 'slurp', 'python-urllib',\n'python-requests', 'aiohttp', 'httpx', 'libwww-perl',\n'httpunit', 'nutch', 'go-http-client', 'biglotron', 'teoma',\n'convera', 'gigablast', 'ia_archiver', 'webmon ', 'httrack',\n'grub.org', 'netresearchserver', 'speedy', 'fluffy',\n'findlink', 'panscient', 'ips-agent', 'yanga', 'yandex',\n'yadirectfetcher', 'cyberpatrol', 'postrank', 'page2rss', \n'linkdex', 'ezooms', 'heritrix', 'findthatfile', 'europarchive.org', \n'mappydata', 'eright', 'apercite', 'aboundex', 'summify', 'ec2linkfinder', \n'facebookexternalhit', 'yeti', 'retrevopageanalyzer', 'sogou', 'wotbox', \n'ichiro', 'drupact', 'coccoc', 'integromedb', 'siteexplorer.info', \n'proximic', 'changedetection', 'cc metadata scaper', 'g00g1e.net', \n'binlar', 'a6-indexer', 'admantx', 'megaindex', 'ltx71', 'bubing', \n'qwantify', 'lipperhey', 'addthis', 'metauri', 'scrapy', 'capsulechecker', \n'sonic', 'sysomos', 'trove', 'deadlinkchecker', 'slack-imgproxy', 'embedly', \n'iskanie', 'skypeuripreview', 'google-adwords-instant', 'whatsapp', \n'electricmonk', 'yahoo link preview', 'xenu link sleuth', 'pcore-http', \n'appinsights', 'phantomjs', 'jetslide', 'newsharecounts', 'tineye', \n'linkarchiver', 'digg deeper', 'snacktory', 'okhttp', 'nuzzel', 'omgili', \n'pocketparser', 'um-ln', 'muckrack', 'netcraftsurveyagent', 'appengine-google', \n'jetty', 'upflow', 'thinklab', 'traackr.com', 'twurly', 'mastodon', 'http_get', \n'brandverity', 'check_http', 'ezid', 'genieo', 'meltwaternews', 'moreover', \n'scoutjet', 'seoscanners', 'hatena', 'google web preview', 'adscanner', \n'netvibes', 'baidu-yunguance', 'btwebclient', 'disqus', 'feedly', 'fever', \n'flamingo_searchengine', 'flipboardproxy', 'g2 web services', 'vkshare', \n'siteimprove.com', 'dareboost', 'feedspot', 'seokicks', 'tracemyfile', \n'zgrab', 'pr-cy.ru', 'datafeedwatch', 'zabbix', 'google-xrawler', 'axios', \n'amazon cloudfront', 'pulsepoint', 'cloudflare-alwaysonline', \n'google-structured-data-testing-tool', 'wordupinfosearch', 'webdatastats', \n'httpurlconnection', 'outbrain', 'w3c_validator', 'w3c-checklink', \n'w3c-mobileok', 'w3c_i18n-checker', 'feedvalidator', 'w3c_css_validator', \n'w3c_unicorn', 'google-physicalweb', 'blackboard', 'bazqux', 'twingly', \n'rivva', 'dataprovider.com', 'theoldreader.com', 'anyevent', \n'nmap scripting engine', '2ip.ru', 'clickagy', 'google favicon', \n'hubspot', 'chrome-lighthouse', 'headlesschrome', 'simplescraper', \n'fedoraplanet', 'friendica', 'nextcloud', 'tiny tiny rss', 'datanyze', \n'google-site-verification', 'trendsmapresolver', 'tweetedtimes', 'gwene', \n'simplepie', 'searchatlas', 'superfeedr', 'freewebmonitoring sitechecker', \n'pandalytics', 'seewithkids', 'cincraw', 'freshrss', 'google-certificates-bridge', \n'viber', 'evc-batch', 'virustotal', 'uptime-kuma', 'feedbin', \n'snap url preview service', 'ruxitsynthetic', 'google-read-aloud', \n'mediapartners', 'wget', 'wget', 'ahrefsgot', 'ahrefssiteaudit', \n'wesee:search', 'y!j', 'collection@infegy.com', 'deusu', 'bingpreview', \n'daum', 'pingdom', 'barkrowler', 'yak', 'ning', 'ahc', 'apache-httpclient', \n'buck', 'newspaper', 'sentry', 'fetch', 'miniflux', 'validator.nu', \n'grouphigh', 'checkmarknetwork', 'www.uptime.com', 'mixnodecache', \n'domains project', 'pagepeeker', 'vigil', 'php-curl-class', 'ptst',\n'seostar.co']\n\nlet userAgentProperty := inputs.userAgent\n\n// Check if user agent property exists in event\n// We treat missing user agent as bot traffic\nif (empty(event.properties[userAgentProperty])) {\n return null\n}\n\n// Get the user agent value\nlet user_agent := event.properties[userAgentProperty]\n\n// Check for empty string\n// We treat empty user agent as bot traffic\nif (user_agent == '') {\n return null\n}\n\n// Now that we know we have a valid user agent, convert to lower case\nuser_agent := lower(user_agent)\n\n// Handle custom bot patterns\nlet bot_list := known_bot_filter_list\nif (notEmpty(inputs.customBotPatterns)) {\n let custom_patterns := splitByString(',', inputs.customBotPatterns)\n // Add each custom pattern to the list\n for (let pattern in custom_patterns) {\n bot_list := arrayPushBack(bot_list, trim(pattern))\n }\n}\n\n// Function to check if user agent contains any bot identifier\nfun isBot(ua) {\n for (let bot_name in bot_list) {\n if (ua =~* bot_name) {\n return true\n }\n }\n return false\n}\n\n// If bot is detected, return null to filter out the event\n// Otherwise return the original event\nif (isBot(user_agent)) {\n return null\n}\n\nreturn event",
|
||||
@@ -304,6 +312,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-downsampling-plugin",
|
||||
"name": "Downsample",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -354,6 +363,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-language-url-splitter-app",
|
||||
"name": "Language URL stripper",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -423,6 +433,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-posthog-app-url-parameters-to-event-properties",
|
||||
"name": "URL parameters to event properties",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -534,6 +545,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-posthog-filter-out-plugin",
|
||||
"name": "Filter Out Plugin",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -582,6 +594,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-posthog-plugin-geoip",
|
||||
"name": "GeoIP",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [],
|
||||
"category": ["Custom"],
|
||||
@@ -596,6 +609,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-posthog-url-normalizer-plugin",
|
||||
"name": "URL Normalizer",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [],
|
||||
"category": ["Transformation"],
|
||||
@@ -610,6 +624,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-property-filter-plugin",
|
||||
"name": "Property Filter",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -634,6 +649,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-semver-flattener-plugin",
|
||||
"name": "SemVer Flattener",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
{
|
||||
@@ -657,6 +673,7 @@
|
||||
"free": true,
|
||||
"type": "transformation",
|
||||
"id": "plugin-taxonomy-plugin",
|
||||
"code_language": "hog",
|
||||
"name": "Taxonomy",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
@@ -703,6 +720,7 @@
|
||||
"type": "transformation",
|
||||
"id": "plugin-timestamp-parser-plugin",
|
||||
"name": "Timestamp Parser",
|
||||
"code_language": "hog",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [],
|
||||
"category": ["Transformation"],
|
||||
@@ -716,6 +734,7 @@
|
||||
"free": true,
|
||||
"type": "transformation",
|
||||
"id": "plugin-user-agent-plugin",
|
||||
"code_language": "hog",
|
||||
"name": "User Agent Populator",
|
||||
"hog": "return event",
|
||||
"inputs_schema": [
|
||||
|
||||
@@ -28,6 +28,7 @@ EXAMPLE_FULL = {
|
||||
"name": "HogHook",
|
||||
"hog": "fetch(inputs.url, {\n 'headers': inputs.headers,\n 'body': inputs.payload,\n 'method': inputs.method\n});",
|
||||
"type": "destination",
|
||||
"code_language": "hog",
|
||||
"enabled": True,
|
||||
"inputs_schema": [
|
||||
{"key": "url", "type": "string", "label": "Webhook URL", "required": True},
|
||||
@@ -360,6 +361,7 @@ class TestHogFunctionAPI(ClickhouseTestMixin, APIBaseTest, QueryMatchingTest):
|
||||
"status": "beta",
|
||||
"icon_url": webhook_template["icon_url"],
|
||||
"category": webhook_template["category"],
|
||||
"code_language": "hog",
|
||||
"inputs_schema": webhook_template["inputs_schema"],
|
||||
"hog": webhook_template["hog"].strip(),
|
||||
"filters": None,
|
||||
|
||||
@@ -17,6 +17,7 @@ MOCK_NODE_TEMPLATES = json.loads(
|
||||
EXPECTED_FIRST_RESULT = {
|
||||
"free": template.free,
|
||||
"type": "destination",
|
||||
"code_language": template.code_language,
|
||||
"status": template.status,
|
||||
"id": template.id,
|
||||
"name": template.name,
|
||||
@@ -272,6 +273,7 @@ class TestDatabaseHogFunctionTemplates(ClickhouseTestMixin, APIBaseTest, QueryMa
|
||||
status="stable",
|
||||
free=True,
|
||||
category=["Customer Success"],
|
||||
code_language="hog",
|
||||
)
|
||||
|
||||
# Save the modified template - this should update the existing one
|
||||
|
||||
@@ -9,6 +9,7 @@ blank_site_destination: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="New destination with complex event mapping. Works only with posthog-js when opt_in_site_apps is set to true.",
|
||||
icon_url="/static/hedgehog/builder-hog-01.png",
|
||||
category=["Custom", "Analytics"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
export async function onLoad({ inputs, posthog }) {
|
||||
console.log('🦔 Loading (takes 1 sec)', { inputs })
|
||||
@@ -144,6 +145,7 @@ blank_site_app: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Run custom JavaScript on your website. Works only with posthog-js when opt_in_site_apps is set to true.",
|
||||
icon_url="/static/hedgehog/builder-hog-03.png",
|
||||
category=["Custom", "Analytics"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
export function onLoad({ inputs, posthog }) {
|
||||
console.log(`Hello ${inputs.name} from your new Site App!`)
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Enable extra debugging tools on your posthog-js",
|
||||
icon_url="/static/hedgehog/builder-hog-01.png",
|
||||
category=["Custom"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
export function onLoad({ inputs, posthog }) {
|
||||
console.log("Enabling PostHog.js debugging", posthog)
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="This app is used with Early Access Feature Management",
|
||||
icon_url="https://raw.githubusercontent.com/PostHog/early-access-features-app/refs/heads/main/logo.png",
|
||||
category=["Custom"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
const style = (inputs) => `
|
||||
.list-container {
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="HogDesk bug reporter",
|
||||
icon_url="https://raw.githubusercontent.com/PostHog/bug-report-app/refs/heads/main/logo.png",
|
||||
category=["Custom"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
const style = (inputs) => `
|
||||
.form, .button, .thanks {
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Show a notification bar for your users",
|
||||
icon_url="/static/hedgehog/list-hog.png",
|
||||
category=["Custom", "Analytics"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
export function onLoad({ inputs }) {
|
||||
if (inputs.domains) {
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Make any website better by adding raining pineapples",
|
||||
icon_url="/static/services/pineapple.png",
|
||||
category=["Custom", "Analytics"],
|
||||
code_language="javascript",
|
||||
hog="""
|
||||
const style = `
|
||||
.button {
|
||||
|
||||
@@ -10,6 +10,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Creates a new contact in ActiveCampaign whenever an event is triggered.",
|
||||
icon_url="/static/services/activecampaign.png",
|
||||
category=["Email Marketing"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
if (empty(inputs.email)) {
|
||||
print('`email` input is empty. Not creating a contact.')
|
||||
|
||||
@@ -10,6 +10,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Creates Airtable records",
|
||||
icon_url="/static/services/airtable.png",
|
||||
category=["Custom"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
let url := f'https://api.airtable.com/v0/{inputs.base_id}/{inputs.table_name}'
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Create and update contacts in Attio",
|
||||
icon_url="/static/services/attio.png",
|
||||
category=["Advertisement"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
let body := {
|
||||
'data': {
|
||||
|
||||
@@ -12,6 +12,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Send events to Avo",
|
||||
icon_url="/static/services/avo.png",
|
||||
category=["Analytics"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
if (empty(inputs.apiKey) or empty(inputs.environment)) {
|
||||
print('API Key and environment has to be set. Skipping...')
|
||||
|
||||
@@ -10,6 +10,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Put data to an AWS Kinesis stream",
|
||||
icon_url="/static/services/aws-kinesis.png",
|
||||
category=["Analytics"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
fun getPayload() {
|
||||
let region := inputs.aws_region
|
||||
|
||||
@@ -10,6 +10,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Send events to Braze",
|
||||
icon_url="/static/services/braze.png",
|
||||
category=["Customer Success"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
let getPayload := () -> [{
|
||||
'attributes': inputs.attributes,
|
||||
|
||||
@@ -9,6 +9,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Update contacts in Brevo",
|
||||
icon_url="/static/services/brevo.png",
|
||||
category=["Email Marketing"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
if (empty(inputs.email)) {
|
||||
print('No email set. Skipping...')
|
||||
|
||||
@@ -12,6 +12,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Loads data from the Clearbit API and tracks an additional event with the enriched data if found. Once enriched, the person will not be enriched again.",
|
||||
icon_url="/static/services/clearbit.png",
|
||||
category=["Analytics"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
let api_key := inputs.api_key
|
||||
let email := inputs.email
|
||||
|
||||
@@ -13,6 +13,7 @@ template: HogFunctionTemplate = HogFunctionTemplate(
|
||||
description="Identify or track events against customers in Customer.io",
|
||||
icon_url="/static/services/customerio.png",
|
||||
category=["Email Marketing"],
|
||||
code_language="hog",
|
||||
hog="""
|
||||
let action := inputs.action
|
||||
let name := event.event
|
||||
|
||||