From f5ea9f5fd295402376927d75f512ed0cdbd0a11c Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:15:47 +0100 Subject: [PATCH 1/9] add snapchat ads destination --- frontend/public/services/snapchat-ads.png | Bin 0 -> 7164 bytes posthog/cdp/templates/__init__.py | 2 + .../snapchat_ads/template_snapchat_ads.py | 141 ++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 frontend/public/services/snapchat-ads.png create mode 100644 posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py diff --git a/frontend/public/services/snapchat-ads.png b/frontend/public/services/snapchat-ads.png new file mode 100644 index 0000000000000000000000000000000000000000..4fd5486e6dd774947906056b39e002fc2fb931df GIT binary patch literal 7164 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 UA@!;k{x(vVdHydV!1?^Y074BUGXMYp literal 0 HcmV?d00001 diff --git a/posthog/cdp/templates/__init__.py b/posthog/cdp/templates/__init__.py index 2bf9f517aeedc..c4c7cec6ffe1d 100644 --- a/posthog/cdp/templates/__init__.py +++ b/posthog/cdp/templates/__init__.py @@ -38,6 +38,7 @@ TemplateGoogleCloudStorageMigrator, ) from .airtable.template_airtable import template as airtable +from .snapchat_ads.template_snapchat_ads import template as snapchat_ads from ._internal.template_broadcast import template_new_broadcast as _broadcast HOG_FUNCTION_TEMPLATES = [ @@ -78,6 +79,7 @@ salesforce_create, salesforce_update, sendgrid, + snapchat_ads, zapier, zendesk, ] diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py new file mode 100644 index 0000000000000..5050f0675df60 --- /dev/null +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -0,0 +1,141 @@ +from posthog.cdp.templates.hog_function_template import HogFunctionTemplate + +template: HogFunctionTemplate = HogFunctionTemplate( + status="alpha", + type="destination", + id="template-snapchat-ads", + name="Snapchat Ads Conversions", + description="Send conversion events to Snapchat Ads", + icon_url="/static/services/snapchat-ads.png", + category=["Advertisement"], + hog=""" +let body := { + 'data': [ + { + 'event_name': inputs.eventName, + 'action_source': inputs.actionSource, + 'event_time': inputs.eventTime, + 'user_data': {}, + 'custom_data': {} + } + ] +} + +if (not empty(event.properties.$current_url)) body.data.1.event_source_url := event.properties.$current_url + +for (let key, value in inputs.userData) { + // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 is an empty string hashed + if (not empty(value) and value != 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') { + body.data.1.user_data[key] := value + } +} + +for (let key, value in inputs.customData) { + // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 is an empty string hashed + if (not empty(value) and value != 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') { + body.data.1.custom_data[key] := value + } +} + +let res := fetch(f'https://tr.snapchat.com/v3/{inputs.pixelId}/events?access_token={inputs.accessToken}', { + 'method': 'POST', + 'headers': { + 'Content-Type': 'application/json', + }, + 'body': body +}) +if (res.status >= 400) { + throw Error(f'Error from graph.facebook.com (status {res.status}): {res.body}') +} +""".strip(), + inputs_schema=[ + { + "key": "accessToken", + "type": "string", + "label": "Access token", + "description": "Check out this page on how to obtain such a token: https://developers.snap.com/api/marketing-api/Conversions-API/GetStarted#access-token", + "secret": True, + "required": True, + }, + { + "key": "pixelId", + "type": "string", + "label": "Pixel ID", + "description": "You must obtain a Pixel ID to use the Conversions API. If you’ve already set up a Pixel for your website, we recommend that you use the same Pixel ID for your browser and server events.", + "secret": False, + "required": True, + }, + { + "key": "eventName", + "type": "string", + "label": "Event name", + "description": "A standard event or custom event name.", + "default": "{event.event}", + "secret": False, + "required": True, + }, + { + "key": "eventTime", + "type": "string", + "label": "Event time", + "description": "A Unix timestamp in seconds indicating when the actual event occurred. You must send this date in GMT time zone.", + "default": "{toUnixTimestampMilli(event.timestamp)}", + "secret": False, + "required": True, + }, + { + "key": "actionSource", + "label": "Action source", + "type": "choice", + "choices": [ + { + "label": "WEB - Conversion was made on your website.", + "value": "WEB", + }, + { + "label": "MOBILE_APP - Conversion was made on your mobile app.", + "value": "MOBILE_APP", + }, + { + "label": "OFFLINE - Conversion happened in a way that is not listed.", + "value": "OFFLINE", + }, + ], + "description": "This field allows you to specify where your conversions occurred. Knowing where your events took place helps ensure your ads go to the right people.", + "default": "website", + "secret": False, + "required": True, + }, + { + "key": "userData", + "type": "dictionary", + "label": "User data", + "description": "A map that contains customer information data. See this page for options: https://developers.snap.com/api/marketing-api/Conversions-API/Parameters#user-data-parameters", + "default": { + "em": "{sha256Hex(person.properties.email ?? '')}", + "ph": "{sha256Hex(person.properties.phone ?? '')}", + "sc_click_id": "{person.properties.sccid ?? person.properties.$initial_sccid}", + }, + "secret": False, + "required": True, + }, + { + "key": "customData", + "type": "dictionary", + "label": "Custom data", + "description": "A map that contains custom data. See this page for options: https://developers.snap.com/api/marketing-api/Conversions-API/Parameters#custom-data-parameters", + "default": { + "currency": "USD", + "value": "{event.properties.price}", + "event_id": "{event.uuid}", + }, + "secret": False, + "required": True, + }, + ], + filters={ + "events": [], + "actions": [], + "filter_test_accounts": True, + }, +) From 65be2bc7583693b143414cff5edea51cac53942f Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:31:50 +0100 Subject: [PATCH 2/9] add test --- .../snapchat_ads/template_snapchat_ads.py | 4 +- .../test_template_snapchat_ads.py | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 posthog/cdp/templates/snapchat_ads/test_template_snapchat_ads.py diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index 5050f0675df60..0037630f0bfd2 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -45,7 +45,7 @@ 'body': body }) if (res.status >= 400) { - throw Error(f'Error from graph.facebook.com (status {res.status}): {res.body}') + throw Error(f'Error from tr.snapchat.com (status {res.status}): {res.body}') } """.strip(), inputs_schema=[ @@ -114,7 +114,7 @@ "default": { "em": "{sha256Hex(person.properties.email ?? '')}", "ph": "{sha256Hex(person.properties.phone ?? '')}", - "sc_click_id": "{person.properties.sccid ?? person.properties.$initial_sccid}", + "sc_click_id": "{person.properties.sccid ?? person.properties.$initial_sccid ?? ''}", }, "secret": False, "required": True, diff --git a/posthog/cdp/templates/snapchat_ads/test_template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/test_template_snapchat_ads.py new file mode 100644 index 0000000000000..8f4f10a4b9a40 --- /dev/null +++ b/posthog/cdp/templates/snapchat_ads/test_template_snapchat_ads.py @@ -0,0 +1,69 @@ +from inline_snapshot import snapshot +from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest +from posthog.cdp.templates.snapchat_ads.template_snapchat_ads import ( + template as template_snapchat_ads, +) + + +class TestTemplateSnapchatAds(BaseHogFunctionTemplateTest): + template = template_snapchat_ads + + def _inputs(self, **kwargs): + inputs = { + "accessToken": "accessToken12345", + "pixelId": "pixel12345", + "eventName": "purchase", + "eventTime": "1728812163", + "actionSource": "WEB", + "userData": { + "em": "3edfaed7454eedb3c72bad566901af8bfbed1181816dde6db91dfff0f0cffa98", + "ph": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + }, + "customData": { + "currency": "USD", + "price": "1500", + "event_id": "49ff3d7c-359d-4f45-960e-6cda29f1beea", + }, + } + inputs.update(kwargs) + return inputs + + def test_function_works(self): + self.run_function( + self._inputs(), + globals={ + "event": { + "uuid": "49ff3d7c-359d-4f45-960e-6cda29f1beea", + "properties": { + "$current_url": "https://posthog.com/cdp", + }, + }, + }, + ) + assert self.get_mock_fetch_calls()[0] == snapshot( + ( + "https://tr.snapchat.com/v3/pixel12345/events?access_token=accessToken12345", + { + "method": "POST", + "headers": { + "Content-Type": "application/json", + }, + "body": { + "data": [ + { + "event_name": "purchase", + "action_source": "WEB", + "event_time": "1728812163", + "user_data": {"em": "3edfaed7454eedb3c72bad566901af8bfbed1181816dde6db91dfff0f0cffa98"}, + "custom_data": { + "currency": "USD", + "price": "1500", + "event_id": "49ff3d7c-359d-4f45-960e-6cda29f1beea", + }, + "event_source_url": "https://posthog.com/cdp", + } + ] + }, + }, + ) + ) From bb286fdd13ad549ef505f4c56f50fd18f2186d43 Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:39:37 +0100 Subject: [PATCH 3/9] rename logo name --- .../services/{snapchat-ads.png => snapchat.png} | Bin .../templates/snapchat_ads/template_snapchat_ads.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename frontend/public/services/{snapchat-ads.png => snapchat.png} (100%) diff --git a/frontend/public/services/snapchat-ads.png b/frontend/public/services/snapchat.png similarity index 100% rename from frontend/public/services/snapchat-ads.png rename to frontend/public/services/snapchat.png diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index 0037630f0bfd2..61164c36f0cea 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -6,7 +6,7 @@ id="template-snapchat-ads", name="Snapchat Ads Conversions", description="Send conversion events to Snapchat Ads", - icon_url="/static/services/snapchat-ads.png", + icon_url="/static/services/snapchat.png", category=["Advertisement"], hog=""" let body := { From df5b8e5d2a3715a959443e4b6fca2f84029a46ec Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:24:35 +0100 Subject: [PATCH 4/9] fix merge --- .../editor/sourceNavigatorLogic.ts | 18 -- .../errorTrackingGroupSceneLogic.ts | 178 -------------- .../experiments/secondaryMetricsLogic.ts | 221 ------------------ .../errors/sessionRecordingErrorsLogic.ts | 44 ---- 4 files changed, 461 deletions(-) delete mode 100644 frontend/src/scenes/data-warehouse/editor/sourceNavigatorLogic.ts delete mode 100644 frontend/src/scenes/error-tracking/errorTrackingGroupSceneLogic.ts delete mode 100644 frontend/src/scenes/experiments/secondaryMetricsLogic.ts delete mode 100644 frontend/src/scenes/session-recordings/errors/sessionRecordingErrorsLogic.ts diff --git a/frontend/src/scenes/data-warehouse/editor/sourceNavigatorLogic.ts b/frontend/src/scenes/data-warehouse/editor/sourceNavigatorLogic.ts deleted file mode 100644 index 406ae6e0d4ea2..0000000000000 --- a/frontend/src/scenes/data-warehouse/editor/sourceNavigatorLogic.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { kea } from 'kea' - -import type { sourceNavigatorLogicType } from './sourceNavigatorLogicType' - -export const sourceNavigatorLogic = kea({ - path: ['scenes', 'data-warehouse', 'editor', 'sourceNavigatorLogic'], - actions: { - setWidth: (width: number) => ({ width }), - }, - reducers: { - navigatorWidth: [ - 200, - { - setWidth: (_, { width }: { width: number }) => width, - }, - ], - }, -}) diff --git a/frontend/src/scenes/error-tracking/errorTrackingGroupSceneLogic.ts b/frontend/src/scenes/error-tracking/errorTrackingGroupSceneLogic.ts deleted file mode 100644 index 22d8f4c4692fb..0000000000000 --- a/frontend/src/scenes/error-tracking/errorTrackingGroupSceneLogic.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { actions, connect, kea, key, listeners, path, props, reducers, selectors } from 'kea' -import { loaders } from 'kea-loaders' -import { actionToUrl, router, urlToAction } from 'kea-router' -import api from 'lib/api' -import { Dayjs, dayjs } from 'lib/dayjs' -import { Scene } from 'scenes/sceneTypes' -import { urls } from 'scenes/urls' - -import { ErrorTrackingGroup } from '~/queries/schema' -import { Breadcrumb } from '~/types' - -import type { errorTrackingGroupSceneLogicType } from './errorTrackingGroupSceneLogicType' -import { errorTrackingLogic } from './errorTrackingLogic' -import { errorTrackingGroupEventsQuery, errorTrackingGroupQuery } from './queries' - -export interface ErrorTrackingEvent { - uuid: string - timestamp: Dayjs - properties: Record - person: { - distinct_id: string - uuid?: string - created_at?: string - properties?: Record - } -} - -export interface ErrorTrackingGroupSceneLogicProps { - fingerprint: ErrorTrackingGroup['fingerprint'] -} - -export enum ErrorGroupTab { - Overview = 'overview', - Breakdowns = 'breakdowns', -} - -export const errorTrackingGroupSceneLogic = kea([ - path((key) => ['scenes', 'error-tracking', 'errorTrackingGroupSceneLogic', key]), - props({} as ErrorTrackingGroupSceneLogicProps), - key((props) => JSON.stringify(props.fingerprint)), - - connect({ - values: [errorTrackingLogic, ['dateRange', 'filterTestAccounts', 'filterGroup', 'hasGroupActions']], - }), - - actions({ - setErrorGroupTab: (tab: ErrorGroupTab) => ({ tab }), - setActiveEventUUID: (uuid: ErrorTrackingEvent['uuid']) => ({ uuid }), - updateGroup: (group: Partial>) => ({ group }), - }), - - reducers(() => ({ - errorGroupTab: [ - ErrorGroupTab.Overview as ErrorGroupTab, - { - setErrorGroupTab: (_, { tab }) => tab, - }, - ], - activeEventUUID: [ - undefined as ErrorTrackingEvent['uuid'] | undefined, - { - setActiveEventUUID: (_, { uuid }) => uuid, - }, - ], - })), - - loaders(({ props, values }) => ({ - group: [ - null as ErrorTrackingGroup | null, - { - loadGroup: async () => { - const response = await api.query( - errorTrackingGroupQuery({ - fingerprint: props.fingerprint, - dateRange: values.dateRange, - filterTestAccounts: values.filterTestAccounts, - filterGroup: values.filterGroup, - }), - {}, - undefined, - true - ) - - // ErrorTrackingQuery returns a list of groups - // when a fingerprint is supplied there will only be a single group - return response.results[0] - }, - updateGroup: async ({ group }) => { - const response = await api.errorTracking.update(props.fingerprint, group) - return { ...values.group, ...response } - }, - }, - ], - events: [ - [] as ErrorTrackingEvent[], - { - loadEvents: async () => { - const response = await api.query( - errorTrackingGroupEventsQuery({ - select: ['uuid', 'properties', 'timestamp', 'person'], - fingerprints: values.combinedFingerprints, - dateRange: values.dateRange, - filterTestAccounts: values.filterTestAccounts, - filterGroup: values.filterGroup, - offset: values.events.length, - }) - ) - - const newResults = response.results.map((r) => ({ - uuid: r[0], - properties: JSON.parse(r[1]), - timestamp: dayjs(r[2]), - person: r[3], - })) - - return [...values.events, ...newResults] - }, - }, - ], - })), - - listeners(({ values, actions }) => ({ - loadGroupSuccess: () => { - actions.loadEvents() - }, - loadEventsSuccess: () => { - if (!values.activeEventUUID) { - actions.setActiveEventUUID(values.events[0]?.uuid) - } - }, - })), - - selectors({ - breadcrumbs: [ - (s) => [s.group], - (group): Breadcrumb[] => { - const exceptionType = group?.exception_type || 'Unknown Type' - return [ - { - key: Scene.ErrorTracking, - name: 'Error tracking', - path: urls.errorTracking(), - }, - { - key: [Scene.ErrorTrackingGroup, exceptionType], - name: exceptionType, - }, - ] - }, - ], - - combinedFingerprints: [ - (s) => [s.group], - (group): ErrorTrackingGroup['fingerprint'][] => - group ? [group.fingerprint, ...group.merged_fingerprints] : [], - ], - }), - - actionToUrl(({ values }) => ({ - setErrorGroupTab: () => { - const searchParams = router.values.searchParams - - if (values.errorGroupTab != ErrorGroupTab.Overview) { - searchParams['tab'] = values.errorGroupTab - } - - return [router.values.location.pathname, searchParams] - }, - })), - - urlToAction(({ actions }) => ({ - [urls.errorTrackingGroup('*')]: (_, searchParams) => { - if (searchParams.tab) { - actions.setErrorGroupTab(searchParams.tab) - } - }, - })), -]) diff --git a/frontend/src/scenes/experiments/secondaryMetricsLogic.ts b/frontend/src/scenes/experiments/secondaryMetricsLogic.ts deleted file mode 100644 index 852d7f17a4721..0000000000000 --- a/frontend/src/scenes/experiments/secondaryMetricsLogic.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { actions, connect, kea, key, listeners, path, props, reducers } from 'kea' -import { forms } from 'kea-forms' -import { FunnelLayout } from 'lib/constants' -import { dayjs } from 'lib/dayjs' -import { insightDataLogic } from 'scenes/insights/insightDataLogic' -import { insightLogic } from 'scenes/insights/insightLogic' -import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic' -import { cleanFilters, getDefaultEvent } from 'scenes/insights/utils/cleanFilters' -import { teamLogic } from 'scenes/teamLogic' - -import { filtersToQueryNode } from '~/queries/nodes/InsightQuery/utils/filtersToQueryNode' -import { queryNodeToFilter } from '~/queries/nodes/InsightQuery/utils/queryNodeToFilter' -import { FunnelsQuery, InsightVizNode, TrendsQuery } from '~/queries/schema' -import { Experiment, FilterType, FunnelVizType, InsightType, SecondaryExperimentMetric } from '~/types' - -import { SECONDARY_METRIC_INSIGHT_ID } from './constants' -import { experimentLogic } from './experimentLogic' -import type { secondaryMetricsLogicType } from './secondaryMetricsLogicType' - -const DEFAULT_DURATION = 14 - -export const MAX_SECONDARY_METRICS = 10 - -export interface SecondaryMetricsProps { - onMetricsChange: (metrics: SecondaryExperimentMetric[]) => void - initialMetrics: SecondaryExperimentMetric[] - experimentId: Experiment['id'] - defaultAggregationType?: number -} - -export interface SecondaryMetricForm { - name: string - filters: Partial -} - -const defaultFormValuesGenerator: ( - aggregationType?: number, - disableAddEventToDefault?: boolean, - cohortIdToFilter?: number -) => SecondaryMetricForm = (aggregationType, disableAddEventToDefault, cohortIdToFilter) => { - const groupAggregation = - aggregationType !== undefined ? { math: 'unique_group', math_group_type_index: aggregationType } : {} - - const cohortFilter = cohortIdToFilter - ? { properties: [{ key: 'id', type: 'cohort', value: cohortIdToFilter }] } - : {} - const eventAddition = disableAddEventToDefault - ? {} - : { events: [{ ...getDefaultEvent(), ...groupAggregation, ...cohortFilter }] } - - return { - name: '', - filters: { - insight: InsightType.TRENDS, - ...eventAddition, - }, - } -} - -export const secondaryMetricsLogic = kea([ - props({} as SecondaryMetricsProps), - key((props) => `${props.experimentId || 'new'}-${props.defaultAggregationType}`), - path((key) => ['scenes', 'experiment', 'secondaryMetricsLogic', key]), - connect((props: SecondaryMetricsProps) => ({ - logic: [insightLogic({ dashboardItemId: SECONDARY_METRIC_INSIGHT_ID, syncWithUrl: false })], - values: [teamLogic, ['currentTeamId'], experimentLogic({ experimentId: props.experimentId }), ['experiment']], - actions: [ - insightDataLogic({ dashboardItemId: SECONDARY_METRIC_INSIGHT_ID }), - ['setQuery'], - insightVizDataLogic({ dashboardItemId: SECONDARY_METRIC_INSIGHT_ID }), - ['updateQuerySource'], - ], - })), - actions({ - // modal - openModalToCreateSecondaryMetric: true, - openModalToEditSecondaryMetric: ( - metric: SecondaryExperimentMetric, - metricIdx: number, - showResults: boolean = false - ) => ({ - metric, - metricIdx, - showResults, - }), - saveSecondaryMetric: true, - closeModal: true, - - // metrics - setMetricId: (metricIdx: number) => ({ metricIdx }), - addNewMetric: (metric: SecondaryExperimentMetric) => ({ metric }), - updateMetric: (metric: SecondaryExperimentMetric, metricIdx: number) => ({ metric, metricIdx }), - deleteMetric: (metricIdx: number) => ({ metricIdx }), - - // preview insight - setPreviewInsight: (filters?: Partial) => ({ filters }), - }), - reducers(({ props }) => ({ - isModalOpen: [ - false, - { - openModalToCreateSecondaryMetric: () => true, - openModalToEditSecondaryMetric: () => true, - closeModal: () => false, - }, - ], - showResults: [ - false, - { - openModalToEditSecondaryMetric: (_, { showResults }) => showResults, - closeModal: () => false, - }, - ], - existingModalSecondaryMetric: [ - null as SecondaryExperimentMetric | null, - { - openModalToCreateSecondaryMetric: () => null, - openModalToEditSecondaryMetric: (_, { metric }) => metric, - }, - ], - metrics: [ - props.initialMetrics, - { - addNewMetric: (metrics, { metric }) => { - return [...metrics, { ...metric }] - }, - updateMetric: (metrics, { metric, metricIdx }) => { - const metricsCopy = [...metrics] - metricsCopy[metricIdx] = metric - return metricsCopy - }, - deleteMetric: (metrics, { metricIdx }) => metrics.filter((_, idx) => idx !== metricIdx), - }, - ], - metricIdx: [ - 0 as number, - { - setMetricId: (_, { metricIdx }) => metricIdx, - }, - ], - })), - forms(({ props, values }) => ({ - secondaryMetricModal: { - defaults: defaultFormValuesGenerator( - props.defaultAggregationType, - false, - values.experiment?.exposure_cohort - ), - errors: () => ({}), - submit: async () => { - // We don't use the form submit anymore - }, - }, - })), - listeners(({ props, actions, values }) => ({ - openModalToCreateSecondaryMetric: () => { - actions.resetSecondaryMetricModal() - actions.setPreviewInsight( - defaultFormValuesGenerator(props.defaultAggregationType, false, values.experiment?.exposure_cohort) - .filters - ) - }, - openModalToEditSecondaryMetric: ({ metric: { name, filters }, metricIdx }) => { - actions.setSecondaryMetricModalValue('name', name) - actions.setPreviewInsight(filters) - actions.setMetricId(metricIdx) - }, - setPreviewInsight: async ({ filters }) => { - let newInsightFilters - if (filters?.insight === InsightType.FUNNELS) { - newInsightFilters = cleanFilters({ - insight: InsightType.FUNNELS, - funnel_viz_type: FunnelVizType.Steps, - date_from: dayjs().subtract(DEFAULT_DURATION, 'day').format('YYYY-MM-DD'), - date_to: dayjs().endOf('d').format('YYYY-MM-DDTHH:mm'), - layout: FunnelLayout.horizontal, - aggregation_group_type_index: props.defaultAggregationType, - ...filters, - }) - } else { - newInsightFilters = cleanFilters({ - insight: InsightType.TRENDS, - date_from: dayjs().subtract(DEFAULT_DURATION, 'day').format('YYYY-MM-DD'), - date_to: dayjs().endOf('d').format('YYYY-MM-DDTHH:mm'), - ...defaultFormValuesGenerator( - props.defaultAggregationType, - (filters?.actions?.length || 0) + (filters?.events?.length || 0) > 0 - ).filters, - ...filters, - }) - } - - // This allows switching between insight types. It's necessary as `updateQuerySource` merges - // the new query with any existing query and that causes validation problems when there are - // unsupported properties in the now merged query. - const newQuery = filtersToQueryNode(newInsightFilters) - if (filters?.insight === InsightType.FUNNELS) { - ;(newQuery as TrendsQuery).trendsFilter = undefined - } else { - ;(newQuery as FunnelsQuery).funnelsFilter = undefined - } - actions.updateQuerySource(newQuery) - }, - // sync form value `filters` with query - setQuery: ({ query }) => { - actions.setSecondaryMetricModalValue('filters', queryNodeToFilter((query as InsightVizNode).source)) - }, - saveSecondaryMetric: () => { - if (values.existingModalSecondaryMetric) { - actions.updateMetric(values.secondaryMetricModal, values.metricIdx) - } else { - actions.addNewMetric(values.secondaryMetricModal) - } - props.onMetricsChange(values.metrics) - actions.closeModal() - }, - deleteMetric: () => { - props.onMetricsChange(values.metrics) - }, - })), -]) diff --git a/frontend/src/scenes/session-recordings/errors/sessionRecordingErrorsLogic.ts b/frontend/src/scenes/session-recordings/errors/sessionRecordingErrorsLogic.ts deleted file mode 100644 index 49de62c7bf5c4..0000000000000 --- a/frontend/src/scenes/session-recordings/errors/sessionRecordingErrorsLogic.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { actions, afterMount, kea, listeners, path } from 'kea' -import { loaders } from 'kea-loaders' -import { router } from 'kea-router' -import api from 'lib/api' -import { urls } from 'scenes/urls' - -import { ErrorClusterResponse } from '~/types' - -import { createPlaylist } from '../playlist/playlistUtils' -import type { sessionRecordingErrorsLogicType } from './sessionRecordingErrorsLogicType' - -export const sessionRecordingErrorsLogic = kea([ - path(['scenes', 'session-recordings', 'detail', 'sessionRecordingErrorsLogic']), - actions({ - createPlaylist: (name: string, sessionIds: string[]) => ({ name, sessionIds }), - }), - loaders(() => ({ - errors: [ - null as ErrorClusterResponse, - { - loadErrorClusters: async (refresh: boolean = true) => { - const response = await api.recordings.errorClusters(refresh) - return response - }, - }, - ], - })), - listeners(() => ({ - createPlaylist: async ({ name, sessionIds }) => { - const playlist = await createPlaylist({ name: name }) - - if (playlist) { - const samples = sessionIds.slice(0, 10) - await Promise.all( - samples.map((sessionId) => api.recordings.addRecordingToPlaylist(playlist.short_id, sessionId)) - ) - router.actions.push(urls.replayPlaylist(playlist.short_id)) - } - }, - })), - afterMount(({ actions }) => { - actions.loadErrorClusters(false) - }), -]) From 920b6dafd81b4d969cb661827801defed0aaf14f Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:01:53 +0100 Subject: [PATCH 5/9] remove hashed empty string check --- posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index 61164c36f0cea..38b6cfe3ed45c 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -24,15 +24,13 @@ if (not empty(event.properties.$current_url)) body.data.1.event_source_url := event.properties.$current_url for (let key, value in inputs.userData) { - // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 is an empty string hashed - if (not empty(value) and value != 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') { + if (not empty(value)) { body.data.1.user_data[key] := value } } for (let key, value in inputs.customData) { - // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 is an empty string hashed - if (not empty(value) and value != 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') { + if (not empty(value)) { body.data.1.custom_data[key] := value } } From ca2050bf003f3284944aeb57ba90fe8bffeb0860 Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:02:29 +0100 Subject: [PATCH 6/9] add snapchat pixel site destination --- posthog/cdp/templates/__init__.py | 6 ++- .../snapchat_ads/template_snapchat_ads.py | 37 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/posthog/cdp/templates/__init__.py b/posthog/cdp/templates/__init__.py index 4718c6a8d1ced..be9044d3c069f 100644 --- a/posthog/cdp/templates/__init__.py +++ b/posthog/cdp/templates/__init__.py @@ -39,7 +39,10 @@ TemplateGoogleCloudStorageMigrator, ) from .airtable.template_airtable import template as airtable -from .snapchat_ads.template_snapchat_ads import template as snapchat_ads +from .snapchat_ads.template_snapchat_ads import ( + template as snapchat_ads, + template_site_destination as snapchat_ads_site_destination, +) from .brevo.template_brevo import template as brevo from ._siteapps.template_early_access_features import template as early_access_features from ._siteapps.template_hogdesk import template as hogdesk @@ -92,6 +95,7 @@ salesforce_update, sendgrid, snapchat_ads, + snapchat_ads_site_destination, zapier, zendesk, early_access_features, diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index 38b6cfe3ed45c..a4927ea76d95c 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -137,3 +137,40 @@ "filter_test_accounts": True, }, ) + +template_site_destination: HogFunctionTemplate = HogFunctionTemplate( + status="client-side", + type="site_destination", + id="template-snapchat-site-destination", + name="Snapchat Pixel", + description="Track how many Snapchat users interact with your website.", + icon_url="/static/services/snapchat.png", + category=["Advertisement"], + hog=""" +export async function onLoad({ inputs, posthog }) { + (function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function() + {a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)}; + a.queue=[];var s='script';r=t.createElement(s);r.async=!0; + r.src=n;var u=t.getElementsByTagName(s)[0]; + u.parentNode.insertBefore(r,u);})(window,document, + 'https://sc-static.net/scevent.min.js'); + + snaptr('init', '{inputs.pixelId}', {}); +} +export function onEvent({ posthog, ...globals }) { + const { event, person } = globals + if (event.event === '$pageview') { + snaptr('track', 'PAGE_VIEW'); + } +} +""".strip(), + inputs_schema=[ + { + "key": "pixelId", + "type": "string", + "label": "Pixel ID", + "default": "", + "required": True, + } + ], +) From 79eb001653ede8486c1740eef1cb9e0ea8a5fde2 Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:33:30 +0100 Subject: [PATCH 7/9] add event and user parameter options --- .../snapchat_ads/template_snapchat_ads.py | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index a4927ea76d95c..5734e70c2b074 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -155,11 +155,28 @@ u.parentNode.insertBefore(r,u);})(window,document, 'https://sc-static.net/scevent.min.js'); - snaptr('init', '{inputs.pixelId}', {}); + let userProperties = {}; + + for (let { key, value } in inputs.userProperties) { + if (value) { + userProperties[key] = value; + } + }; + + snaptr('init', '{inputs.pixelId}', userProperties); } -export function onEvent({ posthog, ...globals }) { - const { event, person } = globals + +export function onEvent({ posthog, globals }) { + const { event, person } = globals; if (event.event === '$pageview') { + let eventProperties = {}; + + for (let { key, value } in inputs.userProperties) { + if (value) { + eventProperties[key] = value; + } + }; + snaptr('track', 'PAGE_VIEW'); } } @@ -169,8 +186,35 @@ "key": "pixelId", "type": "string", "label": "Pixel ID", + "description": "You must obtain a Pixel ID to use the Snapchat Pixel. If you’ve already set up a Pixel for your website, we recommend that you use the same Pixel ID for your browser and server events.", "default": "", + "secret": False, "required": True, - } + }, + { + "key": "userProperties", + "type": "dictionary", + "description": "Map of Snapchat user parameters and their values. Check out this page for more details: https://businesshelp.snapchat.com/s/article/pixel-direct-implementation", + "label": "User parameters", + "default": { + "user_email": "{person.properties.email}", + "ip_address": "{person.user.ip_address}", + }, + "secret": False, + "required": False, + }, + { + "key": "eventProperties", + "type": "dictionary", + "description": "Map of Snapchat event attributes and their values. Check out this page for more details: https://businesshelp.snapchat.com/s/article/pixel-direct-implementation", + "label": "Event parameters", + "default": { + "currency": "{event.properties.currency}", + "price": "{event.properties.price}", + "client_dedup_id": "{event.uuid}", + }, + "secret": False, + "required": False, + }, ], ) From c283ba5048a75947c08d0c6154699a413582ad43 Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:26:56 +0100 Subject: [PATCH 8/9] populate person properties during onLoad in site destinations --- posthog/cdp/site_functions.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/posthog/cdp/site_functions.py b/posthog/cdp/site_functions.py index 3896f4f73515e..a6911168203c2 100644 --- a/posthog/cdp/site_functions.py +++ b/posthog/cdp/site_functions.py @@ -81,7 +81,12 @@ def get_transpiled_function(hog_function: HogFunction) -> str: const posthog = config.posthog; const callback = config.callback; if ('onLoad' in source) { - const r = source.onLoad({ inputs: buildInputs({}, true), posthog: posthog }); + const globals = { + person: { + properties: posthog.get_property('$stored_person_properties'), + } + } + const r = source.onLoad({ inputs: buildInputs(globals, true), posthog: posthog }); if (r && typeof r.then === 'function' && typeof r.finally === 'function') { r.catch(() => callback(false)).then(() => callback(true)) } else { callback(true) } } else { callback(true); From 4b22f98e7f1d0cbd6a5b599e61dc61c40e248cfd Mon Sep 17 00:00:00 2001 From: MarconLP <13001502+MarconLP@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:49:32 +0100 Subject: [PATCH 9/9] update snapchat site destination template --- .../snapchat_ads/template_snapchat_ads.py | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py index 5734e70c2b074..beb3aba69c930 100644 --- a/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py +++ b/posthog/cdp/templates/snapchat_ads/template_snapchat_ads.py @@ -147,7 +147,7 @@ icon_url="/static/services/snapchat.png", category=["Advertisement"], hog=""" -export async function onLoad({ inputs, posthog }) { +export async function onLoad({ inputs }) { (function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function() {a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)}; a.queue=[];var s='script';r=t.createElement(s);r.async=!0; @@ -157,7 +157,7 @@ let userProperties = {}; - for (let { key, value } in inputs.userProperties) { + for (const [key, value] of Object.entries(inputs.userProperties)) { if (value) { userProperties[key] = value; } @@ -166,19 +166,16 @@ snaptr('init', '{inputs.pixelId}', userProperties); } -export function onEvent({ posthog, globals }) { - const { event, person } = globals; - if (event.event === '$pageview') { - let eventProperties = {}; +export function onEvent({ inputs }) { + let eventProperties = {}; - for (let { key, value } in inputs.userProperties) { - if (value) { - eventProperties[key] = value; - } - }; + for (const [key, value] of Object.entries(inputs.eventProperties)) { + if (value) { + eventProperties[key] = value; + } + }; - snaptr('track', 'PAGE_VIEW'); - } + snaptr('track', 'PAGE_VIEW', eventProperties); } """.strip(), inputs_schema=[