--- title: "Opt-out screening" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Opt-out screening} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} # Auth/network chunks are shown but not run at build time. knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE) ``` Screen a phone sample against the **opt-out list** -- every number that has opted out of Survey160 messaging -- to flag or drop opted-out numbers before you field. Assumes you have completed First-time setup (the package README, or `?s160_gcs_init` from R): Cloud Storage access to `s160_disposition_prod`. ## Screen a sample Pull the list once (cached), then annotate your sample in place: ```{r} library(survey160r) s160_gcs_init() # one browser sign-in, cached optout <- opt_out_pull() # small download, then cached my_sample <- data.frame(phone = c("2015550101", "2015550102")) # your phone sample cleaned <- opt_out_screen(my_sample, optout) kept <- subset(cleaned, !(opted_out %in% TRUE)) ``` `opt_out_screen()` returns `my_sample` unchanged with two columns appended 1:1 (see [What you get back](#what-you-get-back)). The `%in% TRUE` filter drops the opted-out numbers; a blank or unparseable phone screens to `NA` and is kept, so it surfaces for correction rather than being silently treated as contactable. ## Screen for opt-out and prior contact together The opt-out and disposition screens are independent and compose -- each appends its own columns and never drops rows -- so chain them and filter once on your own rules: ```{r} cleaned <- opt_out_screen(my_sample, opt_out_pull()) cleaned <- disposition_screen(cleaned, disposition_pull()) kept <- subset(cleaned, !(opted_out %in% TRUE | (n_completed > 0 | n_web_complete > 0) %in% TRUE | (n_terminated > 0 | n_refused > 0 | n_ineligible > 0) %in% TRUE)) ``` Both lists live in the same `s160_disposition_prod` bucket and cache to separate files, so one `s160_gcs_init()` covers both pulls. ## What you get back `opt_out_screen()` returns your sample with two columns appended, 1:1 with the input rows and in input order: | Column | Meaning | |---|---| | `opted_out` | `TRUE` if the number is on the opt-out list, `FALSE` if it is absent, `NA` if the phone is blank or unparseable. | | `opt_out_date` | When the number opted out (carried from the list); `NA` for numbers not on it. | Your original phone column and every other column of the sample are returned untouched. ## Notes - **`NA` is not "contactable".** A blank or unparseable phone screens to `opted_out = NA`, not `FALSE` -- the list cannot speak to a number it cannot read. Keep those rows (the `%in% TRUE` idiom does) and fix the phones. - **The complete list, not contacted-only.** Unlike the disposition dataset (recipients Survey160 has contacted), the opt-out list covers every opted-out number, whether or not it has been in a campaign -- so screen against it even for a fresh, never-fielded sample. - **Stale cache.** The list is re-published on every sync; `opt_out_pull(refresh = TRUE)` forces a fresh download. - **`env`.** `opt_out_pull()` reads `"prod"` (default) or `"dev"` -- there is no `staging` tier (staging sends fold into the prod bucket), so `env = "staging"` errors; use `env = "prod"` for staging data. Run `s160_datasets()` to see every dataset's environments. ## See also `?opt_out_screen`, `?opt_out_pull`, and `?survey160r` for every function by task. To screen the same sample on prior contact history, `vignette("disposition")`. For latency reports, `vignette("latency")`; for the fleet funnel by registration or brand, `vignette("campaign-metrics")`.