-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Airtable CDP destination, creating records per-event (#25656)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
40e69dd
commit c4a87c7
Showing
4 changed files
with
150 additions
and
1 deletion.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
from posthog.cdp.templates.hog_function_template import HogFunctionTemplate | ||
|
||
|
||
template: HogFunctionTemplate = HogFunctionTemplate( | ||
status="alpha", | ||
id="template-airtable", | ||
name="Airtable", | ||
description="Creates Airtable records", | ||
icon_url="/static/services/airtable.png", | ||
category=["Custom"], | ||
hog=""" | ||
let url := f'https://api.airtable.com/v0/{inputs.base_id}/{inputs.table_name}' | ||
let payload := { | ||
'headers': { | ||
'Content-Type': 'application/json', | ||
'Authorization': f'Bearer {inputs.access_token}' | ||
}, | ||
'body': { | ||
'fields': inputs.fields, | ||
'typecast': true | ||
}, | ||
'method': 'POST' | ||
} | ||
if (inputs.debug) { | ||
print('Request', url, payload) | ||
} | ||
let res := fetch(url, payload); | ||
if (inputs.debug) { | ||
print('Response', res.status, res.body); | ||
} | ||
if (res.status >= 400) { | ||
throw Error(f'Error from api.airtable.com (status {res.status}): {res.body}') | ||
} | ||
""".strip(), | ||
inputs_schema=[ | ||
{ | ||
"key": "access_token", | ||
"type": "string", | ||
"label": "Airtable access token", | ||
"secret": True, | ||
"required": True, | ||
"description": "Create this at https://airtable.com/create/tokens", | ||
}, | ||
{ | ||
"key": "base_id", | ||
"type": "string", | ||
"label": "Airtable base ID", | ||
"secret": False, | ||
"required": True, | ||
"description": "Find this at https://airtable.com/developers/web/api/introduction", | ||
}, | ||
{ | ||
"key": "table_name", | ||
"type": "string", | ||
"label": "Table name", | ||
"secret": False, | ||
"required": True, | ||
}, | ||
{ | ||
"key": "fields", | ||
"type": "json", | ||
"label": "Fields", | ||
"default": {"Timestamp": "{event.timestamp}", "Person Name": "{person.name}"}, | ||
"secret": False, | ||
"required": True, | ||
"description": "Map field names from Airtable to properties from events and person records.", | ||
}, | ||
{ | ||
"key": "debug", | ||
"type": "boolean", | ||
"label": "Log responses", | ||
"description": "Logs the response of http calls for debugging.", | ||
"secret": False, | ||
"required": False, | ||
"default": False, | ||
}, | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from inline_snapshot import snapshot | ||
from posthog.cdp.templates.helpers import BaseHogFunctionTemplateTest | ||
from posthog.cdp.templates.airtable.template_airtable import template as template_airtable | ||
|
||
|
||
class TestTemplateAirtable(BaseHogFunctionTemplateTest): | ||
template = template_airtable | ||
|
||
def test_function_works(self): | ||
self.run_function( | ||
inputs={ | ||
"access_token": "test_token", | ||
"base_id": "test_base_id", | ||
"table_name": "test_table", | ||
"fields": {"Name": "John Doe", "Email": "[email protected]"}, | ||
"debug": False, | ||
} | ||
) | ||
|
||
assert self.get_mock_fetch_calls()[0] == snapshot( | ||
( | ||
"https://api.airtable.com/v0/test_base_id/test_table", | ||
{ | ||
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"}, | ||
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True}, | ||
"method": "POST", | ||
}, | ||
) | ||
) | ||
assert self.get_mock_print_calls() == snapshot([]) | ||
|
||
def test_prints_when_debugging(self): | ||
self.run_function( | ||
inputs={ | ||
"access_token": "test_token", | ||
"base_id": "test_base_id", | ||
"table_name": "test_table", | ||
"fields": {"Name": "John Doe", "Email": "[email protected]"}, | ||
"debug": True, | ||
} | ||
) | ||
|
||
assert self.get_mock_fetch_calls()[0] == snapshot( | ||
( | ||
"https://api.airtable.com/v0/test_base_id/test_table", | ||
{ | ||
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"}, | ||
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True}, | ||
"method": "POST", | ||
}, | ||
) | ||
) | ||
assert self.get_mock_print_calls() == snapshot( | ||
[ | ||
( | ||
"Request", | ||
"https://api.airtable.com/v0/test_base_id/test_table", | ||
{ | ||
"headers": {"Content-Type": "application/json", "Authorization": "Bearer test_token"}, | ||
"body": {"fields": {"Name": "John Doe", "Email": "[email protected]"}, "typecast": True}, | ||
"method": "POST", | ||
}, | ||
), | ||
("Response", 200, {}), | ||
] | ||
) |