mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-20 17:02:53 -04:00
marketing tracking (#1297)
This commit is contained in:
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"db_name": "MySQL",
|
"db_name": "MySQL",
|
||||||
"query": "\nINSERT INTO users\nSET\n token = ?,\n \n is_temporary = ?,\n \n username = ?,\n display_name = ?,\n\n username_is_generated = ?,\n username_is_not_customized = ?,\n\n email_address = ?,\n email_gravatar_hash = ?,\n\n email_confirmed = FALSE,\n email_confirmed_by_google = ?,\n email_is_synthetic = ?,\n \n was_eagerly_provisioned = ?,\n\n profile_markdown = ?,\n profile_rendered_html = ?,\n user_role_slug = ?,\n\n password_hash = ?,\n is_without_password = ?,\n\n maybe_feature_flags = ?,\n\n ip_address_creation = ?,\n ip_address_last_login = ?,\n ip_address_last_update = ?,\n\n maybe_source = ?,\n\n maybe_signup_method = ?,\n\n maybe_referral_url = ?\n ",
|
"query": "\nINSERT INTO users\nSET\n token = ?,\n \n is_temporary = ?,\n \n username = ?,\n display_name = ?,\n\n username_is_generated = ?,\n username_is_not_customized = ?,\n\n email_address = ?,\n email_gravatar_hash = ?,\n\n email_confirmed = FALSE,\n email_confirmed_by_google = ?,\n email_is_synthetic = ?,\n \n was_eagerly_provisioned = ?,\n\n profile_markdown = ?,\n profile_rendered_html = ?,\n user_role_slug = ?,\n\n password_hash = ?,\n is_without_password = ?,\n\n maybe_feature_flags = ?,\n\n ip_address_creation = ?,\n ip_address_last_login = ?,\n ip_address_last_update = ?,\n\n maybe_source = ?,\n\n maybe_signup_method = ?,\n\n maybe_referral_url = ?,\n maybe_landing_url = ?\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 23
|
"Right": 24
|
||||||
},
|
},
|
||||||
"nullable": []
|
"nullable": []
|
||||||
},
|
},
|
||||||
"hash": "08996721482fe897c2721298c04cf0eba5fcf1d04d57397b8afab3dd59feaa8c"
|
"hash": "3aacc0d270a9073ee5a38595cc32ab7793e0e8b9ce3ad81f554e7198fd0fd509"
|
||||||
}
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
-- noinspection SqlDialectInspectionForFile
|
||||||
|
-- noinspection SqlNoDataSourceInspectionForFile
|
||||||
|
-- noinspection SqlResolveForFile
|
||||||
|
|
||||||
|
ALTER TABLE users
|
||||||
|
DROP COLUMN maybe_landing_url;
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
-- noinspection SqlDialectInspectionForFile
|
||||||
|
-- noinspection SqlNoDataSourceInspectionForFile
|
||||||
|
-- noinspection SqlResolveForFile
|
||||||
|
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN maybe_landing_url VARCHAR(255) DEFAULT NULL;
|
||||||
@@ -222,8 +222,13 @@ CREATE TABLE users (
|
|||||||
was_eagerly_provisioned BOOLEAN NOT NULL DEFAULT false,
|
was_eagerly_provisioned BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
|
||||||
-- The referral URL the user arrived from when signing up.
|
-- The referral URL the user arrived from when signing up.
|
||||||
|
-- This helps us know what marketing is effective.
|
||||||
maybe_referral_url VARCHAR(255) DEFAULT NULL,
|
maybe_referral_url VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
|
-- The actual URL the user first arrived at when signing up, including query params.
|
||||||
|
-- This helps us know what marketing is effective.
|
||||||
|
maybe_landing_url VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
-- ========== MODERATION DETAILS ==========
|
-- ========== MODERATION DETAILS ==========
|
||||||
|
|
||||||
-- Different than deleted.
|
-- Different than deleted.
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ async fn seed_user(
|
|||||||
ip_address: "127.0.0.1",
|
ip_address: "127.0.0.1",
|
||||||
maybe_source: None,
|
maybe_source: None,
|
||||||
maybe_referral_url: None,
|
maybe_referral_url: None,
|
||||||
|
maybe_landing_url: None,
|
||||||
maybe_user_token: maybe_user_token.as_ref(),
|
maybe_user_token: maybe_user_token.as_ref(),
|
||||||
}).await.map_err(|err| anyhow!("err: {:?}", err))?;
|
}).await.map_err(|err| anyhow!("err: {:?}", err))?;
|
||||||
|
|
||||||
|
|||||||
+5
@@ -25,6 +25,10 @@ pub struct CreateAccountFromEmailPasswordArgs<'a> {
|
|||||||
/// If the browser doesn't send this parameter, we'll try the `referer` header.
|
/// If the browser doesn't send this parameter, we'll try the `referer` header.
|
||||||
pub maybe_referral_url: Option<String>,
|
pub maybe_referral_url: Option<String>,
|
||||||
|
|
||||||
|
/// The URL where the user landed when they first arrived, prior to navigation and signing up.
|
||||||
|
/// We can grab this from `window.location.href`.
|
||||||
|
pub maybe_landing_url: Option<String>,
|
||||||
|
|
||||||
/// In production code, send this as `None`.
|
/// In production code, send this as `None`.
|
||||||
/// Only provide an external user token for db integration tests and db seeding tools.
|
/// Only provide an external user token for db integration tests and db seeding tools.
|
||||||
/// This allows for knowing the user token a priori.
|
/// This allows for knowing the user token a priori.
|
||||||
@@ -68,6 +72,7 @@ pub async fn create_account_from_email_and_password(
|
|||||||
is_without_password: false,
|
is_without_password: false,
|
||||||
|
|
||||||
maybe_referral_url: args.maybe_referral_url,
|
maybe_referral_url: args.maybe_referral_url,
|
||||||
|
maybe_landing_url: args.maybe_landing_url,
|
||||||
|
|
||||||
// NB: This is just for testing.
|
// NB: This is just for testing.
|
||||||
maybe_user_token: args.maybe_user_token,
|
maybe_user_token: args.maybe_user_token,
|
||||||
|
|||||||
+1
@@ -59,6 +59,7 @@ pub async fn create_account_from_google_sso(
|
|||||||
|
|
||||||
// TODO: Necessary? We're not doing SSO for now.
|
// TODO: Necessary? We're not doing SSO for now.
|
||||||
maybe_referral_url: None,
|
maybe_referral_url: None,
|
||||||
|
maybe_landing_url: None,
|
||||||
|
|
||||||
// NB: This is just for testing.
|
// NB: This is just for testing.
|
||||||
maybe_user_token: None,
|
maybe_user_token: None,
|
||||||
|
|||||||
+2
@@ -27,6 +27,7 @@ pub struct CreateAccountFromStripeCheckoutArgs<'a> {
|
|||||||
pub ip_address: &'a str,
|
pub ip_address: &'a str,
|
||||||
pub maybe_source: Option<UserSignupSource>,
|
pub maybe_source: Option<UserSignupSource>,
|
||||||
pub maybe_referral_url: Option<String>,
|
pub maybe_referral_url: Option<String>,
|
||||||
|
pub maybe_landing_url: Option<String>,
|
||||||
|
|
||||||
/// Comma separated string of feature flags.
|
/// Comma separated string of feature flags.
|
||||||
pub maybe_feature_flags: Option<&'a str>,
|
pub maybe_feature_flags: Option<&'a str>,
|
||||||
@@ -70,6 +71,7 @@ pub async fn create_account_from_stripe_checkout(
|
|||||||
is_without_password: true,
|
is_without_password: true,
|
||||||
|
|
||||||
maybe_referral_url: args.maybe_referral_url,
|
maybe_referral_url: args.maybe_referral_url,
|
||||||
|
maybe_landing_url: args.maybe_landing_url,
|
||||||
|
|
||||||
// NB: This is just for testing.
|
// NB: This is just for testing.
|
||||||
maybe_user_token: None,
|
maybe_user_token: None,
|
||||||
|
|||||||
+19
-2
@@ -65,6 +65,10 @@ pub struct GenericCreateAccountArgs<'a> {
|
|||||||
/// If the browser doesn't send this parameter, we'll try the `referer` header.
|
/// If the browser doesn't send this parameter, we'll try the `referer` header.
|
||||||
pub maybe_referral_url: Option<String>,
|
pub maybe_referral_url: Option<String>,
|
||||||
|
|
||||||
|
/// The URL where the user landed when they first arrived, prior to navigation and signing up.
|
||||||
|
/// The browser can send `window.location.href` to the backend so we know how people are finding us.
|
||||||
|
pub maybe_landing_url: Option<String>,
|
||||||
|
|
||||||
/// In production code, send this as `None`.
|
/// In production code, send this as `None`.
|
||||||
/// Only provide an external user token for db integration tests and db seeding tools.
|
/// Only provide an external user token for db integration tests and db seeding tools.
|
||||||
/// This allows for knowing the user token a priori.
|
/// This allows for knowing the user token a priori.
|
||||||
@@ -86,6 +90,9 @@ pub async fn create_account_generic(
|
|||||||
const INITIAL_PROFILE_RENDERED_HTML : &str = "";
|
const INITIAL_PROFILE_RENDERED_HTML : &str = "";
|
||||||
const INITIAL_USER_ROLE: &str = "user";
|
const INITIAL_USER_ROLE: &str = "user";
|
||||||
|
|
||||||
|
let maybe_referral_url = sanitize_optional_url(args.maybe_referral_url);
|
||||||
|
let maybe_landing_url = sanitize_optional_url(args.maybe_landing_url);
|
||||||
|
|
||||||
let user_token = match args.maybe_user_token {
|
let user_token = match args.maybe_user_token {
|
||||||
None => UserToken::generate(),
|
None => UserToken::generate(),
|
||||||
Some(user_token) => user_token.clone(),
|
Some(user_token) => user_token.clone(),
|
||||||
@@ -131,7 +138,8 @@ SET
|
|||||||
|
|
||||||
maybe_signup_method = ?,
|
maybe_signup_method = ?,
|
||||||
|
|
||||||
maybe_referral_url = ?
|
maybe_referral_url = ?,
|
||||||
|
maybe_landing_url = ?
|
||||||
"#,
|
"#,
|
||||||
user_token.as_str(),
|
user_token.as_str(),
|
||||||
|
|
||||||
@@ -167,7 +175,8 @@ SET
|
|||||||
args.maybe_source.map(|s| s.to_str()),
|
args.maybe_source.map(|s| s.to_str()),
|
||||||
args.maybe_signup_method.map(|m| m.to_str()),
|
args.maybe_signup_method.map(|m| m.to_str()),
|
||||||
|
|
||||||
args.maybe_referral_url,
|
maybe_referral_url,
|
||||||
|
maybe_landing_url,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -207,3 +216,11 @@ SET
|
|||||||
user_id: record_id,
|
user_id: record_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trim, reject empty strings, and truncate to 255 characters.
|
||||||
|
fn sanitize_optional_url(value: Option<String>) -> Option<String> {
|
||||||
|
value
|
||||||
|
.map(|s| s.trim().to_string())
|
||||||
|
.filter(|s| !s.is_empty())
|
||||||
|
.map(|s| s.chars().take(255).collect())
|
||||||
|
}
|
||||||
|
|||||||
+4
-3
@@ -88,9 +88,9 @@ pub async fn stripe_artcraft_create_subscription_checkout_with_user_signup_handl
|
|||||||
http_request.headers().get("referer")
|
http_request.headers().get("referer")
|
||||||
.and_then(|v| v.to_str().ok())
|
.and_then(|v| v.to_str().ok())
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
})
|
});
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.map(|s| s.chars().take(255).collect::<String>());
|
let maybe_landing_url = request.maybe_landing_url.clone();
|
||||||
|
|
||||||
let maybe_user_metadata = internal_user_lookup
|
let maybe_user_metadata = internal_user_lookup
|
||||||
.lookup_user_from_http_request_and_mysql_connection(&http_request, &mut mysql_connection)
|
.lookup_user_from_http_request_and_mysql_connection(&http_request, &mut mysql_connection)
|
||||||
@@ -109,6 +109,7 @@ pub async fn stripe_artcraft_create_subscription_checkout_with_user_signup_handl
|
|||||||
&mut mysql_connection,
|
&mut mysql_connection,
|
||||||
&stripe_config,
|
&stripe_config,
|
||||||
maybe_referral_url,
|
maybe_referral_url,
|
||||||
|
maybe_landing_url,
|
||||||
).await?
|
).await?
|
||||||
},
|
},
|
||||||
Some(user_metadata) => {
|
Some(user_metadata) => {
|
||||||
|
|||||||
+2
@@ -29,6 +29,7 @@ pub (super) async fn user_creation_case(
|
|||||||
mysql_connection: &mut PoolConnection<MySql>,
|
mysql_connection: &mut PoolConnection<MySql>,
|
||||||
stripe_config: &ArtcraftStripeConfigWithClient,
|
stripe_config: &ArtcraftStripeConfigWithClient,
|
||||||
maybe_referral_url: Option<String>,
|
maybe_referral_url: Option<String>,
|
||||||
|
maybe_landing_url: Option<String>,
|
||||||
) -> Result<CreationPayload, CommonWebError> {
|
) -> Result<CreationPayload, CommonWebError> {
|
||||||
|
|
||||||
let mut transaction = mysql_connection.begin()
|
let mut transaction = mysql_connection.begin()
|
||||||
@@ -84,6 +85,7 @@ pub (super) async fn user_creation_case(
|
|||||||
ip_address: &ip_address,
|
ip_address: &ip_address,
|
||||||
maybe_source,
|
maybe_source,
|
||||||
maybe_referral_url: maybe_referral_url.clone(),
|
maybe_referral_url: maybe_referral_url.clone(),
|
||||||
|
maybe_landing_url: maybe_landing_url.clone(),
|
||||||
},
|
},
|
||||||
Transactor::for_transaction(&mut transaction),
|
Transactor::for_transaction(&mut transaction),
|
||||||
).await;
|
).await;
|
||||||
|
|||||||
+4
-3
@@ -209,9 +209,9 @@ pub async fn create_account_handler(
|
|||||||
http_request.headers().get("referer")
|
http_request.headers().get("referer")
|
||||||
.and_then(|v| v.to_str().ok())
|
.and_then(|v| v.to_str().ok())
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
})
|
});
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.map(|s| s.chars().take(255).collect::<String>());
|
let maybe_landing_url = request.maybe_landing_url.clone();
|
||||||
|
|
||||||
let create_account_result = create_account_from_email_and_password(
|
let create_account_result = create_account_from_email_and_password(
|
||||||
&mysql_pool,
|
&mysql_pool,
|
||||||
@@ -224,6 +224,7 @@ pub async fn create_account_handler(
|
|||||||
ip_address: &ip_address,
|
ip_address: &ip_address,
|
||||||
maybe_source,
|
maybe_source,
|
||||||
maybe_referral_url,
|
maybe_referral_url,
|
||||||
|
maybe_landing_url,
|
||||||
maybe_user_token: None, // NB: This parameter is for internal testing only
|
maybe_user_token: None, // NB: This parameter is for internal testing only
|
||||||
}
|
}
|
||||||
).await;
|
).await;
|
||||||
|
|||||||
Reference in New Issue
Block a user