Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉Source HubSpot: Adds form_submission and property_history streams #7787

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
199af24
Began working on HubSpot Form Submission Connector
tinomerl Oct 29, 2021
82a2f05
Added Property History Stream
tinomerl Nov 4, 2021
0eb236b
Merge branch 'airbytehq:master' into tinomerl/6493-source-hubspot-add…
tinomerl Nov 5, 2021
b75cf88
Added form_guid to as value to form_submissions_stream.
tinomerl Nov 5, 2021
51bfcca
Merge branch 'tinomerl/6493-source-hubspot-add-stream-contact_form_su…
tinomerl Nov 5, 2021
7ca726f
Finalized the Form Submission Stream
tinomerl Nov 8, 2021
d57cb35
Merge branch 'airbytehq:master' into tinomerl/6493-source-hubspot-add…
tinomerl Nov 8, 2021
073ccee
Merge branch 'airbytehq:master' into tinomerl/6493-source-hubspot-add…
tinomerl Nov 8, 2021
c83f648
Added documentation and test config
tinomerl Nov 9, 2021
47fc2e9
Merge branch 'tinomerl/6493-source-hubspot-add-stream-contact_form_su…
tinomerl Nov 9, 2021
70bf991
Corrected Version Number
tinomerl Nov 9, 2021
4af7867
Merge branch 'airbytehq:master' into tinomerl/6493-source-hubspot-add…
tinomerl Nov 9, 2021
2c47b9b
Merge branch 'master' into tinomerl/6493-source-hubspot-add-stream-co…
tinomerl Nov 15, 2021
365ee80
updated version number to 0.1.25
tinomerl Nov 15, 2021
e3c4821
Merge branch 'tinomerl/6493-source-hubspot-add-stream-contact_form_su…
marcosmarxm Nov 18, 2021
8a2ca7d
removed or none worked on tests
tinomerl Nov 22, 2021
f5934ac
Merge branch 'tinomerl/6493-source-hubspot-add-stream-contact_form_su…
marcosmarxm Dec 7, 2021
47ed536
Merge branch 'master' into tinomerl/6493-source-hubspot-add-stream-co…
tinomerl Jan 10, 2022
58af14b
Changed code due to review comments & merges
tinomerl Jan 11, 2022
e63ac85
Merge remote-tracking branch 'origin/master' into tinomerl/6493-sourc…
tinomerl Jan 21, 2022
0beda4f
readded Propertyhistory after merging
tinomerl Jan 21, 2022
f4767f9
Merge branch 'tinomerl/6493-source-hubspot-add-stream-contact_form_su…
marcosmarxm Jan 26, 2022
15e450d
merge master and contrib code
marcosmarxm Jan 26, 2022
bd1a82f
bump connector version
marcosmarxm Jan 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"sourceDefinitionId": "36c891d9-4bd9-43ac-bad2-10e12756272c",
"name": "HubSpot",
"dockerRepository": "airbyte/source-hubspot",
"dockerImageTag": "0.1.35",
"dockerImageTag": "0.1.36",
"documentationUrl": "https://docs.airbyte.io/integrations/sources/hubspot",
"icon": "hubspot.svg"
}
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
- name: HubSpot
sourceDefinitionId: 36c891d9-4bd9-43ac-bad2-10e12756272c
dockerRepository: airbyte/source-hubspot
dockerImageTag: 0.1.35
dockerImageTag: 0.1.36
documentationUrl: https://docs.airbyte.io/integrations/sources/hubspot
icon: hubspot.svg
sourceType: api
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3067,7 +3067,7 @@
supportsNormalization: false
supportsDBT: false
supported_destination_sync_modes: []
- dockerImage: "airbyte/source-hubspot:0.1.35"
- dockerImage: "airbyte/source-hubspot:0.1.36"
spec:
documentationUrl: "https://docs.airbyte.io/integrations/sources/hubspot"
connectionSpecification:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ COPY source_hubspot ./source_hubspot
ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]

LABEL io.airbyte.version=0.1.35
LABEL io.airbyte.version=0.1.36
LABEL io.airbyte.name=airbyte/source-hubspot
8 changes: 4 additions & 4 deletions airbyte-integrations/connectors/source-hubspot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ and place them into `secrets/config.json`.

### Locally running the connector
```
python main_dev.py spec
python main_dev.py check --config secrets/config.json
python main_dev.py discover --config secrets/config.json
python main_dev.py read --config secrets/config.json --catalog sample_files/configured_catalog.json
python main.py spec
python main.py check --config secrets/config.json
python main.py discover --config secrets/config.json
python main.py read --config secrets/config.json --catalog sample_files/configured_catalog.json
```

## Testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ tests:
- config_path: "secrets/config.json"
basic_read:
- config_path: "secrets/config.json"
timeout_seconds: 600
configured_catalog_path: "sample_files/full_refresh_catalog.json"
empty_streams: ["workflows", "form_submissions", "ticket_pipelines"]
empty_streams: ["workflows", "form_submissions", "ticket_pipelines", "property_history"]
- config_path: "secrets/config_oauth.json"
timeout_seconds: 600
configured_catalog_path: "sample_files/configured_catalog_for_oauth_config.json"
# The `campaigns` stream is empty in this case, because we use a catalog with
# incremental streams: subscription_changes and email_events (it takes a long time to read)
# and therefore the start date is set at 2021-10-10 for `config_oauth.json`,
# but the campaign was created on 2021-01-11
empty_streams: ["campaigns", "workflows", "contacts_list_memberships", "form_submissions", "ticket_pipelines"]
empty_streams: ["campaigns", "workflows", "contacts_list_memberships", "form_submissions", "ticket_pipelines", "property_history"]
incremental:
- config_path: "secrets/config.json"
configured_catalog_path: "sample_files/configured_catalog.json"
Expand All @@ -34,6 +36,7 @@ tests:
subscription_changes: ["timestamp"]
email_events: ["timestamp"]
contact_lists: ["timestamp"]
property_history: ["timestamp"]
full_refresh:
- config_path: "secrets/config.json"
configured_catalog_path: "sample_files/full_refresh_catalog.json"
Expand Down Expand Up @@ -68,6 +71,8 @@ tests:
"tickets": ["properties", "hs_time_in_2"]
"tickets": ["properties", "hs_time_in_3"]
"tickets": ["properties", "hs_time_in_4"]
"property_history": ["property", "hs_time_in_lead"]
"property_history": ["property", "hs_time_in_subscriber"]
- config_path: "secrets/config_oauth.json"
configured_catalog_path: "sample_files/configured_catalog_for_oauth_config.json"
ignored_fields:
Expand Down Expand Up @@ -101,3 +106,5 @@ tests:
"tickets": ["properties", "hs_time_in_2"]
"tickets": ["properties", "hs_time_in_3"]
"tickets": ["properties", "hs_time_in_4"]
"property_history": ["property", "hs_time_in_lead"]
"property_history": ["property", "hs_time_in_subscriber"]
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "form_submissions",
"json_schema": {},
"supported_sync_modes": ["full_refresh"]
},
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "line_items",
Expand Down Expand Up @@ -165,6 +174,17 @@
"cursor_field": ["updatedAt"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "property_history",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"default_cursor_field": ["timestamp"]
},
"sync_mode": "full_refresh",
"cursor_field": ["timestamp"],
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "quotes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add property_history stream too

