SQL · BigQuery
SQL Explore eCommerce Dataset
Analyzing user engagement and revenue trends on the Google Analytics public dataset in BigQuery.
Approach & Platform: Explore a public dataset of Google Analytics in BigQuery. Main Techniques: Window functions, CTEs, UNNEST on nested hits and product arrays.
Result: Extract key insights, such as engagement rates and revenue performance over time.
Query 01 · Total visits, pageviews, transactions (Jan–Mar 2017)
SELECT
FORMAT_DATE("%m-%Y", PARSE_DATE("%Y%m%d", date)) AS month,
SUM(totals.visits) AS number_of_visit,
SUM(totals.pageviews) AS number_of_pageview,
SUM(totals.transactions) AS number_of_transaction
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`
WHERE _table_suffix BETWEEN '0101' AND '0331'
GROUP BY month;
| Month | Visits | Pageviews | Transactions |
| 01-2017 | 64,694 | 257,708 | 713 |
| 02-2017 | 62,192 | 233,373 | 733 |
| 03-2017 | 69,931 | 259,522 | 993 |
✅ March 2017 had the most transactions; January 2017 had the highest visits.
Query 02 · Bounce rate per traffic source (Jul 2017)
SELECT
trafficSource.source,
COUNT(visitNumber) AS total_visits,
SUM(totals.bounces) AS total_no_of_bounces,
ROUND(SUM(totals.bounces) / COUNT(visitNumber) * 100, 2) AS bounce_percent
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
GROUP BY trafficSource.source
ORDER BY total_visits DESC;
| Source | Visits | Bounces | Bounce rate |
| google | 38,400 | 19,798 | 51.56% |
| (direct) | 19,891 | 8,606 | 43.27% |
| youtube.com | 6,351 | 4,238 | 66.73% |
| analytics.google.com | 1,972 | 1,064 | 53.96% |
| m.facebook.com | 669 | 430 | 64.28% |
✅ Google had the highest visits; YouTube and Facebook had the highest bounce rates.
Query 03 · Revenue by traffic source, weekly & monthly (Jun 2017)
WITH monthly_revenue AS (
SELECT "month" AS time_type,
FORMAT_DATE("%m-%Y", PARSE_DATE("%Y%m%d", date)) AS time,
trafficSource.source AS source,
ROUND(SUM(product.productRevenue / 1000000), 2) AS revenue
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201706*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE product.productRevenue IS NOT NULL
GROUP BY time_type, time, source
),
weekly_revenue AS (
SELECT "week" AS time_type,
FORMAT_DATE("%W-%Y", PARSE_DATE("%Y%m%d", date)) AS time,
trafficSource.source AS source,
ROUND(SUM(product.productRevenue) / 1000000, 2) AS revenue
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201706*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE product.productRevenue IS NOT NULL
GROUP BY time_type, time, source
)
SELECT * FROM monthly_revenue
UNION ALL SELECT * FROM weekly_revenue
ORDER BY revenue DESC;
| Type | Time | Source | Revenue |
| Month | 06-2017 | (direct) | $97,333.62 |
| Week | 24-2017 | (direct) | $30,908.91 |
| Week | 25-2017 | (direct) | $27,295.32 |
| Month | 06-2017 | google | $18,757.18 |
| Month | 06-2017 | dfa | $8,862.23 |
✅ Direct traffic dominated June 2017 with ~$97k monthly revenue, far ahead of Google ($18.7k).
Query 04 · Avg pageviews: purchasers vs non-purchasers (Jun–Jul 2017)
WITH purchase_data AS (
SELECT FORMAT_DATE("%m-%Y", PARSE_DATE("%Y%m%d", date)) AS month,
ROUND(SUM(totals.pageviews) / COUNT(DISTINCT fullVisitorId), 2) AS avg_pageviews_purchase
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE totals.transactions IS NOT NULL AND product.productRevenue IS NOT NULL
AND _table_suffix BETWEEN '0601' AND '0731'
GROUP BY month
),
non_purchase_data AS (
SELECT FORMAT_DATE("%m-%Y", PARSE_DATE("%Y%m%d", date)) AS month,
ROUND(SUM(totals.pageviews) / COUNT(DISTINCT fullVisitorId), 2) AS avg_pageviews_non_purchase
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE totals.transactions IS NULL AND product.productRevenue IS NULL
AND _table_suffix BETWEEN '0601' AND '0731'
GROUP BY month
)
SELECT p.month, p.avg_pageviews_purchase, n.avg_pageviews_non_purchase
FROM purchase_data p
FULL OUTER JOIN non_purchase_data n USING (month)
ORDER BY p.month;
✅ Purchasers viewed significantly more pages than non-purchasers; July had slightly higher averages than June.
Query 05 · Avg transactions per purchasing user (Jul 2017)
SELECT
"201707" AS Month,
ROUND(SUM(totals.transactions) / COUNT(DISTINCT fullVisitorId), 2)
AS Avg_total_transactions_per_user
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE totals.transactions >= 1
AND product.productRevenue IS NOT NULL;
| Month | Avg transactions / user |
| 201707 | 4.16 |
Query 06 · Avg revenue per session for purchasers (Jul 2017)
SELECT
FORMAT_DATE('%Y-%m', PARSE_DATE('%Y%m%d', date)) AS month,
ROUND((SUM(product.productRevenue) / SUM(totals.visits)) / 1000000, 2)
AS Avg_revenue_by_user_per_visit
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE product.productRevenue IS NOT NULL
AND totals.transactions IS NOT NULL
GROUP BY month;
| Month | Avg revenue / session |
| 2017-07 | $43.86 |
Query 07 · Cross-sell from “YouTube Men’s Vintage Henley” (Jul 2017)
WITH henley_cust_id AS (
SELECT DISTINCT fullVisitorId
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE product.v2ProductName = "YouTube Men's Vintage Henley"
AND totals.transactions >= 1
AND product.productRevenue IS NOT NULL
)
SELECT
product.v2ProductName AS other_purchased_products,
SUM(product.productQuantity) AS quantity
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE fullVisitorId IN (SELECT * FROM henley_cust_id)
AND product.v2ProductName <> "YouTube Men's Vintage Henley"
AND totals.transactions >= 1
AND product.productRevenue IS NOT NULL
GROUP BY product.v2ProductName
ORDER BY quantity DESC;
| Other purchased products | Qty |
| Google Sunglasses | 20 |
| Google Women's Vintage Hero Tee | 7 |
| SPF-15 Slim & Slender Lip Balm | 6 |
| Google Women's Short Sleeve Hero Tee | 4 |
| YouTube Men's Fleece Hoodie Black | 3 |
| Google Men's Short Sleeve Badge Tee | 3 |
✅ Customers who bought the Henley favored Google Sunglasses, highlighting strong interest in casual Google/YouTube branded accessories.
Query 08 · Cohort funnel: view → cart → purchase (Q1 2017)
WITH productview AS (
SELECT FORMAT_DATE("%Y%m", PARSE_DATE("%Y%m%d", date)) AS month,
COUNT(eCommerceAction.action_type) AS num_product_view
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`, UNNEST(hits) AS hits
WHERE _table_suffix BETWEEN '0101' AND '0331'
AND eCommerceAction.action_type = '2'
GROUP BY month
),
cart AS (
SELECT FORMAT_DATE("%Y%m", PARSE_DATE("%Y%m%d", date)) AS month,
COUNT(eCommerceAction.action_type) AS num_addtocart
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`, UNNEST(hits) AS hits
WHERE _table_suffix BETWEEN '0101' AND '0331'
AND eCommerceAction.action_type = '3'
GROUP BY month
),
purchase AS (
SELECT FORMAT_DATE("%Y%m", PARSE_DATE("%Y%m%d", date)) AS month,
COUNT(eCommerceAction.action_type) AS num_purchase
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_2017*`,
UNNEST(hits) AS hits, UNNEST(hits.product) AS product
WHERE _table_suffix BETWEEN '0101' AND '0331'
AND eCommerceAction.action_type = '6'
AND product.productRevenue IS NOT NULL
AND totals.transactions IS NOT NULL
GROUP BY month
)
SELECT month, num_product_view, num_addtocart, num_purchase,
ROUND(num_addtocart / num_product_view * 100, 2) AS add_to_cart_rate,
ROUND(num_purchase / num_product_view * 100, 2) AS purchase_rate
FROM productview JOIN cart USING (month) JOIN purchase USING (month)
ORDER BY month;
| Month | Views | Add-to-cart | Purchases | ATC rate | Purchase rate |
| 201701 | 25,787 | 7,342 | 2,143 | 28.47% | 8.31% |
| 201702 | 21,489 | 7,360 | 2,060 | 34.25% | 9.59% |
| 201703 | 23,549 | 8,782 | 2,977 | 37.29% | 12.64% |
✅ March 2017 peaked at 12.64% purchase rate; upward trend across all three months signals improving funnel health.
View .sql file