Skip to content

Commit

Permalink
Custom validation in Google Ads for email address to allow hashed ema…
Browse files Browse the repository at this point in the history
…il addresses. (#1365)

* Custom validation for email address to allow hashed email addresses.
* Using `ajv-formats` email Regex to validate email.
* Adding `ajv-formats` as advised in PR comment.
  • Loading branch information
seg-leonelsanches authored Jul 7, 2023
1 parent a76b6bf commit 3d342ba
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 7 deletions.
1 change: 1 addition & 0 deletions packages/destination-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@segment/actions-core": "^3.69.0",
"@segment/actions-shared": "^1.51.0",
"@types/node": "^18.11.15",
"ajv-formats": "^2.1.1",
"aws4": "^1.12.0",
"cheerio": "^1.0.0-rc.10",
"dayjs": "^1.10.7",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createHash } from 'crypto'
import { ConversionCustomVariable, PartialErrorResponse, QueryResponse } from './types'
import { ModifiedResponse, RequestClient, IntegrationError } from '@segment/actions-core'
import { ModifiedResponse, RequestClient, IntegrationError, PayloadValidationError } from '@segment/actions-core'
import { StatsContext } from '@segment/actions-core/src/destination-kit'
import { Features } from '@segment/actions-core/src/mapping-kit'
import { fullFormats } from 'ajv-formats/dist/formats'

export const API_VERSION = 'v12'
export const CANARY_API_VERSION = 'v13'
Expand Down Expand Up @@ -95,3 +96,15 @@ export function getApiVersion(features?: Features, statsContext?: StatsContext):
}

export const isHashedEmail = (email: string): boolean => new RegExp(/[0-9abcdef]{64}/gi).test(email)
export const commonHashedEmailValidation = (email: string): string => {
if (isHashedEmail(email)) {
return email
}

// https://github.com/ajv-validator/ajv-formats/blob/master/src/formats.ts#L64-L65
if (!(fullFormats.email as RegExp).test(email)) {
throw new PayloadValidationError("Email provided doesn't seem to be in a valid format.")
}

return String(hash(email))
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
handleGoogleErrors,
convertTimestamp,
getApiVersion,
isHashedEmail
commonHashedEmailValidation
} from '../functions'
import { ModifiedResponse } from '@segment/actions-core'

Expand Down Expand Up @@ -56,7 +56,6 @@ const action: ActionDefinition<Settings, Payload> = {
description:
'Email address of the individual who triggered the conversion event. Segment will hash this value before sending to Google.',
type: 'string',
format: 'email',
default: {
'@if': {
exists: { '@path': '$.properties.email' },
Expand Down Expand Up @@ -240,8 +239,10 @@ const action: ActionDefinition<Settings, Payload> = {
}

if (payload.email_address) {
const validatedEmail: string = commonHashedEmailValidation(payload.email_address)

request_object.userIdentifiers.push({
hashedEmail: isHashedEmail(payload.email_address) ? payload.email_address : hash(payload.email_address)
hashedEmail: validatedEmail
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ActionDefinition, PayloadValidationError } from '@segment/actions-core'
import { hash, handleGoogleErrors, convertTimestamp, getApiVersion, isHashedEmail } from '../functions'
import { hash, handleGoogleErrors, convertTimestamp, getApiVersion, commonHashedEmailValidation } from '../functions'
import type { Settings } from '../generated-types'
import type { Payload } from './generated-types'
import { PartialErrorResponse } from '../types'
Expand Down Expand Up @@ -79,7 +79,6 @@ const action: ActionDefinition<Settings, Payload> = {
description:
'Email address of the individual who triggered the conversion event. Segment will hash this value before sending to Google.',
type: 'string',
format: 'email',
default: {
'@if': {
exists: { '@path': '$.properties.email' },
Expand Down Expand Up @@ -235,8 +234,10 @@ const action: ActionDefinition<Settings, Payload> = {
}

if (payload.email_address) {
const validatedEmail: string = commonHashedEmailValidation(payload.email_address)

request_object.userIdentifiers.push({
hashedEmail: isHashedEmail(payload.email_address) ? payload.email_address : hash(payload.email_address)
hashedEmail: validatedEmail
})
}

Expand Down

0 comments on commit 3d342ba

Please sign in to comment.