"name": "form_submissions",
"json_schema": {},
"supported_sync_modes": ["full_refresh"]
},
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "forms",
Expand Down Expand Up @@ -141,6 +150,17 @@
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "property_history",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"default_cursor_field": ["timestamp"]
},
"default_cursor_field": ["timestamp"],
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "subscription_changes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "property_history",
"json_schema": {},
"supported_sync_modes": ["full_refresh"]
},
"sync_mode": "full_refresh",
"destination_sync_mode": "overwrite"
},
{
"stream": {
"name": "quotes",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"start_date": "2020-01-01T00:00:00Z",
"credentials": {
"credentials_title": "API Key Credentials",
"api_key": "demo"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"start_date": "2021-10-01T00:00:00Z",
"credentials": {
"credentials_title": "OAuth Credentials",
"client_id": "123456789_client_id_hubspot",
"client_secret": "123456789_client_secret_hubspot",
"refresh_token": "123456789_some_refresh_token"
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from abc import ABC, abstractmethod
from functools import lru_cache, partial
from http import HTTPStatus
from typing import Any, Callable, Iterable, Iterator, List, Mapping, MutableMapping, Optional, Tuple, Union
from typing import Any, Callable, Dict, Iterable, Iterator, List, Mapping, MutableMapping, Optional, Tuple, Union

import backoff
import pendulum as pendulum
Expand Down Expand Up @@ -919,6 +919,50 @@ class OwnerStream(Stream):
created_at_field = "createdAt"


class PropertyHistoryStream(IncrementalStream):
"""Contacts Endpoint, API v1
Is used to get all Contacts and the history of their respective
Properties. Whenever a property is changed it is added here.
Docs: https://legacydocs.hubspot.com/docs/methods/contacts/get_contacts
"""

more_key = "has-more"
url = "/contacts/v1/lists/recently_updated/contacts/recent"
updated_at_field = "timestamp"
created_at_field = "timestamp"
data_field = "contacts"
page_field = "vid-offset"
page_filter = "vidOffset"
limit = 100

def list(self, fields) -> Iterable:
properties = self._api.get("/properties/v2/contact/properties")
properties_list = [single_property["name"] for single_property in properties]
params = {"propertyMode": "value_and_history", "property": properties_list}
yield from self.read(partial(self._api.get, url=self.url), params)

def _transform(self, records: Iterable) -> Iterable:
for record in records:
properties = record.get("properties")
vid = record.get("vid")
value_dict: Dict
for key, value_dict in properties.items():
versions = value_dict.get("versions")
if key == "lastmodifieddate":
# Skipping the lastmodifieddate since it only returns the value
# when one field of a contact was changed no matter which
# field was changed. It therefore creates overhead, since for
# every changed property there will be the date it was changed in itself
# and a change in the lastmodifieddate field.
continue
if versions:
for version in versions:
version["timestamp"] = self._field_to_datetime(version["timestamp"]).to_datetime_string()
version["property"] = key
version["vid"] = vid
yield version


class SubscriptionChangeStream(IncrementalStream):
"""Subscriptions timeline for a portal, API v1
Docs: https://legacydocs.hubspot.com/docs/methods/email/get_subscriptions_timeline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
FormSubmissionStream,
MarketingEmailStream,
OwnerStream,
PropertyHistoryStream,
SubscriptionChangeStream,
TicketPipelineStream,
WorkflowStream,
Expand Down Expand Up @@ -58,6 +59,7 @@ def __init__(self, start_date, credentials, **kwargs):
"marketing_emails": MarketingEmailStream(**common_params),
"owners": OwnerStream(**common_params),
"products": CRMObjectIncrementalStream(entity="product", **common_params),
"property_history": PropertyHistoryStream(**common_params),
"subscription_changes": SubscriptionChangeStream(**common_params),
"tickets": CRMObjectIncrementalStream(entity="ticket", **common_params),
"ticket_pipelines": TicketPipelineStream(**common_params),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": ["null", "object"],
"properties": {
"value": {
"type": ["null", "string"]
},
"source-type": {
"type": ["null", "string"]
},
"source-id": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question as here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Property can either be changed by workflow, form or manully. The id for either is saved in the source-id . The thin is, that for workflow the id is really a id as in integer. but the id of a form is a mixture of characters and numbers. Therefore it is safer to just cast this as a string.

"type": ["null", "string"]
},
"source-label": {
"type": ["null", "string"]
},
"updated-by-user-id" : {
"type": ["null", "integer"]
},
"timestamp": {
"type": ["null", "string"],
"format": "date-time"
},
"selected": {
"type": ["null", "boolean"]
},
"property": {
"type": ["null", "string"]
},
"vid": {
"type": ["null", "integer"]
}
}
}
3 changes: 3 additions & 0 deletions docs/integrations/sources/hubspot.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,11 @@ If you are using Oauth, most of the streams require the appropriate [scopes](htt
| `email_events` | `content` |
| `engagements` | `contacts` |
| `forms` | `forms` |
| `form_submissions`| `forms` |
| `line_items` | `e-commerce` |
| `owners` | `contacts` |
| `products` | `e-commerce` |
| `property_history` | `contacts` |
| `quotes` | no scope required |
| `subscription_changes` | `content` |
| `tickets` | `tickets` |
Expand All @@ -110,6 +112,7 @@ If you are using Oauth, most of the streams require the appropriate [scopes](htt

| Version | Date | Pull Request | Subject |
|:--------|:-----------| :--- |:-----------------------------------------------------------------------------------------------------------------------------------------------|
| 0.1.36 | 2022-01-22 | [7784](https://github.com/airbytehq/airbyte/pull/7784) | Add Property History Stream |
| 0.1.35 | 2021-12-24 | [9081](https://github.com/airbytehq/airbyte/pull/9081) | Add Feedback Submissions stream and update Ticket Pipelines stream |
| 0.1.34 | 2022-01-20 | [9641](https://github.com/airbytehq/airbyte/pull/9641) | Add more fields for `email_events` stream |
| 0.1.33 | 2022-01-14 | [8887](https://github.com/airbytehq/airbyte/pull/8887) | More efficient support for incremental updates on Companies, Contact, Deals and Engagement streams |
Expand Down