Pregnancy Exposure Window
A protocol-specified set of gestational timing rules that maps maternal dispensings, administrations, or procedures onto etiologically relevant developmental periods (periconceptional, first/second/third trimester, peripartum, lactation) so that in-utero exposure is attributed to the window in which a given fetal or neonatal outcome can plausibly arise.
In plain language
A pregnancy exposure window is a specific slice of pregnancy time when a drug could actually cause a birth defect or developmental problem. Instead of simply asking whether a mother took a drug at any point during pregnancy, researchers pin down which biological stage the baby was in when the pills were on hand. For example, the first eight weeks after conception are when the heart, spine, and limbs are being formed, so a drug fill during that window matters far more to birth-defect risk than the same drug taken in the final weeks of pregnancy. In a health insurance claims database, analysts figure out the pregnancy start date, divide the pregnancy into developmental stages, and then check whether any prescription fills overlap each stage, producing a yes/no (or days-of-overlap) score per stage.
A pregnancy exposure window is the date logic that converts a raw maternal exposure record (a pharmacy fill, an infusion administration, a procedure) into the analytic statement "exposed during the developmental period relevant to this outcome." Most teratogenic and developmental effects are time-specific — organogenesis (roughly gestational weeks 3-8) governs the majority of major structural malformations, while later gestation governs fetal growth, neonatal adaptation/withdrawal, and neurodevelopment. Because of this, a single "any use during pregnancy" indicator is usually the wrong exposure: it dilutes a true window-specific signal toward the null by averaging in person-time when the drug could not have caused the outcome, and it invites confounding by indication when women who continue a drug into later trimesters differ systematically from those exposed only periconceptionally.
Every window is anchored to an estimated pregnancy start date — usually last menstrual period (LMP) or an estimated conception date — which in claims and most EHR data must itself be derived (delivery date minus a gestational-age estimate, or earliest prenatal-ultrasound/dating code). Once the anchor is set, the analyst applies pre-specified day or week intervals (e.g., LMP-90 to LMP-1 days periconceptional; LMP to LMP+90/97 days first trimester) and computes overlap between the drug's covered-days interval and each gestational interval. The output is a set of per-window exposure variables (binary, days-exposed, or dose-in-window) on the maternal timeline that are then carried into the mother-infant linked outcome analysis.
Core conceptual distinction
— the estimand is window-specific, not pregnancy-wide, and the window must be named a priori from biology — e.g., "first-trimester exposure to drug X versus an active comparator and the risk of major congenital malformation among live births." This differs sharply from three superficially similar definitions. (1) Versus an any-pregnancy ever-exposed indicator: that variable answers a different, usually less interpretable question and is biased toward the null whenever the causal window is narrow. (2) Versus cumulative dose across the whole pregnancy: that matches a cumulative-toxicity model but mis-specifies a pulse/critical-window mechanism. (3) Versus exposure-lag/induction windows in non-pregnancy pharmacoepidemiology: pregnancy windows are forward-anchored to a developmental clock (the conceptus's gestational age), not backward-lagged from outcome onset. Getting the anchor and the window boundaries right is the entire game; the downstream regression is comparatively routine.
Pros, cons, and trade-offs
— versus an any-use-during-pregnancy binary, window-specific classification preserves etiologic specificity, raises power for the relevant period, and reduces exposure misclassification from irrelevant person-time — at the cost of requiring a credible LMP estimate, explicit rules for fills that straddle two windows, and a bank of dating-sensitivity analyses. Versus trimester-only buckets (first/second/third with no periconceptional or lactation window), windows let you capture pre-recognition exposures (folate antagonists, retinoids acting before a woman knows she is pregnant) and lactation transfer for some neonatal endpoints, which crude trimester buckets miss. Versus cumulative-dose-over-pregnancy, a window is easier to communicate ("first-trimester exposed") and correct when the risk is a single critical pulse, but it loses power and is mis-specified when the true relationship is dose-cumulative across gestation — in which case a dose-in-window or time-updated cumulative-dose metric is preferable. The window approach also shares the active-comparator logic of mainstream pharmacoepidemiology: comparing first-trimester initiators of drug X to first-trimester initiators of a clinically interchangeable comparator beats a drug-versus-unexposed contrast, which is confounded by the underlying maternal indication.
When to use
— use windows for any study of in-utero drug effects on structural malformations, fetal growth, preterm birth, neonatal adaptation/withdrawal, or longer-term neurodevelopment where biology or prior human/animal data implicate a time-limited sensitive period. They are effectively mandatory for regulatory pregnancy-safety studies (FDA and EMA post-approval pregnancy safety guidance, pregnancy registries, and PASS) and for any comparative safety/effectiveness claim that references a specific gestational timing on a product label.
When NOT to use — and when it is actively misleading or dangerous
— do not impose a window when the outcome has no plausible gestational specificity (e.g., a maternal injury months postpartum); the window only adds noise. Do not trust window membership when LMP cannot be estimated within an acceptable error — very late or absent prenatal care, missing gestational-age fields, or reliance on a delivery code with no dating information can make window misclassification worse than an honest any-pregnancy analysis, and a fill near a trimester boundary will be assigned almost at random. The design becomes actively dangerous in three situations: (a) differential pregnancy recognition or termination by exposure — women on a known teratogen may be diagnosed earlier, have earlier dating ultrasounds, or undergo elective termination, which depletes the affected fetuses from the live-birth denominator and biases the live-birth-restricted risk toward the null (a form of live-birth/survivor selection bias); (b) immortal-time-style misalignment when exposure status in a later window is used to define a cohort whose person-time in an earlier window is then counted as "unexposed"; and (c) presenting a reassuring "no increased risk" from an any-pregnancy binary when the etiologically relevant window-specific analysis was never run or was hopelessly under-powered.
Data-source operational depth
- Claims (FFS vs MA vs commercial): LMP is almost always derived — delivery date minus gestational weeks from diagnosis/procedure codes, prenatal-ultrasound dating codes, or a published/validated algorithm. Drug exposure is the pharmacy claim (`ndc` + `fill_date` + `days_supply`); you must construct covered-day intervals and handle reversals, early refills, stockpiling, and 90-day mail-order supplies before computing window overlap. Require continuous medical + pharmacy enrollment across the entire periconceptional-through-delivery span so that "no fill in the window" is observed non-exposure, not missingness. Specific failure modes: Medicare Advantage and capitated/bundled person-time drop fee-for-service claims, so a MA-only span fabricates apparent non-exposure — restrict to enrollees with both medical and pharmacy benefit and exclude MA-only person-time. Differential competing risks of fetal loss by exposure distort the live-birth denominator; report the proportion of pregnancies ending in an observed live birth by arm and analyze non-live-birth endpoints in the maternal cohort. Immortal time in procedure or infusion studies — e.g., requiring a second-trimester administration to be "exposed" makes all of the first trimester immortal — must be avoided by aligning time zero to the first qualifying exposure. - EHR: Prenatal flow sheets, dating ultrasounds, and problem-list gestational age give a direct LMP/EDC and far sharper exposure timing via e-prescribing and medication administration records than fills alone. The cost is visit-driven, leaky capture: external pharmacies and care outside the system are missing, and a patient who leaves the network is differentially lost. Link to claims for complete dispensing and for infant outcomes rendered elsewhere. - Registry: Product or disease pregnancy registries capture exact LMP, ultrasound dating, exposure dates, and adjudicated outcomes prospectively with high validity — but are small and selected (enrollment, recall, and healthy-volunteer effects). Their best use is to validate claims-based window/LMP algorithms or to triangulate effect sizes, not to estimate population risk alone. - Linked claims-EHR-vital records: The reference substrate — claims for complete pharmacy + enrollment, EHR for clinical dating and infant exams, vital/birth records for confirmed live births and recorded gestational age. The catch is linkage selection (only the linkable subset) and date reconciliation across order, fill, service, and delivery dates, which must be resolved before any window is assigned.
Worked claims example (antiepileptic drug, first-trimester major-malformation risk)
Source: linked commercial + multi-state Medicaid claims, 2016-2023. Build the pregnancy cohort by identifying delivery claims, then back-date LMP with a validated gestational-age algorithm (delivery_date - estimated gestational weeks) or the earliest prenatal-dating ultrasound code when present. Eligibility: continuous maternal medical + pharmacy enrollment (no MA-only spans) from LMP-90 days through 90 days post-delivery, and a linked infant continuously enrolled >=90 days. Define the first-trimester window as `[LMP, LMP+97 days]`. For each maternal fill, compute its covered interval `[fill_date, fill_date + days_supply - 1]` and flag `exp_t1 = 1` if that interval overlaps the first-trimester window by at least one day (primary, binary); secondary metrics are days-overlapping-window and average daily milligrams in window. Outcome: a major-congenital- malformation algorithm with validated PPV > 0.80 applied to infant claims in days 0-90 plus the index inpatient stay. Restrict to first-trimester initiators of the index AED versus first-trimester initiators of an active-comparator AED (active-comparator, new-user logic ported into pregnancy), and balance maternal age, epilepsy-type and severity proxies, comorbidities, folic-acid use, and concomitant AEDs with a high-dimensional propensity score (matching or overlap weighting). In this construction the adjusted risk ratio for first-trimester exposure to the teratogenic AED was 2.8 (95% CI 1.6-4.9), whereas the any-pregnancy ever-exposed RR was only 1.9 (1.1-3.2) — diluted by third-trimester-only users for whom organogenesis had passed. Pre-specified dating-sensitivity analyses (shift the LMP algorithm by +/-14 days; move the window end by +/-7 days; reassign straddling fills by majority-of-covered-days rather than any-overlap) moved the point estimate only between 2.4 and 3.1, and a negative-control outcome with no plausible teratogenic mechanism was null, supporting robustness against residual dating error and confounding.
Worked example
Scenario
Maria is a 28-year-old with epilepsy who filled a prescription for an antiepileptic drug several times during her pregnancy. Her delivery was on 2023-09-28, and a validated algorithm estimates her LMP as 2022-12-28, giving a gestational length of about 274 days. We want to know whether she had the drug on hand during the first trimester, specifically the organogenesis window (LMP through LMP+97 days, i.e., 2022-12-28 through 2023-04-04), because that is when major structural malformations are most plausible. We will look up her pharmacy fills in the claims table and compute whether any covered-day interval overlaps that first-trimester window.
Dataset
Maria's pharmacy claims rows (person_id 2001). Each row is one prescription fill.
| person_id | fill_date | drug | days_supply |
|---|---|---|---|
| 2001 | 2022-12-01 | levetiracetam 500 mg | 30 |
| 2022 | 2022-12-01 | levetiracetam 500 mg | 30 |
| 2001 | 2022-12-30 | levetiracetam 500 mg | 90 |
| 2001 | 2023-03-28 | levetiracetam 500 mg | 90 |
| 2001 | 2023-06-25 | levetiracetam 500 mg | 90 |
Steps
Row 1 (fill_date 2022-12-01, 30 days): covered interval is Dec 1 to Dec 30, 2022. LMP is Dec 28, 2022, so this fill ends just two days into the pregnancy. It overlaps the first-trimester window by 3 days (Dec 28-30). This counts as first-trimester exposed.
Row 2 is for person 2022, not Maria (person 2001) -- skip it.
Row 3 (fill_date 2022-12-30, 90 days): covered interval is Dec 30, 2022 through Mar 29, 2023. The first-trimester window ends Apr 4, 2023. This fill is entirely inside the first trimester -- all 90 days overlap.
Row 4 (fill_date 2023-03-28, 90 days): covered interval is Mar 28 through Jun 25, 2023. The first-trimester window ends Apr 4. The overlap is Mar 28 through Apr 4 = 8 days. This fill also reaches into the second trimester (Apr 5 onward).
Row 5 (fill_date 2023-06-25, 90 days): covered interval is Jun 25 through Sep 22, 2023. The first-trimester window ended Apr 4 -- no overlap. This fill is second and third trimester only.
Total unique days overlapping the first-trimester window: the union of Dec 28 through Apr 4 is 98 days. Rows 1, 3, and 4 together cover this entire span without a gap, so Maria had levetiracetam on hand for all 98 days of the first-trimester window.
Result: first-trimester exposed = YES (binary = 1); days-in-window = 98; coverage fraction = 98/98 = 1.00.
Result
Maria is classified as first-trimester exposed (binary = 1). Her covered days fully span the 98-day first-trimester window (Dec 28, 2022 through Apr 4, 2023), meaning the drug was theoretically on hand during the entire organogenesis period. This exposure flag is what gets carried into the birth-defect outcome analysis.
Timeline Spec
- Title
First-trimester drug exposure during organogenesis for one epilepsy patient
- Caption
Maria's levetiracetam fills (gray bars) plotted against her pregnancy timeline. The first-trimester organogenesis window (red span, LMP through LMP+97 days) is fully covered by fills from December 2022 through April 2023. Fills in the second and third trimesters do not affect the first-trimester exposure classification.
- Alt Text
Horizontal timeline from estimated LMP (Dec 28 2022) to delivery (Sep 28 2023). Three trimester spans are shown as colored bands beneath the timeline. Four prescription fill bars sit above the timeline, labeled with fill date and days_supply. The first-trimester band (organogenesis window) is highlighted in red; two fill bars overlap it completely. A result label reads: first-trimester exposed = 1, days in window = 98.
- Window
- Start
2022-12-28
- End
2023-09-28
- Label
Full pregnancy (LMP to delivery, 274 days)
- Events
- Label
Fill A (pre-LMP tail)
- Start
2022-12-01
- Length Days
30
- Quantity
30 days_supply
- Label
Fill B (first 90-day fill)
- Start
2022-12-30
- Length Days
90
- Quantity
90 days_supply
- Label
Fill C (straddles T1/T2 boundary)
- Start
2023-03-28
- Length Days
90
- Quantity
90 days_supply
- Label
Fill D (T2/T3 only)
- Start
2023-06-25
- Length Days
90
- Quantity
90 days_supply
- Spans
- Kind
exposed
- Start
2022-12-28
- End
2023-04-04
- Label
First trimester (organogenesis window): 98 days -- fully covered, exposed = 1
- Kind
followup
- Start
2023-04-05
- End
2023-06-24
- Label
Second trimester: 81 days
- Kind
followup
- Start
2023-06-25
- End
2023-09-28
- Label
Third trimester: 95 days
- Result
- Label
First-trimester exposed = 1 (98 covered days / 98-day window = 100% coverage)
- Value
1
Runnable example
python implementation
Window assignment from claims-style inputs. Required inputs (already cleaned, de-duplicated, and enrollment-filtered): preg : one row per pregnancy -> person_id, lmp_derived (datetime), delivery_date (datetime) # lmp_derived comes from a validated...
import pandas as pd
import numpy as np
# Window edges as integer days relative to LMP (LMP = day 0). End is inclusive.
WINDOWS = {
"precon": (-90, -1), # periconceptional: 90 days before LMP
"t1": (0, 97), # first trimester (organogenesis-bearing)
"t2": (98, 195), # second trimester
"t3": (196, 300), # third trimester (capped; delivery may truncate)
}
def assign_windows(preg: pd.DataFrame, rx: pd.DataFrame) -> pd.DataFrame:
f = rx.merge(preg[["person_id", "lmp_derived", "delivery_date"]], on="person_id", how="inner")
# Covered interval of each fill, in days since LMP.
f["cov_start"] = (f["fill_date"] - f["lmp_derived"]).dt.days
f["cov_end"] = f["cov_start"] + f["days_supply"].astype(int) - 1
# Truncate third trimester at the observed delivery day so post-delivery supply isn't counted in utero.
deliv_day = (f["delivery_date"] - f["lmp_derived"]).dt.days
rows = []
for win, (w0, w1_const) in WINDOWS.items():
w1 = np.minimum(w1_const, deliv_day) if win == "t3" else pd.Series(w1_const, index=f.index)
ov_start = np.maximum(f["cov_start"], w0)
ov_end = np.minimum(f["cov_end"], w1)
days_overlap = (ov_end - ov_start + 1).clip(lower=0)
tmp = f.assign(window=win, days_in_window=days_overlap)
tmp["mg_in_window"] = tmp["days_in_window"] * tmp.get("daily_mg", np.nan)
rows.append(tmp[["person_id", "window", "days_in_window", "mg_in_window"]])
long = pd.concat(rows, ignore_index=True)
agg = (long.groupby(["person_id", "window"], as_index=False)
.agg(days_in_window=("days_in_window", "sum"),
mg_in_window=("mg_in_window", "sum")))
agg["exposed"] = (agg["days_in_window"] > 0).astype(int) # any-overlap binary; swap for majority-of-days rule
wide = agg.pivot(index="person_id", columns="window",
values=["exposed", "days_in_window", "mg_in_window"])
wide.columns = [f"{m}_{w}" for m, w in wide.columns]
return preg.merge(wide.reset_index(), on="person_id", how="left").fillna(
{c: 0 for c in wide.columns if c.startswith("exposed_")})r implementation
data.table window assignment mirroring the Python version. Inputs (cleaned, enrollment-filtered): preg : person_id, lmp_derived (Date), delivery_date (Date) rx : person_id, ndc, fill_date (Date), days_supply (integer), daily_mg (numeric, optional) Produces...
library(data.table)
# Window edges in days relative to LMP (day 0); end inclusive.
win_edges <- list(precon = c(-90L, -1L), t1 = c(0L, 97L),
t2 = c(98L, 195L), t3 = c(196L, 300L))
assign_windows <- function(preg, rx) {
setDT(preg); setDT(rx)
f <- merge(rx, preg[, .(person_id, lmp_derived, delivery_date)], by = "person_id")
f[, cov_start := as.integer(fill_date - lmp_derived)]
f[, cov_end := cov_start + as.integer(days_supply) - 1L]
f[, deliv_day := as.integer(delivery_date - lmp_derived)]
if (!"daily_mg" %in% names(f)) f[, daily_mg := NA_real_]
out <- rbindlist(lapply(names(win_edges), function(win) {
w0 <- win_edges[[win]][1L]
w1 <- if (win == "t3") pmin(win_edges[[win]][2L], f$deliv_day) else win_edges[[win]][2L]
ov_start <- pmax(f$cov_start, w0)
ov_end <- pmin(f$cov_end, w1)
days_ov <- pmax(ov_end - ov_start + 1L, 0L)
data.table(person_id = f$person_id, window = win,
days_in_window = days_ov, mg_in_window = days_ov * f$daily_mg)
}))
agg <- out[, .(days_in_window = sum(days_in_window),
mg_in_window = sum(mg_in_window, na.rm = TRUE)),
by = .(person_id, window)]
agg[, exposed := as.integer(days_in_window > 0)] # any-overlap; swap for majority-of-days rule
wide <- dcast(agg, person_id ~ window,
value.var = c("exposed", "days_in_window", "mg_in_window"), fill = 0)
merge(preg, wide, by = "person_id", all.x = TRUE)
}