0
# Marketing & Sales Streams
1
2
Stream classes for marketing and sales data including forms, form submissions, owners, and products. These streams provide access to HubSpot's marketing automation and sales enablement features.
3
4
## Capabilities
5
6
### Form Streams
7
8
Access to HubSpot form definitions and form submission data.
9
10
```python { .api }
11
class Forms(ClientSideIncrementalStream):
12
"""
13
Stream for HubSpot form definitions.
14
15
Provides access to form data including:
16
- Form configuration and fields
17
- Form settings and styling
18
- Form submission settings
19
- Form performance metadata
20
- Custom form properties
21
"""
22
23
class FormSubmissions(ClientSideIncrementalStream):
24
"""
25
Stream for HubSpot form submission records.
26
27
Provides access to form submission data including:
28
- Submitted form field values
29
- Submission timestamp and source
30
- Contact information from submission
31
- Form conversion tracking
32
- Page context and referrer information
33
"""
34
```
35
36
### Owner Streams
37
38
Access to HubSpot user and owner information for sales team management.
39
40
```python { .api }
41
class Owners(ClientSideIncrementalStream):
42
"""
43
Stream for HubSpot owner (user) records.
44
45
Provides access to owner data including:
46
- User profile information
47
- Owner permissions and roles
48
- Team assignments
49
- Owner activity status
50
- Custom owner properties
51
"""
52
53
class OwnersArchived(ClientSideIncrementalStream):
54
"""
55
Stream for archived HubSpot owner records.
56
57
Provides access to deactivated or archived
58
owner accounts with historical data.
59
"""
60
```
61
62
### Product & E-commerce Streams
63
64
Access to product catalog and line item data for e-commerce integration.
65
66
```python { .api }
67
class Products(CRMObjectIncrementalStream):
68
"""
69
Stream for HubSpot product records.
70
71
Provides access to product data including:
72
- Product name, description, and SKU
73
- Pricing and cost information
74
- Product categories and properties
75
- Inventory tracking data
76
- Custom product properties
77
"""
78
79
class LineItems(CRMObjectIncrementalStream):
80
"""
81
Stream for HubSpot line item records.
82
83
Provides access to line item data including:
84
- Product associations and quantities
85
- Pricing and discount information
86
- Line item properties
87
- Deal and quote associations
88
- Custom line item properties
89
"""
90
```
91
92
### Goal Streams
93
94
Access to HubSpot goal and performance tracking data.
95
96
```python { .api }
97
class Goals(CRMObjectIncrementalStream):
98
"""
99
Stream for HubSpot goal records.
100
101
Provides access to goal data including:
102
- Goal definitions and targets
103
- Goal progress tracking
104
- Goal assignment and ownership
105
- Performance metrics
106
- Custom goal properties
107
"""
108
```
109
110
### Feedback Streams
111
112
Access to customer feedback and survey response data.
113
114
```python { .api }
115
class FeedbackSubmissions(CRMObjectIncrementalStream):
116
"""
117
Stream for HubSpot feedback submission records.
118
119
Provides access to feedback data including:
120
- Survey responses and ratings
121
- Feedback content and comments
122
- Customer satisfaction scores
123
- Feedback categorization
124
- Custom feedback properties
125
"""
126
```
127
128
## Usage Examples
129
130
### Form Performance Analysis
131
132
```python
133
from source_hubspot.streams import Forms, FormSubmissions, API
134
135
api = API(credentials)
136
137
# Get form definitions
138
forms = Forms(
139
api=api,
140
start_date="2023-01-01T00:00:00Z",
141
credentials=credentials
142
)
143
144
# Get form submissions
145
submissions = FormSubmissions(
146
api=api,
147
start_date="2023-01-01T00:00:00Z",
148
credentials=credentials
149
)
150
151
# Analyze form performance
152
form_performance = {}
153
154
# First, get all forms
155
for form_record in forms.read_records(sync_mode="full_refresh"):
156
form_id = form_record['guid']
157
form_name = form_record['name']
158
form_performance[form_id] = {
159
'name': form_name,
160
'submissions': 0,
161
'unique_contacts': set()
162
}
163
164
# Count submissions per form
165
for submission_record in submissions.read_records(sync_mode="full_refresh"):
166
form_guid = submission_record['formId']
167
contact_email = None
168
169
# Extract email from form values
170
for value in submission_record.get('values', []):
171
if value.get('name') == 'email':
172
contact_email = value.get('value')
173
break
174
175
if form_guid in form_performance:
176
form_performance[form_guid]['submissions'] += 1
177
if contact_email:
178
form_performance[form_guid]['unique_contacts'].add(contact_email)
179
180
# Display results
181
for form_id, data in form_performance.items():
182
unique_count = len(data['unique_contacts'])
183
conversion_rate = (unique_count / data['submissions'] * 100) if data['submissions'] > 0 else 0
184
print(f"Form: {data['name']}")
185
print(f" Submissions: {data['submissions']}")
186
print(f" Unique contacts: {unique_count}")
187
print(f" Conversion rate: {conversion_rate:.1f}%")
188
```
189
190
### Sales Team Performance
191
192
```python
193
from source_hubspot.streams import Owners, Deals
194
195
# Get owner information
196
owners = Owners(
197
api=api,
198
start_date="2023-01-01T00:00:00Z",
199
credentials=credentials
200
)
201
202
# Build owner lookup
203
owner_lookup = {}
204
for owner_record in owners.read_records(sync_mode="full_refresh"):
205
owner_id = str(owner_record['ownerId'])
206
owner_lookup[owner_id] = {
207
'name': f"{owner_record.get('firstName', '')} {owner_record.get('lastName', '')}".strip(),
208
'email': owner_record.get('email', ''),
209
'deals_count': 0,
210
'deals_value': 0
211
}
212
213
# Analyze deals by owner
214
deals = Deals(
215
api=api,
216
start_date="2023-01-01T00:00:00Z",
217
credentials=credentials
218
)
219
220
for deal_record in deals.read_records(sync_mode="full_refresh"):
221
owner_id = deal_record['properties'].get('hubspot_owner_id')
222
deal_amount = float(deal_record['properties'].get('amount', 0) or 0)
223
224
if owner_id and owner_id in owner_lookup:
225
owner_lookup[owner_id]['deals_count'] += 1
226
owner_lookup[owner_id]['deals_value'] += deal_amount
227
228
# Display sales performance
229
print("Sales Team Performance:")
230
sorted_owners = sorted(owner_lookup.items(), key=lambda x: x[1]['deals_value'], reverse=True)
231
for owner_id, data in sorted_owners:
232
if data['deals_count'] > 0:
233
avg_deal_size = data['deals_value'] / data['deals_count']
234
print(f"{data['name']}: {data['deals_count']} deals, ${data['deals_value']:,.2f} total, ${avg_deal_size:,.2f} avg")
235
```
236
237
### Product Catalog Management
238
239
```python
240
from source_hubspot.streams import Products, LineItems
241
242
# Get product catalog
243
products = Products(
244
api=api,
245
start_date="2023-01-01T00:00:00Z",
246
credentials=credentials
247
)
248
249
product_catalog = {}
250
for product_record in products.read_records(sync_mode="full_refresh"):
251
product_id = product_record['id']
252
properties = product_record['properties']
253
254
product_catalog[product_id] = {
255
'name': properties.get('name', 'Unnamed Product'),
256
'price': float(properties.get('price', 0) or 0),
257
'sku': properties.get('sku', ''),
258
'sales_count': 0,
259
'revenue': 0
260
}
261
262
# Analyze line item sales
263
line_items = LineItems(
264
api=api,
265
start_date="2023-01-01T00:00:00Z",
266
credentials=credentials
267
)
268
269
for line_item_record in line_items.read_records(sync_mode="full_refresh"):
270
properties = line_item_record['properties']
271
product_id = properties.get('hs_product_id')
272
quantity = int(properties.get('quantity', 0) or 0)
273
price = float(properties.get('price', 0) or 0)
274
275
if product_id and product_id in product_catalog:
276
product_catalog[product_id]['sales_count'] += quantity
277
product_catalog[product_id]['revenue'] += (quantity * price)
278
279
# Display product performance
280
print("Product Performance:")
281
sorted_products = sorted(product_catalog.items(), key=lambda x: x[1]['revenue'], reverse=True)
282
for product_id, data in sorted_products[:10]: # Top 10 products
283
print(f"{data['name']} (SKU: {data['sku']})")
284
print(f" Units sold: {data['sales_count']}")
285
print(f" Revenue: ${data['revenue']:,.2f}")
286
print(f" Avg selling price: ${data['revenue'] / max(data['sales_count'], 1):,.2f}")
287
```
288
289
### Goal Tracking
290
291
```python
292
from source_hubspot.streams import Goals
293
294
goals = Goals(
295
api=api,
296
start_date="2023-01-01T00:00:00Z",
297
credentials=credentials
298
)
299
300
# Track goal progress
301
goal_progress = {}
302
for goal_record in goals.read_records(sync_mode="full_refresh"):
303
properties = goal_record['properties']
304
goal_name = properties.get('name', 'Unnamed Goal')
305
target_value = float(properties.get('target_value', 0) or 0)
306
current_value = float(properties.get('current_value', 0) or 0)
307
308
progress_percent = (current_value / target_value * 100) if target_value > 0 else 0
309
310
goal_progress[goal_name] = {
311
'target': target_value,
312
'current': current_value,
313
'progress': progress_percent,
314
'status': properties.get('status', 'Unknown')
315
}
316
317
print("Goal Progress:")
318
for goal_name, data in goal_progress.items():
319
status_indicator = "โ " if data['progress'] >= 100 else "๐" if data['progress'] >= 50 else "โ ๏ธ"
320
print(f"{status_indicator} {goal_name}: {data['progress']:.1f}% ({data['current']}/{data['target']})")
321
```
322
323
### Customer Feedback Analysis
324
325
```python
326
from source_hubspot.streams import FeedbackSubmissions
327
328
feedback = FeedbackSubmissions(
329
api=api,
330
start_date="2023-01-01T00:00:00Z",
331
credentials=credentials
332
)
333
334
# Analyze feedback ratings
335
feedback_stats = {
336
'total_responses': 0,
337
'rating_distribution': {},
338
'average_rating': 0,
339
'total_rating': 0
340
}
341
342
for feedback_record in feedback.read_records(sync_mode="full_refresh"):
343
properties = feedback_record['properties']
344
rating = properties.get('rating')
345
346
if rating:
347
rating = float(rating)
348
feedback_stats['total_responses'] += 1
349
feedback_stats['total_rating'] += rating
350
351
rating_bucket = int(rating)
352
if rating_bucket not in feedback_stats['rating_distribution']:
353
feedback_stats['rating_distribution'][rating_bucket] = 0
354
feedback_stats['rating_distribution'][rating_bucket] += 1
355
356
if feedback_stats['total_responses'] > 0:
357
feedback_stats['average_rating'] = feedback_stats['total_rating'] / feedback_stats['total_responses']
358
359
print(f"Customer Feedback Summary:")
360
print(f"Total responses: {feedback_stats['total_responses']}")
361
print(f"Average rating: {feedback_stats['average_rating']:.2f}")
362
print("Rating distribution:")
363
for rating in sorted(feedback_stats['rating_distribution'].keys()):
364
count = feedback_stats['rating_distribution'][rating]
365
percentage = count / feedback_stats['total_responses'] * 100
366
print(f" {rating} stars: {count} ({percentage:.1f}%)")
367
```
368
369
## Stream Base Classes
370
371
### ClientSideIncrementalStream
372
373
Used by forms, owners, and other streams that implement client-side incremental logic.
374
375
```python { .api }
376
class ClientSideIncrementalStream(BaseStream, CheckpointMixin):
377
"""
378
Base class for streams with client-side incremental sync.
379
380
Handles state management and checkpointing for streams
381
that don't support server-side incremental queries.
382
"""
383
```
384
385
### CRMObjectIncrementalStream
386
387
Used by products, line items, goals, and feedback streams.
388
389
```python { .api }
390
class CRMObjectIncrementalStream(CRMObjectStream, IncrementalStream):
391
"""
392
Base class for CRM object streams with incremental sync.
393
394
Combines CRM object functionality with incremental
395
sync capabilities for optimal data synchronization.
396
"""
397
```
398
399
## OAuth Scopes
400
401
Marketing & sales streams require specific OAuth scopes:
402
403
- **Forms**: `forms`
404
- **Form Submissions**: `forms`
405
- **Owners**: `crm.objects.owners.read`
406
- **Products**: `e-commerce`
407
- **Line Items**: `e-commerce`, `crm.objects.line_items.read`
408
- **Goals**: `crm.objects.goals.read`
409
- **Feedback Submissions**: Custom object scopes may apply