Skip to content

Commit ab1c7fa

Browse files
Merge pull request #2613 from segmentio/develop
Release 22.11.2
2 parents 62ab577 + 407b111 commit ab1c7fa

File tree

17 files changed

+794
-265
lines changed

17 files changed

+794
-265
lines changed

Diff for: src/_data/sidenav/main.yml

+2
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ sections:
219219
title: Redshift Cluster and Redshift Connector Limitations
220220
- path: /connections/storage/warehouses/redshift-tuning
221221
title: Speeding Up Redshift Queries
222+
- path: /connections/storage/warehouses/redshift-useful-sql
223+
title: Useful SQL Queries for Redshift
222224
- path: /connections/test-connections
223225
title: Testing Connections
224226
- path: /connections/data-export-options

Diff for: src/_includes/content/how-a-sync-works.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
When Segment loads data into your warehouse, each sync goes through two steps:
2+
1. **Ping:** Segment servers connect to your warehouse. For Redshift warehouses, Segment also runs a query to determine how many slices a cluster has. Common reasons a sync might fail at this step include a blocked VPN or IP, a warehouse that isn't set to be publicly accessible, or an issue with user permissions or credentials.
3+
2. **Load:** Segment de-duplicates the transformed data and loads it into your warehouse. If you have queries set up in your warehouse, they run after the data is loaded into your warehouse.

Diff for: src/_includes/content/spec-table-header.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
<thead>
12
<tr>
23
<th>Field</th>
34
<th></th>
45
<th>Type</th>
56
<th>Description</th>
67
</tr>
8+
</thead>

Diff for: src/_sass/components/_markdown.scss

+5-5
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,10 @@
308308

309309
}
310310

311-
a[target="_blank"]:not(.reference-button):after {
312-
content: url("/docs/images/external-link-alt-solid.svg");
313-
margin-left: 4px;
314-
}
311+
//a[target="_blank"]:not(.reference-button):after {
312+
//content: url("/docs/images/external-link-alt-solid.svg");
313+
// margin-left: 4px;
314+
//}
315315

316316
a.no-icon[target="_blank"]:after {
317317
content: none
@@ -436,4 +436,4 @@ div.highlighter-rouge {
436436
color: black;
437437
font-weight: bold;
438438
margin-left: 3px
439-
}
439+
}
+41-34
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
11
---
2-
title: Sendgrid Source
2+
title: SendGrid Source
33
id: jhr8dT2yHn
44
---
55
{% include content/source-region-unsupported.md %}
66

