User Activity

Posit Connect records information about visits to hosted content. Shiny applications and other content types track different details about those visits. This page contains recipes for both kinds of activity data.

In addition to the recipes provided here, an R Markdown dashboard using the instrumentation APIs can be found in the sol-eng/connect-usage GitHub repository.

User activity: Shiny applications

Connect records information about each visit to a Shiny application and the length of that visit.

This recipe uses the GET /v1/instrumentation/shiny/usage endpoint to page through Python and R Shiny application usage. Information is returned in pages following the keyset pagination model.

Note

The keyset pagination recipe explains how to perform multiple, paged requests.

Workflow

  1. Obtain the Connect server URL and API Key from environment variables.
  2. Call the GET /v1/instrumentation/shiny/usage endpoint to get the first page.
  3. Parse the response using httr::content.
  4. Print the current page.
  5. The paging.next response field indicates the URL for the next page. Load, parse, and print each additional page until paging.next is NULL.

Here is an example of the workflow:

library(httr)

connectServer <- Sys.getenv("CONNECT_SERVER")
connectAPIKey <- Sys.getenv("CONNECT_API_KEY")

# Request a page of up to 25 usage records.
resp <- GET(
  paste0(connectServer, "/__api__/v1/instrumentation/shiny/usage?limit=25"),
  add_headers(Authorization = paste("Key", connectAPIKey))
)
payload <- content(resp)
# print the current page results
print(payload$results)

# Continue to page through additional records
# while we have a "next" reference
while(!is.null(payload$paging[["next"]])) {
  resp <- GET(
    payload$paging[["next"]],
    add_headers(Authorization = paste("Key", connectAPIKey))
  )
  payload <- content(resp)
  # print the results on this page
  print(payload$results)
}

User activity: content

Connect records information about each visit for non-Shiny application content.

This recipe uses the GET /v1/instrumentation/content/visits endpoint to page through information about content visits. Information is returned in pages following the keyset pagination model.

Note

The keyset pagination recipe explains how to perform multiple, paged requests.

Workflow

Configure the following environment variables in order to generate an endpoint / page visit usage report using Quarto Markdown (.qmd) for a specified piece of content.

CONNECT_SERVER: the full address of the Connect host, including protocol.

CONNECT_API_KEY: the API key for an administrator or owner of content. The content visits API is not accessible to viewers or collaborators.

TARGET_CONTENT_GUID: the GUID of the content you want to gather metrics on.

---
title: "Content Visits: Path Usage Report"
execute:
  echo: false
---

```{python}
import os
import requests
import pandas as pd

# Grab the Connect server information, API key, and GUID
# of the content we want metrics on from environment variables.
connect_server = os.getenv("CONNECT_SERVER")
connect_api_key = os.getenv("CONNECT_API_KEY")
content_guid = os.getenv("TARGET_CONTENT_GUID")

# Request visit records for the given content GUID
session = requests.Session()
session.headers.update({ "Authorization": f"Key {connect_api_key}" })
response = session.get(
    f"{connect_server}/__api__/v1/instrumentation/content/visits",
    params = {"content_guid":content_guid}
)

# Store all the results and the paging information
json_data = response.json()
nextPage = json_data['paging']['next']
df = pd.DataFrame(json_data['results'])

# Fetch and accumulate each page of results.
while nextPage:
  response = session.get(nextPage)
  json_data = response.json()
  nextPage = json_data['paging']['next']
  results = pd.DataFrame(json_data['results'])
  df = pd.concat([df, results])

# Plot the top ten values
plot = df['path'].head(10).value_counts().plot(kind='barh')
```
---
title: "Content Visits: Path Usage Report" 
---
  
```{r libraries, echo = FALSE, message = FALSE}
library(httr)
library(dplyr)
library(magrittr)
library(ggplot2)
```

```{r, echo = FALSE}
# Grab the Connect server information, API key, and GUID
# of the content we want metrics on from environment variables.
connectServer <- Sys.getenv("CONNECT_SERVER")
if (nchar(connectServer) == 0) {
  stop("Set the CONNECT_SERVER environment variable.")
}
connectAPIKey <- Sys.getenv("CONNECT_API_KEY")
if (nchar(connectAPIKey) == 0) {
  stop("Set the CONNECT_API_KEY environment variable.")
}
contentGuid <- Sys.getenv("TARGET_CONTENT_GUID")
if (nchar(contentGuid) == 0) {
  stop("Set the TARGET_CONTENT_GUID environment variable.")
}

# Request visit records for the given content GUID
resp <- GET(
  paste0(connectServer, "/__api__/v1/instrumentation/content/visits"),
  query = list(content_guid = contentGuid, limit = 25),
  add_headers(Authorization = paste("Key", connectAPIKey))
)

# Store all the results
payload <- content(resp, as = "parsed", simplifyDataFrame = TRUE)
results <- payload$results

# Fetch and accumulate each page of results.
while (!is.null(payload$paging[["next"]])) {
  resp <- GET(
    payload$paging[["next"]],
    add_headers(Authorization = paste("Key", connectAPIKey))
  )
  payload <- content(resp, as = "parsed", simplifyDataFrame = TRUE)
  results <- rbind(results, payload$results)
}

# Grab only the path information from the stored content visits
# results, then group, summarize, and arrange it for plotting!
paths <- results %>%
  select(path) %>%
  na.omit() %>%
  group_by(path) %>%
  summarise(N = n()) %>%
  top_n(10, path) %>%
  arrange(desc(N))

paths %>% ggplot() +
  geom_col(aes(path, N)) +
  coord_flip()
```