Mailchimp report plugin
This commit is contained in:
parent
e6517d4140
commit
6c23fb3173
|
@ -5,9 +5,12 @@
|
||||||
- [#410](https://github.com/influxdb/telegraf/pull/410): Additional redis metrics. Thanks @vlaadbrain!
|
- [#410](https://github.com/influxdb/telegraf/pull/410): Additional redis metrics. Thanks @vlaadbrain!
|
||||||
- [#414](https://github.com/influxdb/telegraf/issues/414): Jolokia plugin auth parameters
|
- [#414](https://github.com/influxdb/telegraf/issues/414): Jolokia plugin auth parameters
|
||||||
- [#415](https://github.com/influxdb/telegraf/issues/415): memcached plugin: support unix sockets
|
- [#415](https://github.com/influxdb/telegraf/issues/415): memcached plugin: support unix sockets
|
||||||
|
- [#418](https://github.com/influxdb/telegraf/pull/418): memcached plugin additional unit tests.
|
||||||
|
- [#408](https://github.com/influxdb/telegraf/pull/408): MailChimp plugin.
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
- [#405](https://github.com/influxdb/telegraf/issues/405): Prometheus output cardinality issue
|
- [#405](https://github.com/influxdb/telegraf/issues/405): Prometheus output cardinality issue
|
||||||
|
- [#388](https://github.com/influxdb/telegraf/issues/388): Fix collection hangup when cpu times decrement.
|
||||||
|
|
||||||
## v0.2.3 [2015-11-30]
|
## v0.2.3 [2015-11-30]
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ Telegraf currently has support for collecting metrics from:
|
||||||
* jolokia (remote JMX with JSON over HTTP)
|
* jolokia (remote JMX with JSON over HTTP)
|
||||||
* leofs
|
* leofs
|
||||||
* lustre2
|
* lustre2
|
||||||
|
* mailchimp
|
||||||
* memcached
|
* memcached
|
||||||
* mongodb
|
* mongodb
|
||||||
* mysql
|
* mysql
|
||||||
|
|
4
agent.go
4
agent.go
|
@ -114,6 +114,10 @@ func (a *Agent) gatherParallel(pointChan chan *client.Point) error {
|
||||||
}(plugin)
|
}(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if counter == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
_ "github.com/influxdb/telegraf/plugins/kafka_consumer"
|
_ "github.com/influxdb/telegraf/plugins/kafka_consumer"
|
||||||
_ "github.com/influxdb/telegraf/plugins/leofs"
|
_ "github.com/influxdb/telegraf/plugins/leofs"
|
||||||
_ "github.com/influxdb/telegraf/plugins/lustre2"
|
_ "github.com/influxdb/telegraf/plugins/lustre2"
|
||||||
|
_ "github.com/influxdb/telegraf/plugins/mailchimp"
|
||||||
_ "github.com/influxdb/telegraf/plugins/memcached"
|
_ "github.com/influxdb/telegraf/plugins/memcached"
|
||||||
_ "github.com/influxdb/telegraf/plugins/mongodb"
|
_ "github.com/influxdb/telegraf/plugins/mongodb"
|
||||||
_ "github.com/influxdb/telegraf/plugins/mysql"
|
_ "github.com/influxdb/telegraf/plugins/mysql"
|
||||||
|
|
|
@ -29,7 +29,7 @@ ConnsAsyncClosing: 205
|
||||||
Scoreboard: WW_____W_RW_R_W__RRR____WR_W___WW________W_WW_W_____R__R_WR__WRWR_RRRW___R_RWW__WWWRW__R_RW___RR_RW_R__W__WR_WWW______WWR__R___R_WR_W___RW______RR________________W______R__RR______W________________R____R__________________________RW_W____R_____W_R_________________R____RR__W___R_R____RW______R____W______W_W_R_R______R__R_R__________R____W_______WW____W____RR__W_____W_R_______W__________W___W____________W_______WRR_R_W____W_____R____W_WW_R____RRW__W............................................................................................................................................................................................................................................................................................................WRRWR____WR__RR_R___RWR_________W_R____RWRRR____R_R__RW_R___WWW_RW__WR_RRR____W___R____WW_R__R___RR_W_W_RRRRWR__RRWR__RRW_W_RRRW_R_RR_W__RR_RWRR_R__R___RR_RR______R__RR____R_____W_R_R_R__R__R__________W____WW_R___R_R___R_________RR__RR____RWWWW___W_R________R_R____R_W___W___R___W_WRRWW_______R__W_RW_______R________RR__R________W_______________________W_W______________RW_________WR__R___R__R_______________WR_R_________W___RW_____R____________W____......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
Scoreboard: WW_____W_RW_R_W__RRR____WR_W___WW________W_WW_W_____R__R_WR__WRWR_RRRW___R_RWW__WWWRW__R_RW___RR_RW_R__W__WR_WWW______WWR__R___R_WR_W___RW______RR________________W______R__RR______W________________R____R__________________________RW_W____R_____W_R_________________R____RR__W___R_R____RW______R____W______W_W_R_R______R__R_R__________R____W_______WW____W____RR__W_____W_R_______W__________W___W____________W_______WRR_R_W____W_____R____W_WW_R____RRW__W............................................................................................................................................................................................................................................................................................................WRRWR____WR__RR_R___RWR_________W_R____RWRRR____R_R__RW_R___WWW_RW__WR_RRR____W___R____WW_R__R___RR_W_W_RRRRWR__RRWR__RRW_W_RRRW_R_RR_W__RR_RWRR_R__R___RR_RR______R__RR____R_____W_R_R_R__R__R__________W____WW_R___R_R___R_________RR__RR____RWWWW___W_R________R_R____R_W___W___R___W_WRRWW_______R__W_RW_______R________RR__R________W_______________________W_W______________RW_________WR__R___R__R_______________WR_R_________W___RW_____R____________W____......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
||||||
`
|
`
|
||||||
|
|
||||||
func TestHTTPInflux(t *testing.T) {
|
func TestHTTPApache(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintln(w, apacheStatus)
|
fmt.Fprintln(w, apacheStatus)
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
package mailchimp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
reports_endpoint string = "/3.0/reports"
|
||||||
|
reports_endpoint_campaign string = "/3.0/reports/%s"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mailchimp_datacenter = regexp.MustCompile("[a-z]+[0-9]+$")
|
||||||
|
|
||||||
|
type ChimpAPI struct {
|
||||||
|
Transport http.RoundTripper
|
||||||
|
Debug bool
|
||||||
|
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
|
url *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReportsParams struct {
|
||||||
|
Count string
|
||||||
|
Offset string
|
||||||
|
SinceSendTime string
|
||||||
|
BeforeSendTime string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ReportsParams) String() string {
|
||||||
|
v := url.Values{}
|
||||||
|
if p.Count != "" {
|
||||||
|
v.Set("count", p.Count)
|
||||||
|
}
|
||||||
|
if p.Offset != "" {
|
||||||
|
v.Set("offset", p.Offset)
|
||||||
|
}
|
||||||
|
if p.BeforeSendTime != "" {
|
||||||
|
v.Set("before_send_time", p.BeforeSendTime)
|
||||||
|
}
|
||||||
|
if p.SinceSendTime != "" {
|
||||||
|
v.Set("since_send_time", p.SinceSendTime)
|
||||||
|
}
|
||||||
|
return v.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewChimpAPI(apiKey string) *ChimpAPI {
|
||||||
|
u := &url.URL{}
|
||||||
|
u.Scheme = "https"
|
||||||
|
u.Host = fmt.Sprintf("%s.api.mailchimp.com", mailchimp_datacenter.FindString(apiKey))
|
||||||
|
u.User = url.UserPassword("", apiKey)
|
||||||
|
return &ChimpAPI{url: u}
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIError struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Detail string `json:"detail"`
|
||||||
|
Instance string `json:"instance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e APIError) Error() string {
|
||||||
|
return fmt.Sprintf("ERROR %v: %v. See %v", e.Status, e.Title, e.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
func chimpErrorCheck(body []byte) error {
|
||||||
|
var e APIError
|
||||||
|
json.Unmarshal(body, &e)
|
||||||
|
if e.Title != "" || e.Status != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ChimpAPI) GetReports(params ReportsParams) (ReportsResponse, error) {
|
||||||
|
a.Lock()
|
||||||
|
defer a.Unlock()
|
||||||
|
a.url.Path = reports_endpoint
|
||||||
|
|
||||||
|
var response ReportsResponse
|
||||||
|
rawjson, err := runChimp(a, params)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawjson, &response)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ChimpAPI) GetReport(campaignID string) (Report, error) {
|
||||||
|
a.Lock()
|
||||||
|
defer a.Unlock()
|
||||||
|
a.url.Path = fmt.Sprintf(reports_endpoint_campaign, campaignID)
|
||||||
|
|
||||||
|
var response Report
|
||||||
|
rawjson, err := runChimp(a, ReportsParams{})
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(rawjson, &response)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runChimp(api *ChimpAPI, params ReportsParams) ([]byte, error) {
|
||||||
|
client := &http.Client{Transport: api.Transport}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
req, err := http.NewRequest("GET", api.url.String(), &b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.URL.RawQuery = params.String()
|
||||||
|
req.Header.Set("User-Agent", "Telegraf-MailChimp-Plugin")
|
||||||
|
if api.Debug {
|
||||||
|
log.Printf("Request URL: %s", req.URL.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if api.Debug {
|
||||||
|
log.Printf("Response Body:%s", string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = chimpErrorCheck(body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReportsResponse struct {
|
||||||
|
Reports []Report `json:"reports"`
|
||||||
|
TotalItems int `json:"total_items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Report struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
CampaignTitle string `json:"campaign_title"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
EmailsSent int `json:"emails_sent"`
|
||||||
|
AbuseReports int `json:"abuse_reports"`
|
||||||
|
Unsubscribed int `json:"unsubscribed"`
|
||||||
|
SendTime string `json:"send_time"`
|
||||||
|
|
||||||
|
TimeSeries []TimeSerie
|
||||||
|
Bounces Bounces `json:"bounces"`
|
||||||
|
Forwards Forwards `json:"forwards"`
|
||||||
|
Opens Opens `json:"opens"`
|
||||||
|
Clicks Clicks `json:"clicks"`
|
||||||
|
FacebookLikes FacebookLikes `json:"facebook_likes"`
|
||||||
|
IndustryStats IndustryStats `json:"industry_stats"`
|
||||||
|
ListStats ListStats `json:"list_stats"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bounces struct {
|
||||||
|
HardBounces int `json:"hard_bounces"`
|
||||||
|
SoftBounces int `json:"soft_bounces"`
|
||||||
|
SyntaxErrors int `json:"syntax_errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Forwards struct {
|
||||||
|
ForwardsCount int `json:"forwards_count"`
|
||||||
|
ForwardsOpens int `json:"forwards_opens"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opens struct {
|
||||||
|
OpensTotal int `json:"opens_total"`
|
||||||
|
UniqueOpens int `json:"unique_opens"`
|
||||||
|
OpenRate float64 `json:"open_rate"`
|
||||||
|
LastOpen string `json:"last_open"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Clicks struct {
|
||||||
|
ClicksTotal int `json:"clicks_total"`
|
||||||
|
UniqueClicks int `json:"unique_clicks"`
|
||||||
|
UniqueSubscriberClicks int `json:"unique_subscriber_clicks"`
|
||||||
|
ClickRate float64 `json:"click_rate"`
|
||||||
|
LastClick string `json:"last_click"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FacebookLikes struct {
|
||||||
|
RecipientLikes int `json:"recipient_likes"`
|
||||||
|
UniqueLikes int `json:"unique_likes"`
|
||||||
|
FacebookLikes int `json:"facebook_likes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IndustryStats struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
OpenRate float64 `json:"open_rate"`
|
||||||
|
ClickRate float64 `json:"click_rate"`
|
||||||
|
BounceRate float64 `json:"bounce_rate"`
|
||||||
|
UnopenRate float64 `json:"unopen_rate"`
|
||||||
|
UnsubRate float64 `json:"unsub_rate"`
|
||||||
|
AbuseRate float64 `json:"abuse_rate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListStats struct {
|
||||||
|
SubRate float64 `json:"sub_rate"`
|
||||||
|
UnsubRate float64 `json:"unsub_rate"`
|
||||||
|
OpenRate float64 `json:"open_rate"`
|
||||||
|
ClickRate float64 `json:"click_rate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimeSerie struct {
|
||||||
|
TimeStamp string `json:"timestamp"`
|
||||||
|
EmailsSent int `json:"emails_sent"`
|
||||||
|
UniqueOpens int `json:"unique_opens"`
|
||||||
|
RecipientsClick int `json:"recipients_click"`
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
package mailchimp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdb/telegraf/plugins"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MailChimp struct {
|
||||||
|
api *ChimpAPI
|
||||||
|
|
||||||
|
ApiKey string
|
||||||
|
DaysOld int
|
||||||
|
CampaignId string
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
# MailChimp API key
|
||||||
|
# get from https://admin.mailchimp.com/account/api/
|
||||||
|
api_key = "" # required
|
||||||
|
# Reports for campaigns sent more than days_old ago will not be collected.
|
||||||
|
# 0 means collect all.
|
||||||
|
days_old = 0
|
||||||
|
# Campaign ID to get, if empty gets all campaigns, this option overrides days_old
|
||||||
|
# campaign_id = ""
|
||||||
|
`
|
||||||
|
|
||||||
|
func (m *MailChimp) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MailChimp) Description() string {
|
||||||
|
return "Gathers metrics from the /3.0/reports MailChimp API"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MailChimp) Gather(acc plugins.Accumulator) error {
|
||||||
|
if m.api == nil {
|
||||||
|
m.api = NewChimpAPI(m.ApiKey)
|
||||||
|
}
|
||||||
|
m.api.Debug = false
|
||||||
|
|
||||||
|
if m.CampaignId == "" {
|
||||||
|
since := ""
|
||||||
|
if m.DaysOld > 0 {
|
||||||
|
now := time.Now()
|
||||||
|
d, _ := time.ParseDuration(fmt.Sprintf("%dh", 24*m.DaysOld))
|
||||||
|
since = now.Add(-d).Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
reports, err := m.api.GetReports(ReportsParams{
|
||||||
|
SinceSendTime: since,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
for _, report := range reports.Reports {
|
||||||
|
gatherReport(acc, report, now)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
report, err := m.api.GetReport(m.CampaignId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
now := time.Now()
|
||||||
|
gatherReport(acc, report, now)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gatherReport(acc plugins.Accumulator, report Report, now time.Time) {
|
||||||
|
tags := make(map[string]string)
|
||||||
|
tags["id"] = report.ID
|
||||||
|
tags["campaign_title"] = report.CampaignTitle
|
||||||
|
acc.Add("emails_sent", report.EmailsSent, tags, now)
|
||||||
|
acc.Add("abuse_reports", report.AbuseReports, tags, now)
|
||||||
|
acc.Add("unsubscribed", report.Unsubscribed, tags, now)
|
||||||
|
acc.Add("hard_bounces", report.Bounces.HardBounces, tags, now)
|
||||||
|
acc.Add("soft_bounces", report.Bounces.SoftBounces, tags, now)
|
||||||
|
acc.Add("syntax_errors", report.Bounces.SyntaxErrors, tags, now)
|
||||||
|
acc.Add("forwards_count", report.Forwards.ForwardsCount, tags, now)
|
||||||
|
acc.Add("forwards_opens", report.Forwards.ForwardsOpens, tags, now)
|
||||||
|
acc.Add("opens_total", report.Opens.OpensTotal, tags, now)
|
||||||
|
acc.Add("unique_opens", report.Opens.UniqueOpens, tags, now)
|
||||||
|
acc.Add("open_rate", report.Opens.OpenRate, tags, now)
|
||||||
|
acc.Add("clicks_total", report.Clicks.ClicksTotal, tags, now)
|
||||||
|
acc.Add("unique_clicks", report.Clicks.UniqueClicks, tags, now)
|
||||||
|
acc.Add("unique_subscriber_clicks", report.Clicks.UniqueSubscriberClicks, tags, now)
|
||||||
|
acc.Add("click_rate", report.Clicks.ClickRate, tags, now)
|
||||||
|
acc.Add("facebook_recipient_likes", report.FacebookLikes.RecipientLikes, tags, now)
|
||||||
|
acc.Add("facebook_unique_likes", report.FacebookLikes.UniqueLikes, tags, now)
|
||||||
|
acc.Add("facebook_likes", report.FacebookLikes.FacebookLikes, tags, now)
|
||||||
|
acc.Add("industry_type", report.IndustryStats.Type, tags, now)
|
||||||
|
acc.Add("industry_open_rate", report.IndustryStats.OpenRate, tags, now)
|
||||||
|
acc.Add("industry_click_rate", report.IndustryStats.ClickRate, tags, now)
|
||||||
|
acc.Add("industry_bounce_rate", report.IndustryStats.BounceRate, tags, now)
|
||||||
|
acc.Add("industry_unopen_rate", report.IndustryStats.UnopenRate, tags, now)
|
||||||
|
acc.Add("industry_unsub_rate", report.IndustryStats.UnsubRate, tags, now)
|
||||||
|
acc.Add("industry_abuse_rate", report.IndustryStats.AbuseRate, tags, now)
|
||||||
|
acc.Add("list_stats_sub_rate", report.ListStats.SubRate, tags, now)
|
||||||
|
acc.Add("list_stats_unsub_rate", report.ListStats.UnsubRate, tags, now)
|
||||||
|
acc.Add("list_stats_open_rate", report.ListStats.OpenRate, tags, now)
|
||||||
|
acc.Add("list_stats_click_rate", report.ListStats.ClickRate, tags, now)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugins.Add("mailchimp", func() plugins.Plugin {
|
||||||
|
return &MailChimp{}
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,832 @@
|
||||||
|
package mailchimp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdb/telegraf/testutil"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMailChimpGatherReports(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(
|
||||||
|
http.HandlerFunc(
|
||||||
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintln(w, sampleReports)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
u, err := url.ParseRequestURI(ts.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
api := &ChimpAPI{
|
||||||
|
url: u,
|
||||||
|
Debug: true,
|
||||||
|
}
|
||||||
|
m := MailChimp{
|
||||||
|
api: api,
|
||||||
|
}
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
err = m.Gather(&acc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tags := make(map[string]string)
|
||||||
|
tags["id"] = "42694e9e57"
|
||||||
|
tags["campaign_title"] = "Freddie's Jokes Vol. 1"
|
||||||
|
|
||||||
|
testInts := []struct {
|
||||||
|
measurement string
|
||||||
|
value int
|
||||||
|
}{
|
||||||
|
{"emails_sent", 200},
|
||||||
|
{"abuse_reports", 0},
|
||||||
|
{"unsubscribed", 2},
|
||||||
|
{"hard_bounces", 0},
|
||||||
|
{"soft_bounces", 2},
|
||||||
|
{"syntax_errors", 0},
|
||||||
|
{"forwards_count", 0},
|
||||||
|
{"forwards_opens", 0},
|
||||||
|
{"opens_total", 186},
|
||||||
|
{"unique_opens", 100},
|
||||||
|
{"clicks_total", 42},
|
||||||
|
{"unique_clicks", 400},
|
||||||
|
{"unique_subscriber_clicks", 42},
|
||||||
|
{"facebook_recipient_likes", 5},
|
||||||
|
{"facebook_unique_likes", 8},
|
||||||
|
{"facebook_likes", 42},
|
||||||
|
}
|
||||||
|
for _, test := range testInts {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
testFloats := []struct {
|
||||||
|
measurement string
|
||||||
|
value float64
|
||||||
|
}{
|
||||||
|
{"open_rate", 42},
|
||||||
|
{"click_rate", 42},
|
||||||
|
{"industry_open_rate", 0.17076777144396},
|
||||||
|
{"industry_click_rate", 0.027431311866951},
|
||||||
|
{"industry_bounce_rate", 0.0063767751251474},
|
||||||
|
{"industry_unopen_rate", 0.82285545343089},
|
||||||
|
{"industry_unsub_rate", 0.001436957032815},
|
||||||
|
{"industry_abuse_rate", 0.00021111996110887},
|
||||||
|
{"list_stats_sub_rate", 10},
|
||||||
|
{"list_stats_unsub_rate", 20},
|
||||||
|
{"list_stats_open_rate", 42},
|
||||||
|
{"list_stats_click_rate", 42},
|
||||||
|
}
|
||||||
|
for _, test := range testFloats {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
testStrings := []struct {
|
||||||
|
measurement string
|
||||||
|
value string
|
||||||
|
}{
|
||||||
|
{"industry_type", "Social Networks and Online Communities"},
|
||||||
|
}
|
||||||
|
for _, test := range testStrings {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMailChimpGatherReport(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(
|
||||||
|
http.HandlerFunc(
|
||||||
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintln(w, sampleReport)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
u, err := url.ParseRequestURI(ts.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
api := &ChimpAPI{
|
||||||
|
url: u,
|
||||||
|
Debug: true,
|
||||||
|
}
|
||||||
|
m := MailChimp{
|
||||||
|
api: api,
|
||||||
|
CampaignId: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
err = m.Gather(&acc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tags := make(map[string]string)
|
||||||
|
tags["id"] = "42694e9e57"
|
||||||
|
tags["campaign_title"] = "Freddie's Jokes Vol. 1"
|
||||||
|
|
||||||
|
testInts := []struct {
|
||||||
|
measurement string
|
||||||
|
value int
|
||||||
|
}{
|
||||||
|
{"emails_sent", 200},
|
||||||
|
{"abuse_reports", 0},
|
||||||
|
{"unsubscribed", 2},
|
||||||
|
{"hard_bounces", 0},
|
||||||
|
{"soft_bounces", 2},
|
||||||
|
{"syntax_errors", 0},
|
||||||
|
{"forwards_count", 0},
|
||||||
|
{"forwards_opens", 0},
|
||||||
|
{"opens_total", 186},
|
||||||
|
{"unique_opens", 100},
|
||||||
|
{"clicks_total", 42},
|
||||||
|
{"unique_clicks", 400},
|
||||||
|
{"unique_subscriber_clicks", 42},
|
||||||
|
{"facebook_recipient_likes", 5},
|
||||||
|
{"facebook_unique_likes", 8},
|
||||||
|
{"facebook_likes", 42},
|
||||||
|
}
|
||||||
|
for _, test := range testInts {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
testFloats := []struct {
|
||||||
|
measurement string
|
||||||
|
value float64
|
||||||
|
}{
|
||||||
|
{"open_rate", 42},
|
||||||
|
{"click_rate", 42},
|
||||||
|
{"industry_open_rate", 0.17076777144396},
|
||||||
|
{"industry_click_rate", 0.027431311866951},
|
||||||
|
{"industry_bounce_rate", 0.0063767751251474},
|
||||||
|
{"industry_unopen_rate", 0.82285545343089},
|
||||||
|
{"industry_unsub_rate", 0.001436957032815},
|
||||||
|
{"industry_abuse_rate", 0.00021111996110887},
|
||||||
|
{"list_stats_sub_rate", 10},
|
||||||
|
{"list_stats_unsub_rate", 20},
|
||||||
|
{"list_stats_open_rate", 42},
|
||||||
|
{"list_stats_click_rate", 42},
|
||||||
|
}
|
||||||
|
for _, test := range testFloats {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
testStrings := []struct {
|
||||||
|
measurement string
|
||||||
|
value string
|
||||||
|
}{
|
||||||
|
{"industry_type", "Social Networks and Online Communities"},
|
||||||
|
}
|
||||||
|
for _, test := range testStrings {
|
||||||
|
assert.True(t, acc.CheckTaggedValue(test.measurement, test.value, tags),
|
||||||
|
fmt.Sprintf("Measurement: %v, value: %v, tags: %v not found",
|
||||||
|
test.measurement, test.value, tags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMailChimpGatherError(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(
|
||||||
|
http.HandlerFunc(
|
||||||
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintln(w, sampleError)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
u, err := url.ParseRequestURI(ts.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
api := &ChimpAPI{
|
||||||
|
url: u,
|
||||||
|
Debug: true,
|
||||||
|
}
|
||||||
|
m := MailChimp{
|
||||||
|
api: api,
|
||||||
|
CampaignId: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
err = m.Gather(&acc)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleReports = `
|
||||||
|
{
|
||||||
|
"reports": [
|
||||||
|
{
|
||||||
|
"id": "42694e9e57",
|
||||||
|
"campaign_title": "Freddie's Jokes Vol. 1",
|
||||||
|
"type": "regular",
|
||||||
|
"emails_sent": 200,
|
||||||
|
"abuse_reports": 0,
|
||||||
|
"unsubscribed": 2,
|
||||||
|
"send_time": "2015-09-15T19:05:51+00:00",
|
||||||
|
"bounces": {
|
||||||
|
"hard_bounces": 0,
|
||||||
|
"soft_bounces": 2,
|
||||||
|
"syntax_errors": 0
|
||||||
|
},
|
||||||
|
"forwards": {
|
||||||
|
"forwards_count": 0,
|
||||||
|
"forwards_opens": 0
|
||||||
|
},
|
||||||
|
"opens": {
|
||||||
|
"opens_total": 186,
|
||||||
|
"unique_opens": 100,
|
||||||
|
"open_rate": 42,
|
||||||
|
"last_open": "2015-09-15T19:15:47+00:00"
|
||||||
|
},
|
||||||
|
"clicks": {
|
||||||
|
"clicks_total": 42,
|
||||||
|
"unique_clicks": 400,
|
||||||
|
"unique_subscriber_clicks": 42,
|
||||||
|
"click_rate": 42,
|
||||||
|
"last_click": "2015-09-15T19:15:47+00:00"
|
||||||
|
},
|
||||||
|
"facebook_likes": {
|
||||||
|
"recipient_likes": 5,
|
||||||
|
"unique_likes": 8,
|
||||||
|
"facebook_likes": 42
|
||||||
|
},
|
||||||
|
"industry_stats": {
|
||||||
|
"type": "Social Networks and Online Communities",
|
||||||
|
"open_rate": 0.17076777144396,
|
||||||
|
"click_rate": 0.027431311866951,
|
||||||
|
"bounce_rate": 0.0063767751251474,
|
||||||
|
"unopen_rate": 0.82285545343089,
|
||||||
|
"unsub_rate": 0.001436957032815,
|
||||||
|
"abuse_rate": 0.00021111996110887
|
||||||
|
},
|
||||||
|
"list_stats": {
|
||||||
|
"sub_rate": 10,
|
||||||
|
"unsub_rate": 20,
|
||||||
|
"open_rate": 42,
|
||||||
|
"click_rate": 42
|
||||||
|
},
|
||||||
|
"timeseries": [
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T19:00:00+00:00",
|
||||||
|
"emails_sent": 198,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T20:00:00+00:00",
|
||||||
|
"emails_sent": 2,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T21:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T22:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T23:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T00:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T01:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T02:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T03:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T04:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T05:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T06:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T07:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T08:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T09:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T10:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T11:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T12:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T13:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T14:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T15:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T16:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T17:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T18:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"share_report": {
|
||||||
|
"share_url": "http://usX.vip-reports.net/reports/summary?u=xxxx&id=xxxx",
|
||||||
|
"share_password": "freddielikesjokes"
|
||||||
|
},
|
||||||
|
"delivery_status": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"_links": [
|
||||||
|
{
|
||||||
|
"rel": "parent",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Collection.json",
|
||||||
|
"schema": "https://api.mailchimp.com/schema/3.0/CollectionLinks/Reports.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Instance.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "campaign",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/campaigns/42694e9e57",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Campaigns/Instance.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "sub-reports",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/sub-reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Sub/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "abuse-reports",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/abuse-reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Abuse/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "advice",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/advice",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Advice/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "click-details",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/click-details",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/ClickDetails/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "domain-performance",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/domain-performance",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/DomainPerformance/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "eepurl",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/eepurl",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Eepurl/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "email-activity",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/email-activity",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/EmailActivity/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "locations",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/locations",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Locations/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "sent-to",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/sent-to",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/SentTo/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "unsubscribed",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/unsubscribed",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Unsubs/Collection.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_links": [
|
||||||
|
{
|
||||||
|
"rel": "parent",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Root.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Collection.json",
|
||||||
|
"schema": "https://api.mailchimp.com/schema/3.0/CollectionLinks/Reports.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total_items": 1
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var sampleReport = `
|
||||||
|
{
|
||||||
|
"id": "42694e9e57",
|
||||||
|
"campaign_title": "Freddie's Jokes Vol. 1",
|
||||||
|
"type": "regular",
|
||||||
|
"emails_sent": 200,
|
||||||
|
"abuse_reports": 0,
|
||||||
|
"unsubscribed": 2,
|
||||||
|
"send_time": "2015-09-15T19:05:51+00:00",
|
||||||
|
"bounces": {
|
||||||
|
"hard_bounces": 0,
|
||||||
|
"soft_bounces": 2,
|
||||||
|
"syntax_errors": 0
|
||||||
|
},
|
||||||
|
"forwards": {
|
||||||
|
"forwards_count": 0,
|
||||||
|
"forwards_opens": 0
|
||||||
|
},
|
||||||
|
"opens": {
|
||||||
|
"opens_total": 186,
|
||||||
|
"unique_opens": 100,
|
||||||
|
"open_rate": 42,
|
||||||
|
"last_open": "2015-09-15T19:15:47+00:00"
|
||||||
|
},
|
||||||
|
"clicks": {
|
||||||
|
"clicks_total": 42,
|
||||||
|
"unique_clicks": 400,
|
||||||
|
"unique_subscriber_clicks": 42,
|
||||||
|
"click_rate": 42,
|
||||||
|
"last_click": "2015-09-15T19:15:47+00:00"
|
||||||
|
},
|
||||||
|
"facebook_likes": {
|
||||||
|
"recipient_likes": 5,
|
||||||
|
"unique_likes": 8,
|
||||||
|
"facebook_likes": 42
|
||||||
|
},
|
||||||
|
"industry_stats": {
|
||||||
|
"type": "Social Networks and Online Communities",
|
||||||
|
"open_rate": 0.17076777144396,
|
||||||
|
"click_rate": 0.027431311866951,
|
||||||
|
"bounce_rate": 0.0063767751251474,
|
||||||
|
"unopen_rate": 0.82285545343089,
|
||||||
|
"unsub_rate": 0.001436957032815,
|
||||||
|
"abuse_rate": 0.00021111996110887
|
||||||
|
},
|
||||||
|
"list_stats": {
|
||||||
|
"sub_rate": 10,
|
||||||
|
"unsub_rate": 20,
|
||||||
|
"open_rate": 42,
|
||||||
|
"click_rate": 42
|
||||||
|
},
|
||||||
|
"timeseries": [
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T19:00:00+00:00",
|
||||||
|
"emails_sent": 198,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T20:00:00+00:00",
|
||||||
|
"emails_sent": 2,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T21:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T22:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-15T23:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T00:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T01:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T02:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T03:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T04:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T05:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T06:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T07:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T08:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T09:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T10:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T11:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T12:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T13:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T14:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T15:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T16:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T17:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": "2015-09-16T18:00:00+00:00",
|
||||||
|
"emails_sent": 0,
|
||||||
|
"unique_opens": 0,
|
||||||
|
"recipients_clicks": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"share_report": {
|
||||||
|
"share_url": "http://usX.vip-reports.net/reports/summary?u=xxxx&id=xxxx",
|
||||||
|
"share_password": "freddielikesjokes"
|
||||||
|
},
|
||||||
|
"delivery_status": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"_links": [
|
||||||
|
{
|
||||||
|
"rel": "parent",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Collection.json",
|
||||||
|
"schema": "https://api.mailchimp.com/schema/3.0/CollectionLinks/Reports.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Instance.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "campaign",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/campaigns/42694e9e57",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Campaigns/Instance.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "sub-reports",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/sub-reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Sub/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "abuse-reports",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/abuse-reports",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Abuse/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "advice",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/advice",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Advice/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "click-details",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/click-details",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/ClickDetails/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "domain-performance",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/domain-performance",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/DomainPerformance/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "eepurl",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/eepurl",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Eepurl/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "email-activity",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/email-activity",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/EmailActivity/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "locations",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/locations",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Locations/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "sent-to",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/sent-to",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/SentTo/Collection.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rel": "unsubscribed",
|
||||||
|
"href": "https://usX.api.mailchimp.com/3.0/reports/42694e9e57/unsubscribed",
|
||||||
|
"method": "GET",
|
||||||
|
"targetSchema": "https://api.mailchimp.com/schema/3.0/Reports/Unsubs/Collection.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var sampleError = `
|
||||||
|
{
|
||||||
|
"type": "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/",
|
||||||
|
"title": "API Key Invalid",
|
||||||
|
"status": 401,
|
||||||
|
"detail": "Your API key may be invalid, or you've attempted to access the wrong datacenter.",
|
||||||
|
"instance": ""
|
||||||
|
}
|
||||||
|
`
|
Loading…
Reference in New Issue