7-
SendGrid is a trusted platform for transactional email and email marketing. [Visit Website](http://sendgrid.com)
7+
[SendGrid](http://sendgrid.com) is a trusted platform for transactional email and email marketing.
88

9-
Take your company's analysis to the next level by **adding Sendgrid as a Source to Segment.** Segment automatically collects events like `Click` or `Delivered` and objects such as `Recipients` or `Campaigns` and load them into your data warehouse. 
9+
Take your company's analysis to the next level by **adding SendGrid as a Source to Segment.** Segment automatically collects events like `Click` or `Delivered` and objects such as `Recipients` or `Campaigns` and loads them into your data warehouse. 
1010

1111
## Getting Started
1212

13-
1. From the [Source catalog page](https://app.segment.com/goto-my-workspace/sources/catalog) in your Segment workspace, enter "Sendgrid" and select the Sendgrid source that appears.
14-
2. From the Sendgrid information panel that appears, click **Add source**.
13+
Adding SendGrid as a Source in Segment requires a SendGrid API key. If you don't yet have a SendGrid API key, first follow these steps within your SendGrid account:
1514

16-
3. Give the Source a name and add any labels to help you organize and filter your sources.
17-
You can give the source any name, but Segment recommends a name that reflects the source itself, as this name autopopulates the schema name. For example, the source name `Sendgrid` creates the schema `sendgrid`. You can add multiple instances if you have multiple SendGrid accounts.
15+
1. Log in to your SendGrid account.
16+
2. Navigate to **Settings > API Keys**, then click **General API Key**.
17+
3. Name the key and, optionally, adjust its settings.
18+
4. Copy the API Key, omitting all spaces.
1819

19-
4. Provide your API Key. In order to pull information about your contacts, we'll make requests to SendGrid's API with our [sync component](#sync). You can create an API Key by navigating to **Settings > API Keys**, clicking **General API Key**.
20+
> info "SendGrid API Key Settings"
21+
> Segment recommends providing read permissions for **Email Activity** and **Marketing Activity**.
2022
21-
You will then be prompted to name that key and given the option to adjust the settings. We recommend providing read permissions for **Email Activity** and **Marketing Activity**.
23+
To finish adding the SendGrid source, return to your Segment Workspace and follow these steps:
2224

23-
6. Finally, copy the resulting API Key into the Segment interface, taking care to trim any errant trailing spaces from copying and pasting, and press connect.
25+
1. From the [Source catalog page](https://app.segment.com/goto-my-workspace/sources/catalog) in your Segment workspace, enter **SendGrid** and select the SendGrid source that appears.
26+
2. From the SendGrid information panel that appears, click **Add source**.
27+
3. Give the Source a name and add any labels to help you organize and filter your sources.
28+
Segment recommends a name that reflects the source itself, as this name populates the schema name. For example, the source name `SendGrid` creates the schema `SendGrid`. You can add multiple instances if you have multiple SendGrid accounts.
29+
4. Paste the SendGrid API Key you copied above into the Segment interface. Click **Connect**.
30+
![](images/601347_Key.png)
2431

25-
![](images/601347_Key.png)
32+
6. Copy the auto-generated Webhook URL and paste it into SendGrid's Event Notification settings pane under **Settings > Mail Settings**.
33+
![](images/694785_Webhook.png)
2634

27-
7. Copy the auto-generated Webhook URL and paste it into SendGrid's Event Notification settings pane under **Settings > Mail Settings**.
28-
29-
![](images/694785_Webhook.png)
30-
31-
8. Once you enable the Event Notification, you're good to go! Press **Next**, and then **Finish** to wrap up the set up flow.
35+
7. Enable Event Notification in SendGrid. Select **Next** and then **Finish** to complete setup.
3236

3337
### Event URL
3438

@@ -38,51 +42,54 @@ SendGrid has a single Event URL location. By using the SendGrid source, you will
3842

3943
### Sync
4044

41-
SendGrid has a sync component, which means we'll make requests to their API on your behalf on a 3 hour interval to pull the latest data into Segment. In the initial sync, we'll grab all the SendGrid objects (and their corresponding properties) according to the [Collections Table](#collections) below. **Note**: If you don't use Sendgrid's marketing campaigns features, these collections will be empty in Sendgrid and you'll see "Zero data synced" in your runs. The webhook will still be processing activity data (but only activity data) for you though!
45+
Segment makes requests to the SendGrid API every three hours. In the initial sync, Segment pulls all SendGrid objects (and their corresponding properties) according to the [Collections Table](#collections) below. If you don't use SendGrid's marketing campaigns features, these collections will be empty in SendGrid and you'll see "Zero data synced" in your runs. The webhook still processes activity data.
4246

43-
Our sync component gets resources from SendGrid and forwards them to Segment using an upsert API, so the dimensional data in your warehouse loaded will reflect the latest state of the corresponding resource in SendGrid. For example, if `lists.recipient_count` goes from `100` to `200` between syncs, on its next flush to your warehouse, that tickets status will be `200`.
47+
Segment's sync component pulls and forwards SendGrid resources to Segment using an upsert API. As a result, dimensional data loaded into your warehouse reflects the latest state of the corresponding resource in SendGrid. For example, if `lists.recipient_count` goes from `100` to `200` between syncs, its status will be `200` on its next flush to your warehouse.
4448

45-
The source syncs and warehouse syncs are independent processes. Source runs pull your data into the Segment Hub, and warehouse runs flush that data to your warehouse. Sources will sync with Segment every 3 hours. Depending on your Warehouses plan, we will push the Source data to your warehouse on the interval associated with your billing plan.
46-
47-
At the moment, we don't support filtering which objects or properties get synced. If you're interested in this feature, [let us know](https://segment.com/help/contact/)!
49+
The source syncs and warehouse syncs are independent processes. Source runs pull your data into the Segment Hub, and warehouse runs flush that data to your warehouse. Sources sync with Segment every three hours. Depending on your Warehouses plan, Segment pushes the Source data to your warehouse on the interval associated with your billing plan.
4850

51+
> info "SendGrid Syncs"
52+
> Segment syncs all objects and properties. [Reach out to support](https://segment.com/help/contact/) if you're interested in filtering objects or properties during syncs.
4953
5054
### Streaming
5155

52-
The SendGrid source also has a streaming component which listens in real time for inbound webhooks from SendGrid's Event Notifications and batches the events to be uploaded on your next warehouse flush. **These events only append to your warehouse.**
56+
The SendGrid source's streaming component listens in real time for inbound webhooks from SendGrid's Event Notifications. The source batches these events for upload on your next warehouse flush. **These events only append to your warehouse.**
5357

5458
> note ""
5559
> **NOTE:** If you don't use SendGrid's marketing features, this will be the only data that Segment receives from SendGrid. There isn't a way to retrieve email event history from SendGrid, so you will only have access to data that Segment collected after you successfully enable this component of the source destination.
5660
5761

5862
## Collections
5963

60-
Collections are the groupings of resources we pull from your source. In your warehouse, each collection gets its own table.
64+
Collections are the groupings of resources Segment pulls from your source. In your warehouse, each collection gets its own table.
6165

6266
**Object** collections are updated with each sync. These are pulled using Segment's sync component.
6367

64-
**Event** collections are append only, represent a user action or activity, and may be likened to fact tables in a traditional data warehouse. **Note:** Unlike traditional events captured by Segment, you can't forward these events to Destinations you've configured in your Segment workspace. You can only sync these events to a supported data warehouse.
68+
**Event** collections are append only, represent a user action or activity, and may be likened to fact tables in a traditional data warehouse. Unlike traditional events captured by Segment, you can't forward these events to Destinations you've configured in your Segment workspace. You can only sync these events to a supported data warehouse.
6569

6670

6771
| Collection | Type | Description |
6872
| ------ | ------ | ------ |
69-
| activity | Event | The union of all SendGrid **event** tables. Useful for creating funnels |
70-
| _open | Event | Recipient has opened the HTML message. You need to enable Open Tracking for getting this type of event. |
71-
| click | Event | Recipient clicked on a link within the message. You need to enable Click Tracking for getting this type of event. |
73+
| activity | Event | The union of all SendGrid **event** tables. Useful for creating funnels. |
74+
| _open | Event | Recipient has opened the HTML message. Enable Open Tracking to get this type of event. |
75+
| click | Event | Recipient clicked on a link within the message. Enable Click Tracking to get this type of event. |
7276
| bounce | Event | Receiving server could not or would not accept message. |
7377
| delivered | Event | Message has been successfully delivered to the receiving server. |
74-
| processed | Event | Triggered when the email is processed |
78+
| processed | Event | Triggered when the email is processed. |
7579
| dropped | Event | You may see the following drop reasons: Invalid SMTPAPI header, Spam Content (if spam checker app enabled), Unsubscribed Address, Bounced Address, Spam Reporting Address, Invalid, Recipient List over Package Quota |
7680
| deferred | Event | Recipient's email server temporarily rejected message. |
7781
| unsubscribe | Event | Recipient clicked on message's subscription management link. You need to enable Subscription Tracking for getting this type of event. |
7882
| spam_report | Event | Recipient marked message as spam. |
79-
| lists | Object | [Groups of contacts](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using Marketing Campaign features of SendGrid.** |
80-
| segments | Object | [Slices of lists](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using Marketing Campaign features of SendGrid.** |
81-
| recipients | Object | All contacts who have received an email, with information about their last activities and custom activities. [More Info](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using Marketing Campaign features of SendGrid.** |
82-
| campaigns | Object | All campaigns you've created in Sendgrid. [More Info](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/campaigns.html). **Will only return data if you're using Marketing Campaign features of SendGrid.** |
83+
| lists | Object | [Groups of contacts](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using SendGrid's Marketing Campaign features.** |
84+
| segments | Object | [Slices of lists](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using SendGrid's Marketing Campaign features.** |
85+
| recipients | Object | All contacts who have received an email, with information about their last activities and custom activities. [More Info](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/contactdb.html). **Will only return data if you're using SendGrid's Marketing Campaign features.** |
86+
| campaigns | Object | All campaigns you've created in SendGrid. [More Info](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/campaigns.html). **Will only return data if you're using SendGrid's Marketing Campaign features.** |
87+
88+
> info "SendGrid and Personas"
89+
> SendGrid data is not available in Personas.
8390
84-
## Troubleshooting
91+
## Troubleshooting
8592

8693
If you're getting an "Invalid Credentials" error when setting up the SendGrid source, send a direct ping to the [SendGrid Marketing Campaigns API](https://sendgrid.com/docs/API_Reference/Web_API_v3/Marketing_Campaigns/campaigns.html) to test if you're using the correct credentials.
8794

88-
Make sure you whitelist the Segment IP addresses on Sendgrid. [Contact Segment](https://segment.com/help/contact/) for the list of IP addresses to whitelist.
95+
Make sure you allowlist Segment IP addresses on SendGrid. [Contact Segment](https://segment.com/help/contact/) for the list of IP addresses to allowlist.

Diff for: src/connections/sources/catalog/libraries/server/java/index.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Add to `pom.xml`:
3838
or if you're using Gradle:
3939

4040
```bash
41-
compile 'com.segment.analytics.java:analytics:+'
41+
implementation 'com.segment.analytics.java:analytics:+'
4242
```
4343

4444
### Initialize the SDK
@@ -74,14 +74,13 @@ We recommend calling `identify` a single time when the user's account is first c
7474
Example `identify` call:
7575

7676
```java
77+
Map<String, String> map = new HashMap();
78+
map.put("name", "Michael Bolton");
79+
map.put("email", "[email protected]");
80+
7781
analytics.enqueue(IdentifyMessage.builder()
78-
.userId("f4ca124298")
79-
.traits(ImmutableMap.builder()
80-
.put("name", "Michael Bolton")
81-
.put("email", "[email protected]")
82-
.build()
83-
)
84-
);
82+
.userId("f4ca124298")
83+
.traits(map));
8584
```
8685

8786
This call is identifying Michael by his unique User ID (the one you know him by in your database) and labeling him with `name` and `email` traits.

Diff for: src/connections/sources/catalog/libraries/server/java/quickstart.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Here's what it would look like with Maven:
4040
*or if you're using Gradle:*
4141

4242
```bash
43-
compile 'com.segment.analytics.java:analytics:+'
43+
implementation 'com.segment.analytics.java:analytics:+'
4444
```
4545

4646
## Step 3: Initialize the SDK
@@ -71,14 +71,13 @@ The `identify` message is how you tell Segment who the current user is. It inclu
7171
Here's what a basic call to `identify` a user might look like:
7272

7373
```java
74+
Map<String, String> map = new HashMap();
75+
map.put("name", "Michael Bolton");
76+
map.put("email", "[email protected]");
77+
7478
analytics.enqueue(IdentifyMessage.builder()
75-
.userId("f4ca124298")
76-
.traits(ImmutableMap.builder()
77-
.put("name", "Michael Bolton")
78-
.put("email", "[email protected]")
79-
.build()
80-
)
81-
);
79+
.userId("f4ca124298")
80+
.traits(map));
8281
```
8382

8483
**Note:** The enqueue method takes a `MessageBuilder` instance and not a `Message` instance directly. This is to allow you to use a `MessageTransformer` that applies to all incoming messages and transform or add data. <!-- LR: Can't find that we ever had a doc about this. Read more about it in the [transformer reference docs](/docs/connections/sources/catalog/libraries/server/java#transformer).-->

Diff for: src/connections/sources/catalog/libraries/server/node/index.md

+78
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,84 @@ analytics.flush(function(err, batch){
437437
});
438438
```
439439

440+
## Long running process
441+
442+
You should call `client.track(...)` and know that events will be queued and eventually sent to Segment. To prevent losing messages, be sure to capture any interruption (for example, a server restart) and call flush to know of and delay the process shutdown.
443+
444+
```js
445+
import { randomUUID } from 'crypto';
446+
import Analytics from 'analytics-node'
447+
448+
const WRITE_KEY = '...';
449+
450+
const analytics = new Analytics(WRITE_KEY, { flushAt: 10 });
451+
452+
analytics.track({
453+
anonymousId: randomUUID(),
454+
event: 'Test event',
455+
properties: {
456+
name: 'Test event',
457+
timestamp: new Date()
458+
}
459+
});
460+
461+
const exitGracefully = async (code) => {
462+
console.log('Flushing events');
463+
await analytics.flush(function(err, batch) {
464+
console.log('Flushed, and now this program can exit!');
465+
process.exit(code);
466+
});
467+
};
468+
469+
[
470+
'beforeExit', 'uncaughtException', 'unhandledRejection',
471+
'SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP',
472+
'SIGABRT','SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV',
473+
'SIGUSR2', 'SIGTERM',
474+
].forEach(evt => process.on(evt, exitGracefully));
475+
476+
function logEvery2Seconds(i) {
477+
setTimeout(() => {
478+
console.log('Infinite Loop Test n:', i);
479+
logEvery2Seconds(++i);
480+
}, 2000);
481+
}
482+
483+
logEvery2Seconds(0);
484+
```
485+
486+
## Short lived process
487+
488+
Short-lived functions have a predictably short and linear lifecycle, so use a queue big enough to hold all messages and then await flush to complete its work.
489+
490+
491+
```js
492+
import { randomUUID } from 'crypto';
493+
import Analytics from 'analytics-node'
494+
495+
496+
async function lambda()
497+
{
498+
const WRITE_KEY = '...';
499+
const analytics = new Analytics(WRITE_KEY, { flushAt: 20 });
500+
analytics.flushed = true;
501+
502+
analytics.track({
503+
anonymousId: randomUUID(),
504+
event: 'Test event',
505+
properties: {
506+
name: 'Test event',
507+
timestamp: new Date()
508+
}
509+
});
510+
await analytics.flush(function(err, batch) {
511+
console.log('Flushed, and now this program can exit!');
512+
});
513+
}
514+
515+
lambda();
516+
```
517+
440518

441519
## Multiple Clients
442520

0 commit comments

Comments
 (0)