This analysis used data from Media Cloud database to compare online news coverage of Artificial Intelligence and Immigration. The results showed that Immigration received the highest overall number of stories, while Artificial Intelligence received fewer studies between December 1st, 2025 and September 1st, 2026. The fluctuations on the graph show how media organizations prioritize certain issues at different times. The findings provide insight into which topic attracted more attention in online news media and how that attention has changed over time.

Here’s a look at the content:

Code:

 ############################################################
# STEP 1: Install and Load Packages
############################################################

if (!require("tidyverse")) install.packages("tidyverse")
if (!require("httr2")) install.packages("httr2")
if (!require("lubridate")) install.packages("lubridate")
if (!require("kableExtra")) install.packages("kableExtra")
library(tidyverse)
library(httr2)
library(lubridate)
library(kableExtra)

############################################################
# STEP 2: Verify Media Cloud API Key
############################################################

if (!nzchar(Sys.getenv("MEDIACLOUD_KEY"))) {
  stop(
    "No Media Cloud API key was found.\n",
    "Please save your key to .Renviron first."
  )
}

############################################################
# STEP 3: Define Two Topics
############################################################

# Replace the topic labels and search queries below.
#
# Examples:
# "artificial intelligence"
# "climate change"
# "immigration"
# "inflation"

topics <- c(
  "Artificial Intelligence" = "\"artificial intelligence\"",
  "Immigration" = "\"Immigration\""
)

############################################################
# STEP 4: Define the Date Range
############################################################

start_date <- "2025-12-01"
end_date <- "2026-09-01"

############################################################
# STEP 5: Create a Function to Download
# Daily Story Counts
############################################################

get_counts <- function(query) {
  response <-
    request(
      "https://search.mediacloud.org/api/search/count-over-time"
    ) |>
    req_headers(
      Authorization = paste(
        "Token",
        Sys.getenv("MEDIACLOUD_KEY")
      )
    ) |>
    req_url_query(
      q = query,
      start = start_date,
      end = end_date,
      platform = "onlinenews-mediacloud",
      cs = 34412234
    ) |>
    req_perform()
  results <-
    response |>
    resp_body_json()
  map_dfr(
    results$count_over_time$counts,
    as_tibble
  ) |>
    mutate(
      date = as.Date(date)
    )
}

############################################################
# STEP 6: Download Data for Both Topics
############################################################

topic_data <-
  imap_dfr(
    topics,
    function(search_query, topic_name) {
      message("Downloading: ", topic_name)
      get_counts(search_query) |>
        mutate(
          topic = topic_name
        )
    }
  )

############################################################
# STEP 7: Examine the Downloaded Data
############################################################

head(topic_data)
glimpse(topic_data)

############################################################
# STEP 8: Calculate Weekly Story Counts
############################################################

weekly_counts <-
  topic_data |>
  mutate(
    week = floor_date(date, unit = "week")
  ) |>
  group_by(topic, week) |>
  summarise(
    stories = sum(count),
    .groups = "drop"
  )

############################################################
# STEP 9: Display Weekly Counts
############################################################

weekly_counts |>
  arrange(topic, week) |>
  kbl(
    caption = "Weekly Media Cloud Story Counts"
  ) |>
  kable_styling(
    full_width = FALSE,
    bootstrap_options = c(
      "striped",
      "hover"
    )
  )

############################################################
# STEP 10: Summarize Total Coverage
############################################################

topic_summary <-
  weekly_counts |>
  group_by(topic) |>
  summarise(
    Total_Stories = sum(stories),
    Weekly_Minimum = min(stories),
    Weekly_Maximum = max(stories),
    Weekly_Mean = round(mean(stories), 2),
    .groups = "drop"
  ) |>
  arrange(desc(Total_Stories))
topic_summary |>
  kbl(
    caption = "Coverage Summary by Topic"
  ) |>
  kable_styling(
    full_width = FALSE,
    bootstrap_options = c(
      "striped",
      "hover"
    )
  )

############################################################
# STEP 11: Create a Line Graph
############################################################

weekly_counts |>
  ggplot(
    aes(
      x = week,
      y = stories,
      color = topic
    )
  ) +
  geom_line(
    linewidth = 1
  ) +
  geom_point(
    size = 2
  ) +
  labs(
    title = "Weekly Media Coverage Volume",
    subtitle = "Comparison of Two Topics",
    x = "Week",
    y = "Number of Stories",
    color = "Topic"
  ) +
  theme_minimal()

############################################################
# STEP 12: Save Results as a CSV File
############################################################

write_csv(
  weekly_counts,
  "weekly_story_counts.csv"
)