Worthwise Impulse Purchase Prediction Model
This model estimates the probability that a browsing session will end in a purchase, based on behavioral signals like time spent and engagement, rather than product details. It powers Worthwise, an app that helps people pause and reflect before making a purchase.
What This Model Does
Given a set of session-level behavioral features, the model outputs a probability (0 to 1) that the session is "purchase-like," based on patterns learned from real e-commerce browsing data. It does not predict whether a purchase will be regretted, and it does not use any information about the specific item being considered (no price, name, or category).
Training Data
Trained on the UCI Online Shoppers Purchasing Intention Dataset,
12,330 real, anonymized e-commerce browsing sessions, each labeled with whether the
session resulted in a purchase (Revenue). About 15.5% of sessions in the dataset ended
in a purchase.
Why This Version Is Different From a Standard Model on This Dataset
The original dataset includes several features that come from live e-commerce site analytics (Google Analytics-derived metrics and traffic-source data). Those features are not observable by a standalone application that isn't connected to a real retailer's backend, so they were deliberately excluded from training:
PageValuesโ a proprietary, site-owner-only analytics metric. By far the strongest predictor in the original dataset (correlation ~0.49 with purchase), but permanently unavailable outside a real e-commerce backend.TrafficType,OperatingSystems,Browser,Regionโ describe how a visitor arrived at a website; not applicable to a standalone reflection app.
This is a deliberate tradeoff: the model is meaningfully less accurate than it could be with those features included, but every feature it actually uses can be honestly and directly provided by an app with no backend analytics access. See Performance below for exactly how much this tradeoff cost.
Features Used (26 total)
Base features: Administrative, Administrative_Duration, Informational,
Informational_Duration, ProductRelated, ProductRelated_Duration, BounceRates,
ExitRates, SpecialDay, Weekend, Month (one-hot encoded), VisitorType (one-hot
encoded)
Engineered features:
Total_Duration= sum of all page-type durationsTotal_Pages= sum of all page-type countsAvg_Duration_Per_Page= Total_Duration / Total_PagesProductRelated_Ratio= ProductRelated / Total_PagesEngagement_Score= Total_Duration ร (1 โ BounceRates)
Model Details
- Algorithm: XGBoost (
XGBClassifier) - Hyperparameters:
max_depth=3,learning_rate=0.05,n_estimators=300,min_child_weight=3,subsample=0.7, tuned viaRandomizedSearchCV(5-fold CV, scored on ROC-AUC) - Class imbalance handling:
scale_pos_weight, set to the ratio of negative to positive class in the training data - Decision threshold: 0.55 (tuned via precision/recall/F1 sweep; the default 0.5 under-performed on F1 and recall for this imbalanced task)
Performance
Evaluated on a held-out, stratified 20% test set (2,466 sessions), using only the 26 app-observable features described above:
| Metric | Score |
|---|---|
| ROC-AUC | 0.777 |
| Recall (purchase class) | 0.75 |
| Precision (purchase class) | 0.31 |
| F1 (purchase class) | 0.43 |
For comparison, a version of this model trained with PageValues included scored
ROC-AUC 0.894 and recall 0.75 with much higher precision (0.49). That comparison is the
clearest evidence of how much predictive power was traded away by restricting the model
to only app-observable features, roughly 0.12 ROC-AUC.
Known Limitations
- No regret label exists. This model predicts whether a session looks like others that ended in a purchase, not whether the person will regret that purchase. No public dataset of "purchase โ regretted" exists; this is the closest available proxy.
- Precision is low (0.31). At the chosen threshold, roughly 2 out of 3 sessions flagged as "high risk" are false positives. This is a real, measured limitation, not an estimate.
- Some features are approximated, not measured, in the app that uses this model
(e.g.
BounceRates/ExitRatesare rough proxies based on click behavior, not real site analytics). See the Worthwise app's own "How this works" page for the full breakdown of which inputs are real vs. approximated at inference time. PageValuescannot be added back without connecting to a real e-commerce analytics backend; this is a permanent, structural limitation of any standalone version of this model.
How to Load and Use
This model is saved in XGBoost's native JSON format (impulse_booster.json), which is
more portable across environments than a pickled scikit-learn wrapper.
import xgboost as xgb
import joblib
import pandas as pd
# Load the booster
booster = xgb.Booster()
booster.load_model("impulse_booster.json")
# Load the supporting artifacts
scaler = joblib.load("impulse_scaler_final.pkl")
model_columns = joblib.load("impulse_model_columns_final.pkl")
numeric_cols = joblib.load("impulse_numeric_cols_final.pkl")
threshold = joblib.load("impulse_decision_threshold_final.pkl")
# Build a single-row input matching model_columns exactly (one-hot encode
# categorical fields, fill any missing expected column with 0), then scale
# the numeric_cols using the loaded scaler before prediction.
dmatrix = xgb.DMatrix(input_row_df) # input_row_df must match model_columns order
probability = booster.predict(dmatrix)[0]
is_high_risk = probability >= threshold
Included Files
| File | Purpose |
|---|---|
impulse_booster.json |
Trained XGBoost model (native format) |
impulse_scaler_final.pkl |
Fitted StandardScaler for numeric features |
impulse_model_columns_final.pkl |
Ordered list of all 26 expected input columns |
impulse_numeric_cols_final.pkl |
List of which columns need scaling |
impulse_decision_threshold_final.pkl |
Tuned decision threshold (0.55) |
Intended Use
This model was built for Worthwise, a personal-finance reflection tool intended to help people pause before impulse purchases. It is not intended for use in credit decisions, fraud detection, or any high-stakes automated decision-making. Given its precision limitations, outputs should be treated as a soft signal for reflection, not a definitive judgment.