| Title: | Access D2L 'Brightspace' Data Sets via the 'BDS' API |
|---|---|
| Description: | Connect to the D2L 'Brightspace' Data Sets ('BDS') API via 'OAuth2', download all available datasets as tidy data frames with proper types, join them using convenience functions that know the foreign key relationships, and analyse student engagement, performance, and retention with ready-made analytics functions. |
| Authors: | Peeyoosh Chandra [aut, cre] |
| Maintainer: | Peeyoosh Chandra <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-05-17 08:46:35 UTC |
| Source: | https://github.com/pcstrategyandopsco/brightspacer |
Constructs a filter list for use with bs_create_ads_job() and
bs_get_ads(). Produces the [{Name, Value}] array format that the
Brightspace dataExport create endpoint expects.
bs_ads_filter( start_date = NULL, end_date = NULL, parent_org_unit_id = NULL, roles = NULL )bs_ads_filter( start_date = NULL, end_date = NULL, parent_org_unit_id = NULL, roles = NULL )
start_date |
Start date (Date, POSIXct, or character in "YYYY-MM-DD" format). Optional. |
end_date |
End date (Date, POSIXct, or character in "YYYY-MM-DD" format). Optional. |
parent_org_unit_id |
Integer org unit ID to filter by. Optional. |
roles |
Integer vector of role IDs to filter by. Optional. |
A list of list(Name = ..., Value = ...) filter objects.
bs_ads_filter(start_date = "2024-01-01", end_date = "2024-12-31") bs_ads_filter(parent_org_unit_id = 6606) bs_ads_filter(roles = c(110, 120))bs_ads_filter(start_date = "2024-01-01", end_date = "2024-12-31") bs_ads_filter(parent_org_unit_id = 6606) bs_ads_filter(roles = c(110, 120))
Check ADS export job status
bs_ads_job_status(job_id)bs_ads_job_status(job_id)
job_id |
Export job ID returned by |
A list with export_job_id, name, status (integer),
status_text (character), and submit_date.
if (bs_has_token()) { status <- bs_ads_job_status("abc-123") status$status_text }if (bs_has_token()) { status <- bs_ads_job_status("abc-123") status$status_text }
Get or set the Brightspace API version
bs_api_version(version = NULL)bs_api_version(version = NULL)
version |
If provided, sets the API version. If |
Character string of the API version.
bs_api_version() bs_api_version("1.49")bs_api_version() bs_api_version("1.49")
Filters or redacts columns based on a YAML-driven field policy. This is the same logic the MCP server uses to strip PII before data reaches the AI model.
bs_apply_field_policy(df, dataset_name, policy = NULL)bs_apply_field_policy(df, dataset_name, policy = NULL)
df |
A data frame (typically from |
dataset_name |
Character string identifying the BDS dataset. |
policy |
A named list representing the field policy (as returned by
|
The policy supports three modes per dataset:
allowOnly the listed fields are kept; all others are dropped.
redactThe listed fields have their values replaced with
"[REDACTED]"; all other fields pass through.
allAll columns pass through unchanged.
If dataset_name is not found in the policy, the data frame is returned
unchanged.
The input data frame with the field policy applied.
df <- data.frame( UserId = 1L, FirstName = "Jane", Organization = "Org1", stringsAsFactors = FALSE ) bs_apply_field_policy(df, "Users")df <- data.frame( UserId = 1L, FirstName = "Jane", Organization = "Org1", stringsAsFactors = FALSE ) bs_apply_field_policy(df, "Users")
Aggregates quiz attempt data into per-user per-quiz performance summaries including best, average, and latest scores.
bs_assessment_performance(quiz_attempts)bs_assessment_performance(quiz_attempts)
quiz_attempts |
A tibble from the Quiz Attempts dataset. |
A summarised tibble with one row per user per quiz per org unit.
if (bs_has_token()) { attempts <- bs_get_dataset("Quiz Attempts") bs_assessment_performance(attempts) }if (bs_has_token()) { attempts <- bs_get_dataset("Quiz Attempts") bs_assessment_performance(attempts) }
Aggregates assignment submission data per assignment per org unit, including grading rates and score statistics.
bs_assignment_completion(assignment_submissions)bs_assignment_completion(assignment_submissions)
assignment_submissions |
A tibble from the Assignment Submissions dataset. |
A summarised tibble with one row per assignment per org unit.
if (bs_has_token()) { submissions <- bs_get_dataset("Assignment Submissions") bs_assignment_completion(submissions) }if (bs_has_token()) { submissions <- bs_get_dataset("Assignment Submissions") bs_assignment_completion(submissions) }
Initiates an OAuth2 Authorization Code flow with PKCE to authenticate with the Brightspace Data Hub API. The resulting token is cached to disk for reuse across sessions and automatically refreshed when expired.
bs_auth( client_id = "", client_secret = "", instance_url = "", redirect_uri = "", scope = "" )bs_auth( client_id = "", client_secret = "", instance_url = "", redirect_uri = "", scope = "" )
client_id |
OAuth2 client ID. Resolved in order: this argument,
|
client_secret |
OAuth2 client secret. Resolved in order: this argument,
|
instance_url |
Your Brightspace instance URL (e.g.,
|
redirect_uri |
The registered redirect URI. Must match the URI
registered in your Brightspace OAuth2 app exactly. Supports both
|
scope |
OAuth2 scope string (space-separated). Resolved from config.yml or defaults to BDS + ADS scopes. |
The first authentication requires an interactive R session (browser-based
login). After that, cached credentials are used automatically — including
in non-interactive scripts run via Rscript.
Invisibly returns TRUE on success.
if (bs_has_token()) { bs_auth() bs_auth( client_id = "my-client-id", client_secret = "my-secret", instance_url = "https://myschool.brightspace.com" ) }if (bs_has_token()) { bs_auth() bs_auth( client_id = "my-client-id", client_secret = "my-secret", instance_url = "https://myschool.brightspace.com" ) }
Authenticates using an existing refresh token, without requiring browser interaction. Ideal for non-interactive scripts and scheduled jobs.
bs_auth_refresh( refresh_token, client_id = Sys.getenv("BRIGHTSPACE_CLIENT_ID"), client_secret = Sys.getenv("BRIGHTSPACE_CLIENT_SECRET"), instance_url = Sys.getenv("BRIGHTSPACE_INSTANCE_URL"), scope = "" )bs_auth_refresh( refresh_token, client_id = Sys.getenv("BRIGHTSPACE_CLIENT_ID"), client_secret = Sys.getenv("BRIGHTSPACE_CLIENT_SECRET"), instance_url = Sys.getenv("BRIGHTSPACE_INSTANCE_URL"), scope = "" )
refresh_token |
The OAuth2 refresh token string. |
client_id |
OAuth2 client ID. Defaults to |
client_secret |
OAuth2 client secret. Defaults to
|
instance_url |
Your Brightspace instance URL. Defaults to
|
scope |
OAuth2 scope. |
Invisibly returns TRUE on success.
if (bs_has_token()) { bs_auth_refresh(refresh_token = "my-refresh-token") }if (bs_has_token()) { bs_auth_refresh(refresh_token = "my-refresh-token") }
Sets authentication credentials without going through the browser-based OAuth2 flow. Useful for non-interactive environments or when you already have a valid token.
bs_auth_token( token, instance_url, client_id = Sys.getenv("BRIGHTSPACE_CLIENT_ID"), client_secret = Sys.getenv("BRIGHTSPACE_CLIENT_SECRET") )bs_auth_token( token, instance_url, client_id = Sys.getenv("BRIGHTSPACE_CLIENT_ID"), client_secret = Sys.getenv("BRIGHTSPACE_CLIENT_SECRET") )
token |
A token list with at least an |
instance_url |
Your Brightspace instance URL. |
client_id |
OAuth2 client ID. |
client_secret |
OAuth2 client secret. |
Invisibly returns TRUE.
Verifies which API capabilities are available with the current token by making lightweight test calls to each endpoint group. Checks are grouped into Tier 1 (BDS) and Tier 2 (ADS) so you can see at a glance which tier is working. Useful for diagnosing 403 errors.
bs_check_scopes()bs_check_scopes()
A tibble with columns tier, scope, endpoint, status
("OK" or error message), printed as a summary table.
if (bs_has_token()) { bs_auth() bs_check_scopes() }if (bs_has_token()) { bs_auth() bs_check_scopes() }
Convert column names from PascalCase to snake_case
bs_clean_names(df)bs_clean_names(df)
df |
A data frame. |
A data frame with snake_case column names.
df <- data.frame(UserId = 1, FirstName = "A") bs_clean_names(df)df <- data.frame(UserId = 1, FirstName = "A") bs_clean_names(df)
Reads Brightspace OAuth2 credentials from a YAML configuration file using
the config package. The function looks for a brightspace key in the
config file and returns the credentials as a named list.
bs_config( file = "config.yml", profile = Sys.getenv("R_CONFIG_ACTIVE", "default") )bs_config( file = "config.yml", profile = Sys.getenv("R_CONFIG_ACTIVE", "default") )
file |
Path to the YAML config file. Defaults to |
profile |
Configuration profile to use. Defaults to the
|
A named list with elements client_id, client_secret,
instance_url, redirect_uri, and scope, or NULL if the file does
not exist or the brightspace key is missing.
if (bs_has_token()) { # Read from default config.yml cfg <- bs_config() cfg$client_id # Read from a custom file and profile cfg <- bs_config(file = "my-config.yml", profile = "production") }if (bs_has_token()) { # Read from default config.yml cfg <- bs_config() cfg$client_id # Read from a custom file and profile cfg <- bs_config(file = "my-config.yml", profile = "production") }
Interactively creates or updates a config.yml file with Brightspace
OAuth2 credentials. If the file already exists, the brightspace section
is updated while preserving other settings.
bs_config_set( client_id, client_secret, instance_url, redirect_uri = "https://localhost:1410/", scope = paste("datasets:bds:read", "datahub:dataexports:read", "datahub:dataexports:download", "reporting:dataset:list", "reporting:dataset:fetch", "reporting:job:create", "reporting:job:list", "reporting:job:fetch", "reporting:job:download", "users:profile:read"), file = "config.yml", profile = "default" )bs_config_set( client_id, client_secret, instance_url, redirect_uri = "https://localhost:1410/", scope = paste("datasets:bds:read", "datahub:dataexports:read", "datahub:dataexports:download", "reporting:dataset:list", "reporting:dataset:fetch", "reporting:job:create", "reporting:job:list", "reporting:job:fetch", "reporting:job:download", "users:profile:read"), file = "config.yml", profile = "default" )
client_id |
OAuth2 client ID. |
client_secret |
OAuth2 client secret. |
instance_url |
Your Brightspace instance URL (e.g.,
|
redirect_uri |
Redirect URI. Defaults to |
scope |
OAuth2 scope string (space-separated). Defaults to the full
BDS + ADS scope set used by |
file |
Path for the config file. Defaults to |
profile |
Configuration profile to write to. Defaults to |
Invisibly returns the file path.
if (bs_has_token()) { bs_config_set( client_id = "my-client-id", client_secret = "my-secret", instance_url = "https://myschool.brightspace.com" ) }if (bs_has_token()) { bs_config_set( client_id = "my-client-id", client_secret = "my-secret", instance_url = "https://myschool.brightspace.com" ) }
Computes engagement metrics from Learner Usage ADS data including progress
percentage, days since last visit, and passes through all raw activity counts.
No composite score is computed here — use bs_engagement_score() to add one.
bs_course_engagement(learner_usage, tz = NULL)bs_course_engagement(learner_usage, tz = NULL)
learner_usage |
A tibble from the Learner Usage ADS. |
tz |
Timezone for date conversion. Defaults to |
A tibble with all learner_usage identity columns plus computed
metrics: progress_pct, days_since_visit.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") engagement <- bs_course_engagement(usage) }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") engagement <- bs_course_engagement(usage) }
Creates a per-course dashboard view with engagement, progress, and optionally
award-based completion metrics. completion_rate_progress uses content
progress (available from Learner Usage alone); completion_rate_awards uses
certificate issuance (more authoritative but requires Awards Issued dataset).
bs_course_summary(learner_usage, awards = NULL)bs_course_summary(learner_usage, awards = NULL)
learner_usage |
A tibble from the Learner Usage ADS. |
awards |
Optional tibble from the Awards Issued ADS. When provided, adds award-based completion rate. |
A summarised tibble with one row per course, sorted by n_learners
descending.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_course_summary(usage) awards <- bs_get_ads("Awards Issued") bs_course_summary(usage, awards = awards) }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_course_summary(usage) awards <- bs_get_ads("Awards Issued") bs_course_summary(usage, awards = awards) }
Submits a new export job for the named ADS dataset. Use
bs_ads_job_status() to poll for completion, then
bs_download_ads() to retrieve the result.
bs_create_ads_job(name, filters = list())bs_create_ads_job(name, filters = list())
name |
Dataset name (case-insensitive). For example,
|
filters |
Optional filter list from |
A tibble with one row containing export_job_id, dataset_id,
name, status, status_text, submit_date.
if (bs_has_token()) { job <- bs_create_ads_job("Learner Usage") job$export_job_id }if (bs_has_token()) { job <- bs_create_ads_job("Learner Usage") job$export_job_id }
Removes cached credentials from the current session and optionally from disk.
bs_deauth(clear_cache = TRUE)bs_deauth(clear_cache = TRUE)
clear_cache |
If |
Invisibly returns TRUE.
if (bs_has_token()) { bs_deauth() }if (bs_has_token()) { bs_deauth() }
Returns a tibble showing each extract (full + diffs + merged total) with its creation date, row count, and download status. Use this to verify that all differential extracts were successfully downloaded and merged.
bs_diff_manifest(data)bs_diff_manifest(data)
data |
A tibble returned by |
A tibble with columns extract, created_date, rows, status,
or NULL if the data has no manifest attribute.
if (bs_has_token()) { users <- bs_get_dataset_current("Users") bs_diff_manifest(users) }if (bs_has_token()) { users <- bs_get_dataset_current("Users") bs_diff_manifest(users) }
Downloads the result of a completed ADS export job, unzips it, and returns a tidy tibble with proper types and snake_case names.
bs_download_ads(job_id, dataset_name = NULL)bs_download_ads(job_id, dataset_name = NULL)
job_id |
Export job ID. |
dataset_name |
Optional dataset name (used for schema lookup). |
A tibble of the dataset contents.
if (bs_has_token()) { result <- bs_download_ads("abc-123", "Learner Usage") }if (bs_has_token()) { result <- bs_download_ads("abc-123", "Learner Usage") }
Downloads all available datasets and returns them as a named list of tibbles. Names are snake_case versions of the dataset names.
bs_download_all(extract_type = c("full", "diff"))bs_download_all(extract_type = c("full", "diff"))
extract_type |
Type of extract: |
A named list of tibbles.
if (bs_has_token()) { all_data <- bs_download_all() all_data$users all_data$org_units }if (bs_has_token()) { all_data <- bs_download_all() all_data$users all_data$org_units }
Downloads a specific dataset extract as a ZIP file, unzips it, reads the CSV, and returns a tidy tibble with proper types.
bs_download_dataset( schema_id, plugin_id, extract_type = c("full", "diff"), extract_id = NULL, dataset_name = NULL )bs_download_dataset( schema_id, plugin_id, extract_type = c("full", "diff"), extract_id = NULL, dataset_name = NULL )
schema_id |
Schema ID of the dataset. |
plugin_id |
Plugin ID of the dataset. |
extract_type |
Type of extract: |
extract_id |
Specific extract ID. If |
dataset_name |
Optional name of the dataset (used for schema lookup). |
A tibble of the dataset contents.
if (bs_has_token()) { datasets <- bs_list_datasets() users <- bs_download_dataset( datasets$schema_id[1], datasets$plugin_id[1] ) }if (bs_has_token()) { datasets <- bs_list_datasets() users <- bs_download_dataset( datasets$schema_id[1], datasets$plugin_id[1] ) }
Adds a weighted composite engagement_score column to any tibble that has
raw activity count columns. Default weights reflect relative effort/depth
(login is passive, assignment is active). Users should override for their
context.
bs_engagement_score(df, weights = list())bs_engagement_score(df, weights = list())
df |
A tibble with activity count columns. |
weights |
A named list of column-weight pairs to override defaults.
Defaults: |
The input tibble with an engagement_score column appended.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") scored <- bs_engagement_score(usage) scored <- bs_engagement_score(usage, weights = list(login_count = 2)) }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") scored <- bs_engagement_score(usage) scored <- bs_engagement_score(usage, weights = list(login_count = 2)) }
Aggregates engagement metrics from Learner Usage data by course, department, or user.
bs_engagement_summary(learner_usage, by = c("course", "department", "user"))bs_engagement_summary(learner_usage, by = c("course", "department", "user"))
learner_usage |
A tibble from the Learner Usage ADS. |
by |
Grouping dimension: |
A summarised tibble sorted by mean_progress descending (or
last_activity for user grouping).
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_engagement_summary(usage, by = "course") bs_engagement_summary(usage, by = "department") bs_engagement_summary(usage, by = "user") }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_engagement_summary(usage, by = "course") bs_engagement_summary(usage, by = "department") bs_engagement_summary(usage, by = "user") }
Builds the enriched enrollment table by joining enrollments with org units and users, adding analysis-friendly column aliases. Original column names are preserved for compatibility; friendly aliases are added for readability.
bs_enrich_enrollments( enrollments, org_units, users, course_type = "Course Offering" )bs_enrich_enrollments( enrollments, org_units, users, course_type = "Course Offering" )
enrollments |
A tibble from the Enrollments and Withdrawals dataset. |
org_units |
A tibble from the Org Units dataset. |
users |
A tibble from the Users dataset. |
course_type |
Org unit type to filter to (default |
A tibble with both original and friendly column names, filtered to the specified course type.
if (bs_has_token()) { enroll <- bs_get_dataset("Enrollments and Withdrawals") org_units <- bs_get_dataset("Org Units") users <- bs_get_dataset("Users") enriched <- bs_enrich_enrollments(enroll, org_units, users) }if (bs_has_token()) { enroll <- bs_get_dataset("Enrollments and Withdrawals") org_units <- bs_get_dataset("Org Units") users <- bs_get_dataset("Users") enriched <- bs_enrich_enrollments(enroll, org_units, users) }
Removes test/system accounts using a two-layer filter: ID string length and an optional exclusion list. This eliminates the repeated boilerplate of removing test users before analysis.
bs_filter_test_users( df, min_id_length = 30, exclusion_list = NULL, id_col = "org_defined_id" )bs_filter_test_users( df, min_id_length = 30, exclusion_list = NULL, id_col = "org_defined_id" )
df |
A tibble containing user data. |
min_id_length |
Minimum character length of a real user ID (default 30). IDs shorter than this are assumed to be test accounts. |
exclusion_list |
Optional character vector of specific IDs to exclude. |
id_col |
Name of the column containing user IDs (default
|
A filtered tibble with test users removed.
if (bs_has_token()) { users <- bs_get_dataset("Users") real_users <- bs_filter_test_users(users) real_users <- bs_filter_test_users(users, exclusion_list = c("testuser01")) }if (bs_has_token()) { users <- bs_get_dataset("Users") real_users <- bs_filter_test_users(users) real_users <- bs_filter_test_users(users, exclusion_list = c("testuser01")) }
High-level function that finds the dataset by name, creates an export job, polls until complete, downloads the result, and returns a tidy tibble. Intended for interactive use.
bs_get_ads(name, filters = list(), poll_interval = 5, timeout = 300)bs_get_ads(name, filters = list(), poll_interval = 5, timeout = 300)
name |
Dataset name (case-insensitive). For example,
|
filters |
Optional filter list from |
poll_interval |
Seconds between status checks. Default 5. |
timeout |
Maximum seconds to wait for completion. Default 300. |
A tibble of the dataset contents.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") usage <- bs_get_ads("Learner Usage", filters = bs_ads_filter(start_date = "2024-01-01")) }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") usage <- bs_get_ads("Learner Usage", filters = bs_ads_filter(start_date = "2024-01-01")) }
Get the schema for an ADS dataset
bs_get_ads_schema(dataset_name)bs_get_ads_schema(dataset_name)
dataset_name |
Name of the dataset (will be normalized to snake_case). |
A schema list, or NULL if no schema is registered.
bs_get_ads_schema("Learner Usage")bs_get_ads_schema("Learner Usage")
Convenience wrapper that finds a dataset by name, downloads the latest full extract, and returns a tidy tibble.
bs_get_dataset(name, extract_type = c("full", "diff"))bs_get_dataset(name, extract_type = c("full", "diff"))
name |
Dataset name (case-insensitive partial match). For example,
|
extract_type |
Type of extract: |
A tibble of the dataset contents.
if (bs_has_token()) { users <- bs_get_dataset("Users") grades <- bs_get_dataset("Grade Results") }if (bs_has_token()) { users <- bs_get_dataset("Users") grades <- bs_get_dataset("Grade Results") }
Downloads the latest full extract and all subsequent differential extracts for a dataset, then merges them to produce a current-as-of-today tibble.
bs_get_dataset_current(name, keep_deleted = FALSE)bs_get_dataset_current(name, keep_deleted = FALSE)
name |
Dataset name (case-insensitive partial match). For example,
|
keep_deleted |
If |
A tibble of the merged dataset contents. The tibble carries a
"bds_manifest" attribute with the extract breakdown (full, each diff,
and merged total with row counts and download status). Retrieve it with
bs_diff_manifest().
if (bs_has_token()) { users <- bs_get_dataset_current("Users") bs_diff_manifest(users) }if (bs_has_token()) { users <- bs_get_dataset_current("Users") bs_diff_manifest(users) }
Get the schema for a dataset
bs_get_schema(dataset_name)bs_get_schema(dataset_name)
dataset_name |
Name of the dataset (will be normalized to snake_case). |
A schema list, or NULL if no schema is registered.
bs_get_schema("Users") bs_get_schema("Grade Results")bs_get_schema("Users") bs_get_schema("Grade Results")
Returns the timezone set by bs_set_timezone(), defaulting to "UTC".
bs_get_timezone()bs_get_timezone()
Character string of the timezone.
bs_get_timezone()bs_get_timezone()
Joins grade results with grade object definitions and calculates grade percentages.
bs_grade_summary(grade_results, grade_objects)bs_grade_summary(grade_results, grade_objects)
grade_results |
A tibble from the Grade Results dataset. |
grade_objects |
A tibble from the Grade Objects dataset. |
A joined tibble with grade object name, type, max points, and
calculated grade_pct and grade_label.
if (bs_has_token()) { grades <- bs_get_dataset("Grade Results") objects <- bs_get_dataset("Grade Objects") bs_grade_summary(grades, objects) }if (bs_has_token()) { grades <- bs_get_dataset("Grade Results") objects <- bs_get_dataset("Grade Objects") bs_grade_summary(grades, objects) }
Check if authenticated with Brightspace
bs_has_token()bs_has_token()
Logical; TRUE if a token is available.
bs_has_token()bs_has_token()
Flags at-risk students from Learner Usage data based on configurable thresholds. Adds boolean risk flags and a composite risk score.
bs_identify_at_risk(learner_usage, thresholds = list())bs_identify_at_risk(learner_usage, thresholds = list())
learner_usage |
A tibble from the Learner Usage ADS. |
thresholds |
A named list of thresholds to override defaults. Available
thresholds: |
A tibble with all original columns plus risk flags (never_accessed,
low_progress, inactive, low_logins), risk_score (0-4), and
risk_level (ordered factor: Low, Medium, High, Critical), sorted by
risk_score descending.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") at_risk <- bs_identify_at_risk(usage) at_risk <- bs_identify_at_risk(usage, thresholds = list(progress = 30)) }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") at_risk <- bs_identify_at_risk(usage) at_risk <- bs_identify_at_risk(usage, thresholds = list(progress = 30)) }
Automatically detects shared key columns between two tibbles based on the schema registry and performs a join. Falls back to joining on common column names if schemas are not available.
bs_join(df1, df2, type = c("left", "inner", "right", "full"))bs_join(df1, df2, type = c("left", "inner", "right", "full"))
df1 |
First tibble. |
df2 |
Second tibble. |
type |
Join type: |
A joined tibble.
if (bs_has_token()) { users <- bs_get_dataset("Users") enrollments <- bs_get_dataset("User Enrollments") bs_join(users, enrollments) }if (bs_has_token()) { users <- bs_get_dataset("Users") enrollments <- bs_get_dataset("User Enrollments") bs_join(users, enrollments) }
Left joins a content objects tibble with a content user progress tibble
on content_object_id and org_unit_id.
bs_join_content_progress(content_objects, content_progress)bs_join_content_progress(content_objects, content_progress)
content_objects |
A tibble from the Content Objects dataset. |
content_progress |
A tibble from the Content User Progress dataset. |
A joined tibble.
if (bs_has_token()) { content <- bs_get_dataset("Content Objects") progress <- bs_get_dataset("Content User Progress") bs_join_content_progress(content, progress) }if (bs_has_token()) { content <- bs_get_dataset("Content Objects") progress <- bs_get_dataset("Content User Progress") bs_join_content_progress(content, progress) }
Left joins an enrollments tibble with a grade results tibble on
org_unit_id and user_id.
bs_join_enrollments_grades(enrollments, grade_results)bs_join_enrollments_grades(enrollments, grade_results)
enrollments |
A tibble from the User Enrollments dataset. |
grade_results |
A tibble from the Grade Results dataset. |
A joined tibble.
if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") grades <- bs_get_dataset("Grade Results") bs_join_enrollments_grades(enrollments, grades) }if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") grades <- bs_get_dataset("Grade Results") bs_join_enrollments_grades(enrollments, grades) }
Left joins an enrollments tibble with an org units tibble on org_unit_id.
bs_join_enrollments_orgunits(enrollments, org_units)bs_join_enrollments_orgunits(enrollments, org_units)
enrollments |
A tibble from the User Enrollments dataset. |
org_units |
A tibble from the Org Units dataset. |
A joined tibble.
if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") org_units <- bs_get_dataset("Org Units") bs_join_enrollments_orgunits(enrollments, org_units) }if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") org_units <- bs_get_dataset("Org Units") bs_join_enrollments_orgunits(enrollments, org_units) }
Left joins an enrollments tibble with a role details tibble on role_id.
bs_join_enrollments_roles(enrollments, role_details)bs_join_enrollments_roles(enrollments, role_details)
enrollments |
A tibble from the User Enrollments dataset. |
role_details |
A tibble from the Role Details dataset. |
A joined tibble.
if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") roles <- bs_get_dataset("Role Details") bs_join_enrollments_roles(enrollments, roles) }if (bs_has_token()) { enrollments <- bs_get_dataset("User Enrollments") roles <- bs_get_dataset("Role Details") bs_join_enrollments_roles(enrollments, roles) }
Left joins a grade results tibble with a grade objects tibble on
grade_object_id and org_unit_id.
bs_join_grades_objects(grade_results, grade_objects)bs_join_grades_objects(grade_results, grade_objects)
grade_results |
A tibble from the Grade Results dataset. |
grade_objects |
A tibble from the Grade Objects dataset. |
A joined tibble.
if (bs_has_token()) { grades <- bs_get_dataset("Grade Results") objects <- bs_get_dataset("Grade Objects") bs_join_grades_objects(grades, objects) }if (bs_has_token()) { grades <- bs_get_dataset("Grade Results") objects <- bs_get_dataset("Grade Objects") bs_join_grades_objects(grades, objects) }
Left joins a users tibble with an enrollments tibble on user_id.
bs_join_users_enrollments(users, enrollments)bs_join_users_enrollments(users, enrollments)
users |
A tibble from the Users dataset. |
enrollments |
A tibble from the User Enrollments dataset. |
A joined tibble.
if (bs_has_token()) { users <- bs_get_dataset("Users") enrollments <- bs_get_dataset("User Enrollments") bs_join_users_enrollments(users, enrollments) }if (bs_has_token()) { users <- bs_get_dataset("Users") enrollments <- bs_get_dataset("User Enrollments") bs_join_users_enrollments(users, enrollments) }
Retrieves all available ADS datasets from the Brightspace instance.
bs_list_ads()bs_list_ads()
A tibble with columns: dataset_id, name, description,
category.
if (bs_has_token()) { ads <- bs_list_ads() ads }if (bs_has_token()) { ads <- bs_list_ads() ads }
List all submitted ADS export jobs
bs_list_ads_jobs()bs_list_ads_jobs()
A tibble of all submitted export jobs with columns:
export_job_id, name, dataset_id, status, status_text,
submit_date.
if (bs_has_token()) { bs_list_ads_jobs() }if (bs_has_token()) { bs_list_ads_jobs() }
List all registered ADS dataset schemas
bs_list_ads_schemas()bs_list_ads_schemas()
A character vector of registered dataset names (snake_case).
bs_list_ads_schemas()bs_list_ads_schemas()
Retrieves all available BDS datasets from the Brightspace instance.
bs_list_datasets()bs_list_datasets()
A tibble with columns: schema_id, plugin_id, name,
description, full_download_link, diff_download_link,
created_date.
if (bs_has_token()) { datasets <- bs_list_datasets() datasets }if (bs_has_token()) { datasets <- bs_list_datasets() datasets }
Retrieves available full and differential extracts for a specific dataset.
bs_list_extracts(schema_id, plugin_id)bs_list_extracts(schema_id, plugin_id)
schema_id |
Schema ID of the dataset. |
plugin_id |
Plugin ID of the dataset. |
A tibble with columns: extract_id, extract_type, bds_type,
created_date, download_link, download_size.
if (bs_has_token()) { datasets <- bs_list_datasets() extracts <- bs_list_extracts(datasets$schema_id[1], datasets$plugin_id[1]) }if (bs_has_token()) { datasets <- bs_list_datasets() extracts <- bs_list_extracts(datasets$schema_id[1], datasets$plugin_id[1]) }
List all registered dataset schemas
bs_list_schemas()bs_list_schemas()
A character vector of registered dataset names (snake_case).
bs_list_schemas()bs_list_schemas()
Calls /d2l/api/lp/(version)/organization/info and returns the org
identifier.
bs_org_id()bs_org_id()
Character string of the root org unit ID.
if (bs_has_token()) { bs_org_id() }if (bs_has_token()) { bs_org_id() }
Applies bs_pseudonymise_id() to the person-referencing columns for a
known Brightspace Data Set. Structural IDs (OrgUnitId, GradeObjectId, etc.)
are left untouched.
bs_pseudonymise_df(df, dataset_name, key, columns = NULL)bs_pseudonymise_df(df, dataset_name, key, columns = NULL)
df |
A data frame (typically from |
dataset_name |
Character string identifying the BDS dataset (e.g.
|
key |
A raw vector used as the HMAC key (passed to
|
columns |
Character vector of column names to pseudonymise. If |
The input data frame with person-referencing columns replaced by pseudonyms.
key <- openssl::rand_bytes(32) df <- data.frame(UserId = c(1L, 2L), OrgUnitId = c(10L, 20L)) bs_pseudonymise_df(df, "Users", key = key)key <- openssl::rand_bytes(32) df <- data.frame(UserId = c(1L, 2L), OrgUnitId = c(10L, 20L)) bs_pseudonymise_df(df, "Users", key = key)
Replaces each value with an HMAC-SHA256 pseudonym of the form usr_a3f2b1c8.
The same value + key always produces the same pseudonym, so joins and
grouping work correctly within a session.
bs_pseudonymise_id(values, key)bs_pseudonymise_id(values, key)
values |
A vector of IDs (integer, numeric, or character). |
key |
A raw vector used as the HMAC key. Generate one per session with
|
A character vector the same length as values, with non-NA
entries replaced by usr_ plus 8 hex characters.
key <- openssl::rand_bytes(32) bs_pseudonymise_id(c(1, 2, NA, 3), key = key)key <- openssl::rand_bytes(32) bs_pseudonymise_id(c(1, 2, NA, 3), key = key)
Calculates retention metrics by course or department, including start rates, completion rates, and dropout rates.
bs_retention_summary(learner_usage, by = c("course", "department"))bs_retention_summary(learner_usage, by = c("course", "department"))
learner_usage |
A tibble from the Learner Usage ADS. |
by |
Grouping dimension: |
A summarised tibble sorted by completion_rate.
if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_retention_summary(usage, by = "course") }if (bs_has_token()) { usage <- bs_get_ads("Learner Usage") bs_retention_summary(usage, by = "course") }
All analytics functions use this timezone for converting date columns.
bs_set_timezone(tz)bs_set_timezone(tz)
tz |
A valid timezone string from |
Invisibly returns the timezone string.
bs_set_timezone("Pacific/Auckland") bs_set_timezone("America/New_York")bs_set_timezone("Pacific/Auckland") bs_set_timezone("America/New_York")
Collapses enrollment records to keep only the latest enrollment date for each user-course combination.
bs_summarize_enrollments(enriched_enrollments, event_type = "Enroll")bs_summarize_enrollments(enriched_enrollments, event_type = "Enroll")
enriched_enrollments |
An enriched enrollment tibble (from
|
event_type |
The event type to filter to (default |
A tibble with one row per user per course.
if (bs_has_token()) { enriched <- bs_enrich_enrollments(enroll, org_units, users) summary <- bs_summarize_enrollments(enriched) }if (bs_has_token()) { enriched <- bs_enrich_enrollments(enroll, org_units, users) summary <- bs_summarize_enrollments(enriched) }