sql/moz-fx-data-shared-prod/mozilla_vpn_derived/all_subscriptions_v1/query.sql (375 lines of code) (raw):
WITH standardized_country AS (
SELECT
raw_country AS country,
standardized_country AS country_name,
FROM
`moz-fx-data-shared-prod`.static.third_party_standardized_country_names
),
fxa_attributions AS (
SELECT
fxa_uid,
attribution
FROM
`moz-fx-data-shared-prod`.mozilla_vpn_derived.fxa_attribution_v1
CROSS JOIN
UNNEST(fxa_uids) AS fxa_uid
WHERE
attribution IS NOT NULL
),
users AS (
SELECT
id AS user_id,
fxa_uid,
created_at AS user_registration_date,
FROM
`moz-fx-data-shared-prod`.mozilla_vpn.users
),
stripe_subscriptions_history AS (
SELECT
*,
CONCAT(
subscription_id,
COALESCE(
CONCAT(
"-",
NULLIF(ROW_NUMBER() OVER (PARTITION BY subscription_id ORDER BY valid_from), 1)
),
""
)
) AS subscription_sequence_id
FROM
`moz-fx-data-shared-prod`.subscription_platform_derived.stripe_subscriptions_history_v1
WHERE
-- Only include the current history records and the last history records for previous plans.
(valid_to IS NULL OR plan_ended_at IS NOT NULL)
AND status NOT IN ("incomplete", "incomplete_expired")
),
stripe_subscriptions AS (
SELECT
user_id,
customer_id,
subscription_sequence_id AS subscription_id,
IF(
subscription_sequence_id != subscription_id,
subscription_id,
NULL
) AS original_subscription_id,
plan_id,
status,
synced_at AS event_timestamp,
IF(
(trial_end > TIMESTAMP(CURRENT_DATE) OR ended_at <= trial_end),
NULL,
COALESCE(plan_started_at, subscription_start_date)
) AS subscription_start_date,
--first subscription start date associated with the subscription id
IF(
(trial_end > TIMESTAMP(CURRENT_DATE) OR ended_at <= trial_end),
NULL,
subscription_start_date
) AS original_subscription_start_date,
IF(plan_started_at IS NOT NULL, "Plan Change", NULL) AS subscription_start_reason,
created,
trial_start,
trial_end,
canceled_at,
canceled_for_customer_at,
cancel_at,
cancel_at_period_end,
COALESCE(plan_ended_at, IF(ended_at < TIMESTAMP(CURRENT_DATE), ended_at, NULL)) AS ended_at,
IF(plan_ended_at IS NOT NULL, "Plan Change", NULL) AS ended_reason,
fxa_uid,
country,
country_name,
state,
user_registration_date,
provider,
plan_amount,
billing_scheme,
plan_currency,
plan_interval,
plan_interval_count,
plan_interval_timezone,
product_id,
product_name,
CONCAT(
plan_interval_count,
"-",
plan_interval,
"-",
plan_currency,
"-",
(plan_amount / 100)
) AS pricing_plan,
-- Stripe billing grace period is 7 day and Paypal is billed by Stripe
INTERVAL 7 DAY AS billing_grace_period,
has_refunds,
has_fraudulent_charges,
has_fraudulent_charge_refunds,
promotion_codes,
promotion_discounts_amount,
FROM
stripe_subscriptions_history
LEFT JOIN
standardized_country
USING (country)
LEFT JOIN
users
USING (fxa_uid)
WHERE
"guardian_vpn_1" IN UNNEST(stripe_subscriptions_history.product_capabilities)
OR "guardian_vpn_1" IN UNNEST(stripe_subscriptions_history.plan_capabilities)
),
apple_iap_subscriptions AS (
SELECT
users.user_id,
subplat.customer_id,
subplat.subscription_id,
subplat.original_subscription_id,
subplat.plan_id,
subplat.status,
subplat.event_timestamp,
subplat.subscription_start_date,
-- Until the upgrade event surfacing work, original_subscription_start_date is set to be NULL
CAST(NULL AS TIMESTAMP) AS original_subscription_start_date,
CAST(NULL AS STRING) AS subscription_start_reason,
subplat.created,
subplat.trial_start,
subplat.trial_end,
CAST(NULL AS TIMESTAMP) AS canceled_at,
CAST(NULL AS STRING) AS canceled_for_customer_at,
CAST(NULL AS TIMESTAMP) AS cancel_at,
subplat.cancel_at_period_end,
IF(
subplat.ended_at < TIMESTAMP(CURRENT_DATE),
subplat.ended_at,
CAST(NULL AS TIMESTAMP)
) AS ended_at,
subplat.ended_reason,
subplat.fxa_uid,
CAST(NULL AS STRING) AS country,
CAST(NULL AS STRING) AS country_name,
CAST(NULL AS STRING) AS state,
users.user_registration_date,
subplat.provider,
CAST(NULL AS INT64) AS plan_amount,
CAST(NULL AS STRING) AS billing_scheme,
CAST(NULL AS STRING) AS plan_currency,
subplat.plan_interval,
subplat.plan_interval_count,
subplat.plan_interval_timezone,
subplat.product_id,
"Mozilla VPN" AS product_name,
CONCAT(subplat.plan_interval_count, "-", subplat.plan_interval, "-", "apple") AS pricing_plan,
subplat.billing_grace_period,
CAST(NULL AS BOOL) AS has_refunds,
CAST(NULL AS BOOL) AS has_fraudulent_charges,
CAST(NULL AS BOOL) AS has_fraudulent_charge_refunds,
subplat.promotion_codes,
CAST(NULL AS INT64) AS promotion_discounts_amount,
FROM
`moz-fx-data-shared-prod`.subscription_platform_derived.apple_subscriptions_v1 AS subplat
LEFT JOIN
users
USING (fxa_uid)
WHERE
subplat.product_id = "org.mozilla.ios.FirefoxVPN"
AND subplat.fxa_uid IS NOT NULL
),
google_iap_subscriptions AS (
SELECT
users.user_id,
subscriptions.customer_id,
subscriptions.subscription_id,
subscriptions.original_subscription_id,
subscriptions.plan_id,
CAST(NULL AS STRING) AS status,
subscriptions.event_timestamp,
subscriptions.subscription_start AS subscription_start_date,
-- Until the upgrade event surfacing work, original_subscription_start_date is set to be NULL
CAST(NULL AS TIMESTAMP) AS original_subscription_start_date,
CAST(NULL AS STRING) AS subscription_start_reason,
subscriptions.created,
subscriptions.trial_start,
subscriptions.trial_end,
CAST(NULL AS TIMESTAMP) AS canceled_at,
subscriptions.canceled_for_customer_at,
CAST(NULL AS TIMESTAMP) AS cancel_at,
CAST(NULL AS BOOL) AS cancel_at_period_end,
IF(
subscriptions.in_billing_grace_period,
-- Google subscriptions in grace period have not ended
CAST(NULL AS TIMESTAMP),
IF(
subscriptions.subscription_end < TIMESTAMP(CURRENT_DATE),
subscriptions.subscription_end,
CAST(NULL AS TIMESTAMP)
)
) AS ended_at,
CAST(NULL AS STRING) AS ended_reason,
subscriptions.fxa_uid,
subscriptions.country,
standardized_country.country_name,
CAST(NULL AS STRING) AS state,
users.user_registration_date,
subscriptions.provider,
subscriptions.plan_amount,
CAST(NULL AS STRING) AS billing_scheme,
subscriptions.plan_currency,
subscriptions.plan_interval,
subscriptions.plan_interval_count,
subscriptions.plan_interval_timezone,
subscriptions.product_id,
"Mozilla VPN" AS product_name,
CONCAT(
subscriptions.plan_interval_count,
"-",
subscriptions.plan_interval,
"-",
subscriptions.plan_currency,
"-",
(subscriptions.plan_amount / 100)
) AS pricing_plan,
subscriptions.billing_grace_period,
CAST(NULL AS BOOL) AS has_refunds,
CAST(NULL AS BOOL) AS has_fraudulent_charges,
CAST(NULL AS BOOL) AS has_fraudulent_charge_refunds,
CAST(NULL AS ARRAY<STRING>) AS promotion_codes,
CAST(NULL AS INT64) AS promotion_discounts_amount,
FROM
`moz-fx-data-shared-prod`.subscription_platform_derived.google_subscriptions_v1 AS subscriptions
LEFT JOIN
standardized_country
USING (country)
LEFT JOIN
users
USING (fxa_uid)
WHERE
subscriptions.product_id = "org.mozilla.firefox.vpn"
),
all_subscriptions AS (
SELECT
*
FROM
stripe_subscriptions
UNION ALL
SELECT
*
FROM
apple_iap_subscriptions
UNION ALL
SELECT
*
FROM
google_iap_subscriptions
),
subscription_last_touch_attributions AS (
-- Select the latest attribution before the subscription originally started.
SELECT
subscriptions.subscription_id,
ARRAY_AGG(
fxa_attributions.attribution
ORDER BY
fxa_attributions.attribution.timestamp DESC
LIMIT
1
)[ORDINAL(1)].*
FROM
all_subscriptions AS subscriptions
JOIN
fxa_attributions
ON subscriptions.fxa_uid = fxa_attributions.fxa_uid
AND COALESCE(
subscriptions.original_subscription_start_date,
subscriptions.subscription_start_date,
subscriptions.trial_start
) >= fxa_attributions.attribution.timestamp
GROUP BY
subscription_id
),
all_subscriptions_with_attribution AS (
SELECT
subscriptions.*,
attributions.timestamp AS attribution_timestamp,
attributions.entrypoint_experiment,
attributions.entrypoint_variation,
attributions.utm_campaign,
attributions.utm_content,
attributions.utm_medium,
attributions.utm_source,
attributions.utm_term,
mozfun.norm.vpn_attribution(
utm_campaign => attributions.utm_campaign,
utm_content => attributions.utm_content,
utm_medium => attributions.utm_medium,
utm_source => attributions.utm_source
).*
FROM
all_subscriptions AS subscriptions
LEFT JOIN
subscription_last_touch_attributions AS attributions
ON subscriptions.subscription_id = attributions.subscription_id
),
all_subscriptions_with_end_date AS (
SELECT
*,
IF(
customer_id IS NOT NULL,
MIN(subscription_start_date) OVER (PARTITION BY customer_id),
subscription_start_date
) AS customer_start_date,
COALESCE(ended_at, TIMESTAMP(CURRENT_DATE)) AS end_date,
FROM
all_subscriptions_with_attribution
)
SELECT
* REPLACE (
CASE
WHEN subscription_start_date IS NULL
THEN NULL
WHEN subscription_start_reason IS NOT NULL
THEN subscription_start_reason
WHEN trial_start IS NOT NULL
THEN "Converted Trial"
WHEN DATE(subscription_start_date) = DATE(customer_start_date)
THEN "New"
ELSE "Resurrected"
END AS subscription_start_reason,
CASE
WHEN ended_at IS NULL
THEN NULL
WHEN ended_reason IS NOT NULL
THEN ended_reason
WHEN provider = "Apple Store"
THEN "Cancelled by IAP"
WHEN canceled_for_customer_at IS NOT NULL
OR cancel_at_period_end
THEN "Cancelled by Customer"
ELSE "Payment Failed"
END AS ended_reason
),
mozfun.norm.diff_months(
start => DATETIME(subscription_start_date, plan_interval_timezone),
`end` => DATETIME(end_date, plan_interval_timezone),
grace_period => billing_grace_period,
inclusive => FALSE
) AS months_retained,
mozfun.norm.diff_months(
start => DATETIME(
COALESCE(original_subscription_start_date, subscription_start_date),
plan_interval_timezone
),
`end` => DATETIME(end_date, plan_interval_timezone),
grace_period => billing_grace_period,
inclusive => FALSE
) AS original_subscription_months_retained,
mozfun.norm.diff_months(
start => DATETIME(subscription_start_date, plan_interval_timezone),
`end` => DATETIME(TIMESTAMP(CURRENT_DATE), plan_interval_timezone),
grace_period => billing_grace_period,
inclusive => FALSE
) AS current_months_since_subscription_start,
mozfun.norm.diff_months(
start => DATETIME(
COALESCE(original_subscription_start_date, subscription_start_date),
plan_interval_timezone
),
`end` => DATETIME(TIMESTAMP(CURRENT_DATE), plan_interval_timezone),
grace_period => billing_grace_period,
inclusive => FALSE
) AS current_months_since_original_subscription_start,
FROM
all_subscriptions_with_end_date