# Key Performance Statistics

The `/statcounters` resource is a multifunctional tool that allows you to view stats through various prisms while varying the Source (API Key, Campaign, List or Sender), the Timing (Event-based or Message-based counters' timestamp), or the Timeframe (Lifetime, Day, Hour, 5 Minutes).

## Stats at Campaign, List or APIKey Level

The /statcounters code samples available in the following sections are done at a campaign level, which is indicated by the use of the following filters in the calls:

- `SourceId=$Campaign_ID` : Substitute $CampaignID with the ID of the Campaign you are interested in.
- `CounterSource=Campaign`


If you want to retrieve these key statistics but at a List level, use the $ListID as the value of the `SourceID` filter and enter List as the `CounterSource`. Keep in mind that retrieving list stats can only be done with `CounterTiming=Message&CounterResolution=Lifetime`.

If you need the stats at an API key level, make the request with ApiKey as the `CounterSource` value. Keep in mind that you can only retrieve data for the ApiKey with which you are authenticated.

You can also retrieve stats at a Sender level - simply set `Sender` as the CounterSource value and enter the sender ID as the value of the SourceID filter. Sender statistics can only be retrieved as message-based, so you'll need to set the value of the `CounterTiming` filter to Message.

## Event-based vs Message-based Stats Timing

The /statcounters resource allows you to retrieve information both based on the message sending time (message-based) and on the timing of the event occurrence (event-based).

Message-based stats allow you to easily view the success of your sending by having the delivery rates / contact engagement details linked to the sending time. To retrieve message-based statistics, set the value of the `CounterTiming` query parameter to `Message`.

### Example

cURL
```shell
# View : Retrieve Key Delivery statistics for a Specific Campaign
curl -s \
	-X GET \
	--user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
	https://api.mailjet.com/v3/REST/statcounters?SourceId=$Campaign_ID\&CounterSource=Campaign\&CounterTiming=Message\&CounterResolution=Lifetime
```

PHP
```php
<?php
/*
View : Retrieve Key Delivery statistics for a Specific Campaign
*/
require 'vendor/autoload.php';
use \Mailjet\Resources;
$mj = new \Mailjet\Client(getenv('MJ_APIKEY_PUBLIC'), getenv('MJ_APIKEY_PRIVATE'));
$filters = [
  'SourceId' => '$Campaign_ID',
  'CounterSource' => 'Campaign',
  'CounterTiming' => 'Message',
  'CounterResolution' => 'Lifetime'
];
$response = $mj->get(Resources::$Statcounters, ['filters' => $filters]);
$response->success() && var_dump($response->getData());
?>
```

Node.js
```javascript
/**
 *
 * View : Retrieve Key Delivery statistics for a Specific Campaign
 *
 */
const mailjet = require('node-mailjet').connect(
  process.env.MJ_APIKEY_PUBLIC,
  process.env.MJ_APIKEY_PRIVATE
)
const request = mailjet.get('statcounters').request({
  SourceId: '$Campaign_ID',
  CounterSource: 'Campaign',
  CounterTiming: 'Message',
  CounterResolution: 'Lifetime',
})
request
  .then(result => {
    console.log(result.body)
  })
  .catch(err => {
    console.log(err.statusCode)
  })
```

Ruby
```ruby
# View : Retrieve Key Delivery statistics for a Specific Campaign
require 'mailjet'
Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
end
variable = Mailjet::Statcounters.all(source_id: "$Campaign_ID",
counter_source: "Campaign",
counter_timing: "Message",
counter_resolution: "Lifetime"
)
p variable.attributes['Data']
```

Python
```python
"""
View : Retrieve Key Delivery statistics for a Specific Campaign
"""
from mailjet_rest import Client
import os
api_key = os.environ['MJ_APIKEY_PUBLIC']
api_secret = os.environ['MJ_APIKEY_PRIVATE']
mailjet = Client(auth=(api_key, api_secret))
filters = {
  'SourceId': '$Campaign_ID',
  'CounterSource': 'Campaign',
  'CounterTiming': 'Message',
  'CounterResolution': 'Lifetime'
}
result = mailjet.statcounters.get(filters=filters)
print result.status_code
print result.json()
```

Java
```java
package com.my.project;
import com.mailjet.client.errors.MailjetException;
import com.mailjet.client.errors.MailjetSocketTimeoutException;
import com.mailjet.client.MailjetClient;
import com.mailjet.client.MailjetRequest;
import com.mailjet.client.MailjetResponse;
import com.mailjet.client.resource.Statcounters;
import org.json.JSONArray;
import org.json.JSONObject;
public class MyClass {
    /**
     * View : Retrieve Key Delivery statistics for a Specific Campaign
     */
    public static void main(String[] args) throws MailjetException, MailjetSocketTimeoutException {
      MailjetClient client;
      MailjetRequest request;
      MailjetResponse response;
      client = new MailjetClient(System.getenv("MJ_APIKEY_PUBLIC"), System.getenv("MJ_APIKEY_PRIVATE"));
      request = new MailjetRequest(Statcounters.resource)
                  .filter(Statcounters.SOURCEID, "$Campaign_ID")
                  .filter(Statcounters.COUNTERSOURCE, "Campaign")
                  .filter(Statcounters.COUNTERTIMING, "Message")
                  .filter(Statcounters.COUNTERRESOLUTION, "Lifetime");
      response = client.get(request);
      System.out.println(response.getStatus());
      System.out.println(response.getData());
    }
}
```

Go
```go
/*
View : Retrieve Key Delivery statistics for a Specific Campaign
*/
package main
import (
	"fmt"
	"log"
	"os"
	mailjet "github.com/mailjet/mailjet-apiv3-go"
	"github.com/mailjet/mailjet-apiv3-go/resources"
)
func main () {
	mailjetClient := NewMailjetClient(os.Getenv("MJ_APIKEY_PUBLIC"), os.Getenv("MJ_APIKEY_PRIVATE"))
	var data []resources.Statcounters
	_, _, err := mailjetClient.List("statcounters", &data, Filter("SourceId", "$Campaign_ID"), Filter("CounterSource", "Campaign"), Filter("CounterTiming", "Message"), Filter("CounterResolution", "Lifetime"))
	if err != nil {
	  fmt.Println(err)
	}
	fmt.Printf("Data array: %+v\n", data)
}
```

C#
```csharp
using Mailjet.Client;
using Mailjet.Client.Resources;
using System;
using Newtonsoft.Json.Linq;
namespace Mailjet.ConsoleApplication
{
   class Program
   {
      /// <summary>
      /// View : Retrieve Key Delivery statistics for a Specific Campaign
      /// </summary>
      static void Main(string[] args)
      {
         RunAsync().Wait();
      }
      static async Task RunAsync()
      {
         MailjetClient client = new MailjetClient(Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"), Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"));
         MailjetRequest request = new MailjetRequest
         {
            Resource = Statcounters.Resource,
         }
         .Filter(Statcounters.Sourceid, "$Campaign_ID")
         .Filter(Statcounters.Countersource, "Campaign")
         .Filter(Statcounters.Countertiming, "Message")
         .Filter(Statcounters.Counterresolution, "Lifetime");
         MailjetResponse response = await client.GetAsync(request);
         if (response.IsSuccessStatusCode)
         {
            Console.WriteLine(string.Format("Total: {0}, Count: {1}\n", response.GetTotal(), response.GetCount()));
            Console.WriteLine(response.GetData());
         }
         else
         {
            Console.WriteLine(string.Format("StatusCode: {0}\n", response.StatusCode));
            Console.WriteLine(string.Format("ErrorInfo: {0}\n", response.GetErrorInfo()));
            Console.WriteLine(response.GetData());
            Console.WriteLine(string.Format("ErrorMessage: {0}\n", response.GetErrorMessage()));
         }
      }
   }
}
```

### API Response

```
{
  "Count": 1,
  "Data": [
    {
      "APIKeyID": 123456,
      "EventClickDelay": 322,
      "EventClickedCount": 6,
      "EventOpenDelay": 739,
      "EventOpenedCount": 11,
      "EventSpamCount": 0,
      "EventUnsubscribedCount": 2,
      "EventWorkflowExitedCount": 0,
      "MessageBlockedCount": 12,
      "MessageClickedCount": 3,
      "MessageDeferredCount": 0,
      "MessageHardBouncedCount": 5,
      "MessageOpenedCount": 8,
      "MessageQueuedCount": 0,
      "MessageSentCount": 15,
      "MessageSoftBouncedCount": 0,
      "MessageSpamCount": 0,
      "MessageUnsubscribedCount": 2,
      "MessageWorkFlowExitedCount": 0,
      "SourceID": 654321,
      "Timeslice": "",
      "Total": 32
    }
  ],
  "Total": 1
}
```

Event-based stats allow you to view the spread of events over time after the initial sending, helping you identify when recipients were most active / engaged with your campaigns. To retrieve event-based statistics, set the value of the `CounterTiming` query parameter to `Event`.

### Example

cURL
```shell
# View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
curl -s \
	-X GET \
	--user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
	https://api.mailjet.com/v3/REST/statcounters?SourceId=$Campaign_ID\&CounterSource=Campaign\&CounterTiming=Event\&CounterResolution=Day\&FromTS=123\&ToTS=456
```

PHP
```php
<?php
/*
View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
*/
require 'vendor/autoload.php';
use \Mailjet\Resources;
$mj = new \Mailjet\Client(getenv('MJ_APIKEY_PUBLIC'), getenv('MJ_APIKEY_PRIVATE'));
$filters = [
  'SourceId' => '$Campaign_ID',
  'CounterSource' => 'Campaign',
  'CounterTiming' => 'Event',
  'CounterResolution' => 'Day',
  'FromTS' => '123',
  'ToTS' => '456'
];
$response = $mj->get(Resources::$Statcounters, ['filters' => $filters]);
$response->success() && var_dump($response->getData());
?>
```

Node.js
```javascript
/**
 *
 * View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
 *
 */
const mailjet = require('node-mailjet').connect(
  process.env.MJ_APIKEY_PUBLIC,
  process.env.MJ_APIKEY_PRIVATE
)
const request = mailjet.get('statcounters').request({
  SourceId: '$Campaign_ID',
  CounterSource: 'Campaign',
  CounterTiming: 'Event',
  CounterResolution: 'Day',
  FromTS: 123,
  ToTS: 456,
})
request
  .then(result => {
    console.log(result.body)
  })
  .catch(err => {
    console.log(err.statusCode)
  })
```

Ruby
```ruby
# View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
require 'mailjet'
Mailjet.configure do |config|
  config.api_key = ENV['MJ_APIKEY_PUBLIC']
  config.secret_key = ENV['MJ_APIKEY_PRIVATE']
end
variable = Mailjet::Statcounters.all(source_id: "$Campaign_ID",
counter_source: "Campaign",
counter_timing: "Event",
counter_resolution: "Day",
from_ts: "123",
to_ts: "456"
)
p variable.attributes['Data']
```

Python
```python
"""
View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
"""
from mailjet_rest import Client
import os
api_key = os.environ['MJ_APIKEY_PUBLIC']
api_secret = os.environ['MJ_APIKEY_PRIVATE']
mailjet = Client(auth=(api_key, api_secret))
filters = {
  'SourceId': '$Campaign_ID',
  'CounterSource': 'Campaign',
  'CounterTiming': 'Event',
  'CounterResolution': 'Day',
  'FromTS': '123',
  'ToTS': '456'
}
result = mailjet.statcounters.get(filters=filters)
print result.status_code
print result.json()
```

Java
```java
package com.my.project;
import com.mailjet.client.errors.MailjetException;
import com.mailjet.client.errors.MailjetSocketTimeoutException;
import com.mailjet.client.MailjetClient;
import com.mailjet.client.MailjetRequest;
import com.mailjet.client.MailjetResponse;
import com.mailjet.client.resource.Statcounters;
import org.json.JSONArray;
import org.json.JSONObject;
public class MyClass {
    /**
     * View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
     */
    public static void main(String[] args) throws MailjetException, MailjetSocketTimeoutException {
      MailjetClient client;
      MailjetRequest request;
      MailjetResponse response;
      client = new MailjetClient(System.getenv("MJ_APIKEY_PUBLIC"), System.getenv("MJ_APIKEY_PRIVATE"));
      request = new MailjetRequest(Statcounters.resource)
                  .filter(Statcounters.SOURCEID, "$Campaign_ID")
                  .filter(Statcounters.COUNTERSOURCE, "Campaign")
                  .filter(Statcounters.COUNTERTIMING, "Event")
                  .filter(Statcounters.COUNTERRESOLUTION, "Day")
                  .filter(Statcounters.FROMTS, "123")
                  .filter(Statcounters.TOTS, "456");
      response = client.get(request);
      System.out.println(response.getStatus());
      System.out.println(response.getData());
    }
}
```

Go
```go
/*
View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
*/
package main
import (
	"fmt"
	"log"
	"os"
	mailjet "github.com/mailjet/mailjet-apiv3-go"
	"github.com/mailjet/mailjet-apiv3-go/resources"
)
func main () {
	mailjetClient := NewMailjetClient(os.Getenv("MJ_APIKEY_PUBLIC"), os.Getenv("MJ_APIKEY_PRIVATE"))
	var data []resources.Statcounters
	_, _, err := mailjetClient.List("statcounters", &data, Filter("SourceId", "$Campaign_ID"), Filter("CounterSource", "Campaign"), Filter("CounterTiming", "Event"), Filter("CounterResolution", "Day"), Filter("FromTS", "123"), Filter("ToTS", "456"))
	if err != nil {
	  fmt.Println(err)
	}
	fmt.Printf("Data array: %+v\n", data)
}
```

C#
```csharp
using Mailjet.Client;
using Mailjet.Client.Resources;
using System;
using Newtonsoft.Json.Linq;
namespace Mailjet.ConsoleApplication
{
   class Program
   {
      /// <summary>
      /// View : View campaign evolution statistics, based on daily timeslices and with a defined timeframe
      /// </summary>
      static void Main(string[] args)
      {
         RunAsync().Wait();
      }
      static async Task RunAsync()
      {
         MailjetClient client = new MailjetClient(Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"), Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"));
         MailjetRequest request = new MailjetRequest
         {
            Resource = Statcounters.Resource,
         }
         .Filter(Statcounters.Sourceid, "$Campaign_ID")
         .Filter(Statcounters.Countersource, "Campaign")
         .Filter(Statcounters.Countertiming, "Event")
         .Filter(Statcounters.Counterresolution, "Day")
         .Filter(Statcounters.Fromts, "123")
         .Filter(Statcounters.Tots, "456");
         MailjetResponse response = await client.GetAsync(request);
         if (response.IsSuccessStatusCode)
         {
            Console.WriteLine(string.Format("Total: {0}, Count: {1}\n", response.GetTotal(), response.GetCount()));
            Console.WriteLine(response.GetData());
         }
         else
         {
            Console.WriteLine(string.Format("StatusCode: {0}\n", response.StatusCode));
            Console.WriteLine(string.Format("ErrorInfo: {0}\n", response.GetErrorInfo()));
            Console.WriteLine(response.GetData());
            Console.WriteLine(string.Format("ErrorMessage: {0}\n", response.GetErrorMessage()));
         }
      }
   }
}
```

### API Response

```
{
  "StatCounters": {
    "Count": 2,
    "Data": [
        {
        "APIKeyID": "320046",
        "EventClickDelay": "200",
        "EventClickCount": "3",
        "EventOpenDelay": "20",
        "EventOpenedCount": "4",
        "EventSpamCount": "4",
        "EventUnsubscribedCount": "5",
        "EventWorkflowExitedCount": "5",
        "MessageBlockedCount": "7",
        "MessageClickedCount": "3",
        "MessageDeferredCount": "2",
        "MessageHardBouncedCount": "5",
        "MessageOpenedCount": "5",
        "MessageQueuedCount": "3",
        "MessageSentCount": "2",
        "MessageSoftBouncedCount": "7",
        "MessageSpamCount": "5",
        "MessageUnsubscribedCount": "1",
        "MessageWorkflowExitedCount": "8",
        "SourceID": "123456789",
        "Timeslice": "456",
        "Total": "50000",
        }
        {
        "APIKeyID": "320046",
        "EventClickDelay": "113",
        "EventClickCount": "2",
        "EventOpenDelay": "15",
        "EventOpenedCount": "2",
        "EventSpamCount": "0",
        "EventUnsubscribedCount": "1",
        "EventWorkflowExitedCount": "2",
        "MessageBlockedCount": "3",
        "MessageClickedCount": "1",
        "MessageDeferredCount": "2",
        "MessageHardBouncedCount": "2",
        "MessageOpenedCount": "2",
        "MessageQueuedCount": "3",
        "MessageSentCount": "2",
        "MessageSoftBouncedCount": "7",
        "MessageSpamCount": "5",
        "MessageUnsubscribedCount": "1",
        "MessageWorkflowExitedCount": "8",
        "SourceID": "123456789",
        "Timeslice": "123",
        "Total": "50000",
        }
    ]
  },
        "Total": 2
}
```

#### Example

Example: A campaign is sent on Day1. There are 10 opens on Day2 and another 20 on Day3. If you use `CounterTiming=Message` in the call, the returned result will be for the messages that were opened, thus showing 30 opens on Day1. If you use `CounterTiming=Event`, /statcounters will return the information on the open events, showing 10 opens on Day2 and 20 on Day3.