{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "rRZ7j28KcY5ZyKWv7dQnxjxF", "metadata": { "id": "rRZ7j28KcY5ZyKWv7dQnxjxF", "tags": [] }, "outputs": [], "source": [ "# Copyright 2025 Google LLC\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License.\n" ] }, { "cell_type": "markdown", "id": "Z_Qroe-RvDQQ", "metadata": { "id": "Z_Qroe-RvDQQ" }, "source": [ "# Customer Segmentation" ] }, { "cell_type": "markdown", "id": "76c24018318e", "metadata": {}, "source": [ "## Overview" ] }, { "cell_type": "markdown", "id": "PUDZ25xLvDpS", "metadata": { "id": "PUDZ25xLvDpS" }, "source": [ "**The Business Challenge:** Marketing teams often need to optimize budget allocation to maximize return on investment (ROI). A one-size-fits-all marketing strategy is inefficient, leading to wasted ad spend and low engagement, as the messaging is not relevant to all recipients. The business problem is to develop a systematic, data-driven method for partitioning a customer base into distinct groups based on their behavior, enabling more effective and personalized marketing campaigns.\n", "\n", "While basic segmentation using simple demographic data is straightforward, it often fails to capture the more nuanced differences in customer purchasing patterns. The analytical challenge is to move beyond these simple heuristics and identify meaningful segments based on complex behavioral data, such as purchase frequency, monetary value, and product category preferences. The goal is to produce segments that are not only statistically distinct but also interpretable and actionable for the marketing team.\n" ] }, { "cell_type": "markdown", "id": "B9huAQgmvUjL", "metadata": { "id": "B9huAQgmvUjL" }, "source": [ "**The Data Science Approach:** In this use case, we will combine unsupervised machine learning with generative AI to create and characterize customer segments. First, we will apply a k-means clustering algorithm directly within BigQuery ML to efficiently partition the entire customer dataset based on purchasing behavior within BigQuery.\n", "\n", "Clustering effectively groups customers and generates a cluster ID. The second part of our approach is to automate the interpretation of these segments to provide business context. We will use a generative AI function to analyze the behavioral data of customers within each cluster and programmatically generate qualitative descriptions, including concise segment name, segment summary and tailored marketing suggestions for each segment." ] }, { "cell_type": "markdown", "id": "771239ce343a", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "markdown", "id": "8b082ef2f84b", "metadata": {}, "source": [ "This section sets up the necessary environment and configurations for running the notebook. It includes defining project and dataset IDs and providing instructions for BigQuery connections." ] }, { "cell_type": "markdown", "id": "423583cd", "metadata": {}, "source": [ "Installs the `bigquery-magics` extension, which allows running BigQuery SQL queries directly within Jupyter notebooks." ] }, { "cell_type": "code", "execution_count": null, "id": "4d8ca68b", "metadata": {}, "outputs": [], "source": [ "%pip install bigquery-magics -q" ] }, { "cell_type": "markdown", "id": "2151333d", "metadata": {}, "source": [ "Loads the `bigquery_magics` extension, enabling the use of `%%bigquery --project $PROJECT_ID` cell magic for executing SQL." ] }, { "cell_type": "code", "execution_count": null, "id": "a382ebbc", "metadata": {}, "outputs": [], "source": [ "%load_ext bigquery_magics" ] }, { "cell_type": "markdown", "id": "47cc86ef", "metadata": {}, "source": [ "### Configure Google Cloud Project and Dataset\n", "\n", "Defines the Google Cloud project ID, dataset ID, and geographic location to be used for BigQuery operations. **Remember to replace `PROJECT_ID` and `DATASET_ID` with your actual values.**" ] }, { "cell_type": "code", "execution_count": null, "id": "6723c732", "metadata": {}, "outputs": [], "source": [ "PROJECT_ID = \"PROJECT_ID\"\n", "DATASET_ID = \"DATASET_ID\"\n", "LOCATION = \"US\"" ] }, { "cell_type": "markdown", "id": "b3e9444bb252", "metadata": {}, "source": [ "## Data Preparation" ] }, { "cell_type": "markdown", "id": "06394e1e0a29", "metadata": {}, "source": [ "### Preview Raw Customer Order Data\n", "\n", "This cell queries a sample of the raw customer order data from the `thelook_ecommerce` public dataset to understand its structure and content before further processing." ] }, { "cell_type": "code", "execution_count": null, "id": "YAh27zfewa03", "metadata": { "id": "YAh27zfewa03" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "fe4eed5349eb45debda2aff921fd663d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Query is running: 0%| |" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3c33dd452fae4ed68315cdcfedc9eeb5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Downloading: 0%| |" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.microsoft.datawrangler.viewer.v0+json": { "columns": [ { "name": "index", "rawType": "int64", "type": "integer" }, { "name": "order_id", "rawType": "Int64", "type": "integer" }, { "name": "user_id", "rawType": "Int64", "type": "integer" }, { "name": "status", "rawType": "object", "type": "string" }, { "name": "gender", "rawType": "object", "type": "string" }, { "name": "created_at", "rawType": "datetime64[us, UTC]", "type": "unknown" }, { "name": "returned_at", "rawType": "datetime64[us, UTC]", "type": "unknown" }, { "name": "shipped_at", "rawType": "datetime64[us, UTC]", "type": "unknown" }, { "name": "delivered_at", "rawType": "datetime64[us, UTC]", "type": "unknown" }, { "name": "num_of_item", "rawType": "Int64", "type": "integer" } ], "ref": "4878aeef-734f-47a5-ab97-a928d10b3f76", "rows": [ [ "0", "15", "10", "Cancelled", "F", "2025-07-19 06:06:00+00:00", null, null, null, "1" ], [ "1", "18", "14", "Cancelled", "F", "2024-07-28 03:35:00+00:00", null, null, null, "3" ], [ "2", "39", "32", "Cancelled", "F", "2021-05-19 16:28:00+00:00", null, null, null, "1" ], [ "3", "47", "37", "Cancelled", "F", "2023-03-02 01:10:00+00:00", null, null, null, "1" ], [ "4", "68", "54", "Cancelled", "F", "2023-11-28 10:53:00+00:00", null, null, null, "1" ], [ "5", "71", "56", "Cancelled", "F", "2025-07-02 14:05:00+00:00", null, null, null, "1" ], [ "6", "73", "59", "Cancelled", "F", "2023-09-05 14:53:00+00:00", null, null, null, "1" ], [ "7", "76", "63", "Cancelled", "F", "2023-02-07 02:37:00+00:00", null, null, null, "1" ], [ "8", "84", "70", "Cancelled", "F", "2021-10-08 05:27:00+00:00", null, null, null, "1" ], [ "9", "85", "71", "Cancelled", "F", "2024-08-04 13:54:00+00:00", null, null, null, "1" ], [ "10", "87", "72", "Cancelled", "F", "2022-08-12 06:45:00+00:00", null, null, null, "1" ], [ "11", "88", "72", "Cancelled", "F", "2025-01-19 06:45:00+00:00", null, null, null, "2" ], [ "12", "113", "96", "Cancelled", "F", "2023-05-27 16:56:00+00:00", null, null, null, "1" ], [ "13", "140", "117", "Cancelled", "F", "2022-09-10 18:20:00+00:00", null, null, null, "2" ], [ "14", "141", "117", "Cancelled", "F", "2023-12-11 18:20:00+00:00", null, null, null, "3" ], [ "15", "144", "120", "Cancelled", "F", "2024-01-22 18:34:00+00:00", null, null, null, "1" ], [ "16", "148", "123", "Cancelled", "F", "2024-03-21 06:48:00+00:00", null, null, null, "1" ], [ "17", "149", "123", "Cancelled", "F", "2025-03-29 06:48:00+00:00", null, null, null, "1" ], [ "18", "167", "140", "Cancelled", "F", "2024-01-31 12:27:00+00:00", null, null, null, "1" ], [ "19", "174", "143", "Cancelled", "F", "2023-04-10 14:08:00+00:00", null, null, null, "1" ], [ "20", "192", "155", "Cancelled", "F", "2019-12-25 04:16:00+00:00", null, null, null, "1" ], [ "21", "207", "166", "Cancelled", "F", "2024-05-31 01:03:00+00:00", null, null, null, "2" ], [ "22", "212", "172", "Cancelled", "F", "2025-07-18 04:15:00+00:00", null, null, null, "1" ], [ "23", "227", "181", "Cancelled", "F", "2025-08-21 17:49:00+00:00", null, null, null, "1" ], [ "24", "238", "186", "Cancelled", "F", "2024-09-10 13:05:00+00:00", null, null, null, "4" ], [ "25", "257", "198", "Cancelled", "F", "2024-01-02 07:38:00+00:00", null, null, null, "1" ], [ "26", "299", "233", "Cancelled", "F", "2024-05-04 03:32:00+00:00", null, null, null, "1" ], [ "27", "301", "234", "Cancelled", "F", "2024-04-11 15:14:00+00:00", null, null, null, "4" ], [ "28", "317", "242", "Cancelled", "F", "2024-07-03 04:35:00+00:00", null, null, null, "1" ], [ "29", "318", "243", "Cancelled", "F", "2025-09-03 02:52:42.726372+00:00", null, null, null, "4" ], [ "30", "337", "256", "Cancelled", "F", "2024-04-30 17:13:00+00:00", null, null, null, "1" ], [ "31", "364", "276", "Cancelled", "F", "2020-05-28 15:13:00+00:00", null, null, null, "2" ], [ "32", "373", "281", "Cancelled", "F", "2024-09-08 13:08:00+00:00", null, null, null, "1" ], [ "33", "374", "283", "Cancelled", "F", "2020-06-15 03:21:00+00:00", null, null, null, "2" ], [ "34", "381", "289", "Cancelled", "F", "2025-09-03 07:34:43.685205+00:00", null, null, null, "4" ], [ "35", "391", "299", "Cancelled", "F", "2025-05-16 17:35:00+00:00", null, null, null, "1" ], [ "36", "406", "314", "Cancelled", "F", "2021-12-21 02:49:00+00:00", null, null, null, "2" ], [ "37", "411", "319", "Cancelled", "F", "2025-05-16 11:53:00+00:00", null, null, null, "2" ], [ "38", "414", "321", "Cancelled", "F", "2023-11-10 09:34:00+00:00", null, null, null, "2" ], [ "39", "418", "323", "Cancelled", "F", "2023-11-07 15:24:00+00:00", null, null, null, "1" ], [ "40", "420", "326", "Cancelled", "F", "2022-02-05 04:17:00+00:00", null, null, null, "2" ], [ "41", "454", "355", "Cancelled", "F", "2023-07-02 15:06:00+00:00", null, null, null, "1" ], [ "42", "456", "358", "Cancelled", "F", "2024-06-06 11:45:00+00:00", null, null, null, "1" ], [ "43", "483", "386", "Cancelled", "F", "2023-08-20 00:59:00+00:00", null, null, null, "3" ], [ "44", "486", "389", "Cancelled", "F", "2025-04-24 08:00:00+00:00", null, null, null, "1" ], [ "45", "502", "398", "Cancelled", "F", "2024-12-17 02:46:00+00:00", null, null, null, "1" ], [ "46", "510", "402", "Cancelled", "F", "2023-02-21 18:49:00+00:00", null, null, null, "1" ], [ "47", "511", "403", "Cancelled", "F", "2024-08-31 00:25:00+00:00", null, null, null, "1" ], [ "48", "516", "406", "Cancelled", "F", "2025-08-15 03:47:00+00:00", null, null, null, "1" ], [ "49", "526", "417", "Cancelled", "F", "2024-02-06 05:05:00+00:00", null, null, null, "1" ] ], "shape": { "columns": 9, "rows": 1000 } }, "text/html": [ "
| \n", " | order_id | \n", "user_id | \n", "status | \n", "gender | \n", "created_at | \n", "returned_at | \n", "shipped_at | \n", "delivered_at | \n", "num_of_item | \n", "
|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "15 | \n", "10 | \n", "Cancelled | \n", "F | \n", "2025-07-19 06:06:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 1 | \n", "18 | \n", "14 | \n", "Cancelled | \n", "F | \n", "2024-07-28 03:35:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "3 | \n", "
| 2 | \n", "39 | \n", "32 | \n", "Cancelled | \n", "F | \n", "2021-05-19 16:28:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 3 | \n", "47 | \n", "37 | \n", "Cancelled | \n", "F | \n", "2023-03-02 01:10:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 4 | \n", "68 | \n", "54 | \n", "Cancelled | \n", "F | \n", "2023-11-28 10:53:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 995 | \n", "12816 | \n", "10141 | \n", "Cancelled | \n", "F | \n", "2024-10-01 11:40:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 996 | \n", "12833 | \n", "10152 | \n", "Cancelled | \n", "F | \n", "2025-09-03 01:47:50.414919+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 997 | \n", "12869 | \n", "10183 | \n", "Cancelled | \n", "F | \n", "2025-06-29 15:24:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 998 | \n", "12875 | \n", "10185 | \n", "Cancelled | \n", "F | \n", "2024-06-17 17:06:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
| 999 | \n", "12877 | \n", "10186 | \n", "Cancelled | \n", "F | \n", "2023-05-09 18:57:00+00:00 | \n", "NaT | \n", "NaT | \n", "NaT | \n", "1 | \n", "
1000 rows \u00d7 9 columns
\n", "