2
0

feat(integration): Add Google Analytics integration

This commit is contained in:
Baptiste Arnaud
2022-01-19 14:25:15 +01:00
parent 44b478550f
commit 3506d86d50
21 changed files with 528 additions and 152 deletions

View File

@ -0,0 +1,37 @@
import { GoogleAnalyticsOptions } from 'models'
declare const gtag: any
const initGoogleAnalytics = (id: string): Promise<void> =>
new Promise((resolve) => {
const existingScript = document.getElementById('gtag')
if (!existingScript) {
const script = document.createElement('script')
script.src = `https://www.googletagmanager.com/gtag/js?id=${id}`
script.id = 'gtag'
const initScript = document.createElement('script')
initScript.innerHTML = `window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${id}');
`
document.body.appendChild(script)
document.body.appendChild(initScript)
script.onload = () => {
resolve()
}
}
if (existingScript) resolve()
})
export const sendGaEvent = (options: GoogleAnalyticsOptions) => {
if (!options) return
gtag('event', options.action, {
event_category: options.category,
event_label: options.label,
value: options.value,
})
}
export default initGoogleAnalytics

View File

@ -26,7 +26,8 @@ export const HostMessageBubble = ({
const [isTyping, setIsTyping] = useState(true)
const content = useMemo(
() => parseVariables(step.content.html, typebot.variables),
() =>
parseVariables({ text: step.content.html, variables: typebot.variables }),
[typebot.variables]
)

View File

@ -9,10 +9,12 @@ import {
GoogleSheetsUpdateRowOptions,
Cell,
GoogleSheetsGetOptions,
GoogleAnalyticsStep,
} from 'models'
import { stringify } from 'qs'
import { sendRequest } from 'utils'
import { parseVariables } from './variable'
import { sendGaEvent } from '../../lib/gtag'
import { parseVariables, parseVariablesInObject } from './variable'
export const executeIntegration = (
step: IntegrationStep,
@ -22,9 +24,21 @@ export const executeIntegration = (
switch (step.type) {
case IntegrationStepType.GOOGLE_SHEETS:
return executeGoogleSheetIntegration(step, variables, updateVariableValue)
case IntegrationStepType.GOOGLE_ANALYTICS:
return executeGoogleAnalyticsIntegration(step, variables)
}
}
export const executeGoogleAnalyticsIntegration = async (
step: GoogleAnalyticsStep,
variables: Table<Variable>
) => {
if (!step.options?.trackingId) return
const { default: initGoogleAnalytics } = await import('../../lib/gtag')
await initGoogleAnalytics(step.options.trackingId)
sendGaEvent(parseVariablesInObject(step.options, variables))
}
const executeGoogleSheetIntegration = async (
step: GoogleSheetsStep,
variables: Table<Variable>,
@ -73,7 +87,10 @@ const updateRowInGoogleSheets = async (
values: parseCellValues(options.cellsToUpsert, variables),
referenceCell: {
column: options.referenceCell.column,
value: parseVariables(options.referenceCell.value ?? '', variables),
value: parseVariables({
text: options.referenceCell.value ?? '',
variables,
}),
},
},
})
@ -90,7 +107,10 @@ const getRowFromGoogleSheets = async (
credentialsId: options.credentialsId,
referenceCell: {
column: options.referenceCell.column,
value: parseVariables(options.referenceCell.value ?? '', variables),
value: parseVariables({
text: options.referenceCell.value ?? '',
variables,
}),
},
columns: options.cellsToExtract.allIds.map(
(id) => options.cellsToExtract?.byId[id].column
@ -117,5 +137,8 @@ const parseCellValues = (
const cell = cells.byId[id]
return !cell.column || !cell.value
? row
: { ...row, [cell.column]: parseVariables(cell.value, variables) }
: {
...row,
[cell.column]: parseVariables({ text: cell.value, variables }),
}
}, {})

View File

@ -22,7 +22,7 @@ export const executeLogic = (
return
const expression = step.options.expressionToEvaluate
const evaluatedExpression = isMathFormula(expression)
? evaluateExpression(parseVariables(expression, variables))
? evaluateExpression(parseVariables({ text: expression, variables }))
: expression
updateVariableValue(step.options.variableId, evaluatedExpression)
return

View File

@ -6,11 +6,14 @@ const safeEval = eval
export const stringContainsVariable = (str: string): boolean =>
/\{\{(.*?)\}\}/g.test(str)
export const parseVariables = (
text: string,
export const parseVariables = ({
text,
variables,
}: {
text?: string
variables: Table<Variable>
): string => {
if (text === '') return text
}): string => {
if (!text || text === '') return ''
return text.replace(/\{\{(.*?)\}\}/g, (_, fullVariableString) => {
const matchedVarName = fullVariableString.replace(/{{|}}/g, '')
const matchedVariableId = variables.allIds.find((variableId) => {
@ -44,3 +47,18 @@ const countDecimals = (value: number) => {
if (value % 1 != 0) return value.toString().split('.')[1].length
return 0
}
export const parseVariablesInObject = (
object: { [key: string]: string | number },
variables: Table<Variable>
) =>
Object.keys(object).reduce((newObj, key) => {
const currentValue = object[key]
return {
...newObj,
[key]:
typeof currentValue === 'string'
? parseVariables({ text: currentValue, variables })
: currentValue,
}
}, {})

View File

@ -1,12 +1,15 @@
import { StepBase } from '.'
import { Table } from '../..'
export type IntegrationStep = GoogleSheetsStep
export type IntegrationStep = GoogleSheetsStep | GoogleAnalyticsStep
export type IntegrationStepOptions = GoogleSheetsOptions
export type IntegrationStepOptions =
| GoogleSheetsOptions
| GoogleAnalyticsOptions
export enum IntegrationStepType {
GOOGLE_SHEETS = 'Google Sheets',
GOOGLE_ANALYTICS = 'Google Analytics',
}
export type GoogleSheetsStep = StepBase & {
@ -14,6 +17,19 @@ export type GoogleSheetsStep = StepBase & {
options?: GoogleSheetsOptions
}
export type GoogleAnalyticsStep = StepBase & {
type: IntegrationStepType.GOOGLE_ANALYTICS
options?: GoogleAnalyticsOptions
}
export type GoogleAnalyticsOptions = {
trackingId?: string
category?: string
action?: string
label?: string
value?: number
}
export enum GoogleSheetsAction {
GET = 'Get data from sheet',
INSERT_ROW = 'Insert a row',

View File

@ -73,4 +73,4 @@ export const isConditionStep = (step: Step): step is ConditionStep =>
step.type === LogicStepType.CONDITION
export const isIntegrationStep = (step: Step): step is IntegrationStep =>
step.type === IntegrationStepType.GOOGLE_SHEETS
(Object.values(IntegrationStepType) as string[]).includes(step.type)