This page describes REST API request parameters.
GoodMetrics has two REST API request styles:
- Realtime endpoints use the current live window automatically.
- Reporting endpoints use flat query parameters for date ranges, filters, sorting, and pagination.
Realtime requests
Section titled “Realtime requests”Realtime endpoints read from GET /{gmID}/events/realtime/{resource}.
Bearer-token realtime requests use the current live window automatically, so no timestamp query parameter is required.
curl "https://data.goodmetrics.io/{gmID}/events/realtime/pages" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/realtime/pages`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/realtime/pages", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/realtime/pages";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var url = $"https://data.goodmetrics.io/{gmID}/events/realtime/pages";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$url = "https://data.goodmetrics.io/{$gmID}/events/realtime/pages";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/realtime/pages", nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}Reporting requests
Section titled “Reporting requests”Reporting endpoints read from GET /{gmID}/events/{resource}?start={start}&end={end}.
start and end are Unix timestamps. Unix seconds are recommended. The API also accepts millisecond timestamps and normalizes them internally.
curl "https://data.goodmetrics.io/{gmID}/events/audience/countries?start=1771872000&end=1772476799&page=1&limit=10&sort_by=uniqueVisitors&dir=desc" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "page": "1", "limit": "10", "sort_by": "uniqueVisitors", "dir": "desc"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/audience/countries?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "page": "1", "limit": "10", "sort_by": "uniqueVisitors", "dir": "desc"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/audience/countries?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/audience/countries?start=1771872000&end=1772476799&page=1&limit=10&sort_by=uniqueVisitors&dir=desc";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["page"] = "1", ["limit"] = "10", ["sort_by"] = "uniqueVisitors", ["dir"] = "desc"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/audience/countries?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "page" => "1", "limit" => "10", "sort_by" => "uniqueVisitors", "dir" => "desc"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/audience/countries?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("page", "1") params.Set("limit", "10") params.Set("sort_by", "uniqueVisitors") params.Set("dir", "desc")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/audience/countries?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}Date ranges
Section titled “Date ranges”Every reporting request needs a primary date range:
| Parameter | Description |
|---|---|
start | Primary range start timestamp. |
end | Primary range end timestamp. |
Pass a comparison range to receive primary, secondary, and change arrays in supported responses.
| Parameter | Description |
|---|---|
compare_start | Comparison range start timestamp. |
compare_end | Comparison range end timestamp. |
curl "https://data.goodmetrics.io/{gmID}/events/audience/countries?start=1771872000&end=1772476799&compare_start=1771267200&compare_end=1771871999" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "compare_start": "1771267200", "compare_end": "1771871999"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/audience/countries?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "compare_start": "1771267200", "compare_end": "1771871999"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/audience/countries?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/audience/countries?start=1771872000&end=1772476799&compare_start=1771267200&compare_end=1771871999";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["compare_start"] = "1771267200", ["compare_end"] = "1771871999"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/audience/countries?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "compare_start" => "1771267200", "compare_end" => "1771871999"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/audience/countries?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("compare_start", "1771267200") params.Set("compare_end", "1771871999")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/audience/countries?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}Each range must include both start and end values, and each start value must be before its end value.
Filters
Section titled “Filters”Filters are written as {field}_{operator} query parameters. Use comma-separated values for multiple matches.
| Operator suffix | Behavior |
|---|---|
_is | Include exact values. |
_is_not | Exclude exact values. |
_contains | Include values containing text. |
_not_contains | Exclude values containing text. |
Examples include country_is=Canada, country_is=Canada,United States, page_contains=/pricing, page_not_contains=/admin, and event_type_is=signup,upgrade_to_paid.
Supported filter fields:
browser, city, country, device, eventType, eventURL, exitPage, initialLandingPage, initialReferrer, initialUtmSource, initialUtmMedium, initialUtmSourceMedium, isNewVisitor, language, landingPage, operatingSystem, page, referrer, region, utmCampaign, utmContent, utmMedium, utmSource, utmSourceMedium, utmTerm, subdomain.
Use snake-case field names in the URL:
| Field | Query parameter examples |
|---|---|
eventType | event_type_is=signup |
eventURL | event_url_contains=/checkout |
initialLandingPage | initial_landing_page_contains=/docs |
utmSourceMedium | utm_source_medium_is=google / cpc |
Use is_new_visitor=true or is_new_visitor=false for the new-versus-returning visitor filter.
If inclusive and exclusive operators are mixed on the same field, inclusive operators take precedence.
Custom events
Section titled “Custom events”Use the event_type_is filter to select custom events by event name or event ID.
curl "https://data.goodmetrics.io/{gmID}/events/custom/top-events?start=1771872000&end=1772476799&event_type_is=signup%2Cupgrade_to_paid" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "event_type_is": "signup,upgrade_to_paid"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/custom/top-events?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "event_type_is": "signup,upgrade_to_paid"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/custom/top-events?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/custom/top-events?start=1771872000&end=1772476799&event_type_is=signup%2Cupgrade_to_paid";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["event_type_is"] = "signup,upgrade_to_paid"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/custom/top-events?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "event_type_is" => "signup,upgrade_to_paid"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/custom/top-events?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("event_type_is", "signup,upgrade_to_paid")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/custom/top-events?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}When no event type filter is provided, custom-event-aware endpoints use all available events for the site.
Sorting
Section titled “Sorting”Use sort_by and dir, for example sort_by=uniqueVisitors&dir=desc.
Sort fields vary by endpoint. Common fields include sessions, uniqueVisitors, newVisitors, pageViews, eventCompletions, eventValue, eventConversionRate, and total.
dir may be asc or desc.
Pagination and cursors
Section titled “Pagination and cursors”Table endpoints support page-based pagination and cursor reuse.
| Parameter | Description |
|---|---|
page | Page number to fetch. |
limit | Number of rows per page. |
cursor | Cursor returned by an earlier table response. |
curl "https://data.goodmetrics.io/{gmID}/events/audience/countries?start=1771872000&end=1772476799&page=1&limit=10" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "page": "1", "limit": "10"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/audience/countries?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "page": "1", "limit": "10"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/audience/countries?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/audience/countries?start=1771872000&end=1772476799&page=1&limit=10";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["page"] = "1", ["limit"] = "10"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/audience/countries?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "page" => "1", "limit" => "10"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/audience/countries?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("page", "1") params.Set("limit", "10")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/audience/countries?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}The first response returns meta.cursor. Include that value in later requests to fetch additional pages from the same result set.
curl "https://data.goodmetrics.io/{gmID}/events/audience/countries?start=1771872000&end=1772476799&page=2&limit=10&cursor=returned-cursor" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "page": "2", "limit": "10", "cursor": "returned-cursor"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/audience/countries?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "page": "2", "limit": "10", "cursor": "returned-cursor"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/audience/countries?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/audience/countries?start=1771872000&end=1772476799&page=2&limit=10&cursor=returned-cursor";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["page"] = "2", ["limit"] = "10", ["cursor"] = "returned-cursor"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/audience/countries?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "page" => "2", "limit" => "10", "cursor" => "returned-cursor"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/audience/countries?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("page", "2") params.Set("limit", "10") params.Set("cursor", "returned-cursor")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/audience/countries?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}Charts
Section titled “Charts”/charts/overview supports type and interval.
curl "https://data.goodmetrics.io/{gmID}/events/charts/overview?start=1771872000&end=1772476799&type=unique_visitors&interval=day" \ -H "Authorization: Bearer YOUR_API_KEY"const gmID = '{gmID}';const apiKey = 'YOUR_API_KEY';const params = new URLSearchParams({ "start": "1771872000", "end": "1772476799", "type": "unique_visitors", "interval": "day"});
const response = await fetch(`https://data.goodmetrics.io/${gmID}/events/charts/overview?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }});
console.log(await response.json());import jsonimport urllib.parseimport urllib.request
gm_id = "{gmID}"api_key = "YOUR_API_KEY"params = urllib.parse.urlencode({ "start": "1771872000", "end": "1772476799", "type": "unique_visitors", "interval": "day"})
request = urllib.request.Request( f"https://data.goodmetrics.io/{gm_id}/events/charts/overview?{params}", headers={"Authorization": f"Bearer {api_key}"},)
with urllib.request.urlopen(request) as response: print(json.load(response))import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
class GoodMetricsExample { public static void main(String[] args) throws Exception { var gmID = "{gmID}"; var apiKey = "YOUR_API_KEY"; var url = "https://data.goodmetrics.io/" + gmID + "/events/charts/overview?start=1771872000&end=1772476799&type=unique_visitors&interval=day";
var request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer " + apiKey) .GET() .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Net.Http.Headers;
var gmID = "{gmID}";var apiKey = "YOUR_API_KEY";var query = new Dictionary<string, string>{ ["start"] = "1771872000", ["end"] = "1772476799", ["type"] = "unique_visitors", ["interval"] = "day"};var queryString = string.Join("&", query.Select(parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var url = $"https://data.goodmetrics.io/{gmID}/events/charts/overview?{queryString}";
using var client = new HttpClient();using var request = new HttpRequestMessage(HttpMethod.Get, url);request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
using var response = await client.SendAsync(request);Console.WriteLine(await response.Content.ReadAsStringAsync());<?php$gmID = "{gmID}";$apiKey = "YOUR_API_KEY";$params = http_build_query([ "start" => "1771872000", "end" => "1772476799", "type" => "unique_visitors", "interval" => "day"]);
$url = "https://data.goodmetrics.io/{$gmID}/events/charts/overview?{$params}";
$context = stream_context_create([ "http" => [ "method" => "GET", "header" => "Authorization: Bearer {$apiKey}\r\n", ],]);
$response = file_get_contents($url, false, $context);echo $response;package main
import ( "fmt" "io" "net/http" "net/url")
func main() { gmID := "{gmID}" apiKey := "YOUR_API_KEY"
params := url.Values{} params.Set("start", "1771872000") params.Set("end", "1772476799") params.Set("type", "unique_visitors") params.Set("interval", "day")
request, _ := http.NewRequest( "GET", "https://data.goodmetrics.io/"+gmID+"/events/charts/overview?"+params.Encode(), nil, ) request.Header.Set("Authorization", "Bearer "+apiKey)
response, _ := http.DefaultClient.Do(request) defer response.Body.Close()
body, _ := io.ReadAll(response.Body) fmt.Println(string(body))}Supported intervals are hour, day, week, and month.
Session-centric chart types include unique_visitors, page_views, visits, page_views_per_visit, bounce_rate, and avg_visit_duration.
When a request is event-centric because it has a page or subdomain filter, chart types include avg_time_on_page, visits, pageviews, and unique_visitors.
Event conversion cohort
Section titled “Event conversion cohort”Some table and custom-event responses include event conversion rates. Use event_conversion_cohort=visitors to choose the denominator.
Supported values are sessions, visitors, page_views, and sessions_with_page_views. The default is sessions.