diff --git a/website/api/controllers/create-or-update-one-newsletter-subscription.js b/website/api/controllers/create-or-update-one-newsletter-subscription.js index addf3911f0..6585257b36 100644 --- a/website/api/controllers/create-or-update-one-newsletter-subscription.js +++ b/website/api/controllers/create-or-update-one-newsletter-subscription.js @@ -13,12 +13,6 @@ module.exports = { required: true, }, - subscribeTo: { - type: 'string', - required: true, - description: 'The type of content that this user is changing their subscription for', - isIn: ['releases'] - } }, @@ -28,24 +22,39 @@ module.exports = { description: 'A user has successfully changed their subscription to the Fleet newsletter' }, + invalidEmailDomain: { + description: 'This email address is on a denylist of domains and was not delivered.', + responseType: 'badRequest' + }, + + }, - fn: async function ({emailAddress, subscribeTo}) { - + fn: async function ({emailAddress}) { + let emailDomain = emailAddress.split('@')[1]; + if(_.includes(sails.config.custom.bannedEmailDomainsForWebsiteSubmissions, emailDomain.toLowerCase())){ + throw 'invalidEmailDomain'; + } await NewsletterSubscription.create({emailAddress: emailAddress}) .tolerate('E_UNIQUE'); - let argins = {}; + await NewsletterSubscription.updateOne({emailAddress: emailAddress}).set({isSubscribedToReleases: true}); - // Update the NewsletterSubscription record for this email address with `isSubscribedTo____` boolean attributes based on the subscribeTo input - if(subscribeTo === 'releases') { - argins.isSubscribedToReleases = true; - } - // FUTURE: Handle more types of subscribeTo inputs - await NewsletterSubscription.updateOne({emailAddress: emailAddress}).set(argins); + sails.helpers.salesforce.updateOrCreateContactAndAccount.with({ + emailAddress: emailAddress, + contactSource: 'Website - Newsletter', + description: `Subscribed to the Fleet newsletter`, + psychologicalStage: '3 - Intrigued', + psychologicalStageChangeReason: 'Website - Newsletter', + }).exec((err)=>{// Use .exec() to run the salesforce helpers in the background. + if(err) { + sails.log.warn(`Background task failed: When a user signed up for a newsletter, a lead/contact could not be updated in the CRM for this email address: ${emailAddress}.`, err); + } + return; + }); // All done. return; diff --git a/website/api/controllers/unsubscribe-from-all-newsletters.js b/website/api/controllers/unsubscribe-from-all-newsletters.js index cb8d288524..978b8de985 100644 --- a/website/api/controllers/unsubscribe-from-all-newsletters.js +++ b/website/api/controllers/unsubscribe-from-all-newsletters.js @@ -35,7 +35,7 @@ module.exports = { sails.log.warn('When a user tried to unsubscribe from the Fleet newsletter, a NewsletterSubscription record for the specified email address ('+ emailAddress +') could not be found.'); } // All done. - return; + return this.res.redirect('/#unsubscribed'); } diff --git a/website/api/helpers/salesforce/update-or-create-contact-and-account.js b/website/api/helpers/salesforce/update-or-create-contact-and-account.js index 41ebd76efe..0a820c109a 100644 --- a/website/api/helpers/salesforce/update-or-create-contact-and-account.js +++ b/website/api/helpers/salesforce/update-or-create-contact-and-account.js @@ -14,8 +14,8 @@ module.exports = { linkedinUrl: { type: 'string' }, // Set… - firstName: { type: 'string', required: true }, - lastName: { type: 'string', required: true }, + firstName: { type: 'string'}, + lastName: { type: 'string'}, organization: { type: 'string' }, description: { type: 'string' }, primaryBuyingSituation: { type: 'string' }, @@ -39,6 +39,7 @@ module.exports = { isIn: [ 'Website - Contact forms', 'Website - Sign up', + 'Website - Newsletter', ], }, getStartedResponses: { @@ -237,8 +238,8 @@ module.exports = { .create({ AccountId: salesforceAccountId, OwnerId: salesforceAccountOwnerId, - FirstName: firstName, - LastName: lastName, + FirstName: firstName ? firstName : '?', + LastName: lastName ? lastName : '?', ...valuesToSet, }); // console.log(`Created ${newContactRecord.id}`); diff --git a/website/assets/js/pages/homepage.page.js b/website/assets/js/pages/homepage.page.js index b9bfc560b4..e6e40c8c93 100644 --- a/website/assets/js/pages/homepage.page.js +++ b/website/assets/js/pages/homepage.page.js @@ -4,7 +4,20 @@ parasails.registerPage('homepage', { // ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝ data: { modal: undefined, - selectedCategory: 'mdm' + selectedCategory: 'mdm', + formData: { /* … */ }, + formErrors: { /* … */ }, + + // Form rules + formRules: { + emailAddress: {isEmail: true, required: true}, + }, + + syncing: false, + + // Server error state for the form + cloudError: '', + cloudSuccess: false, }, // ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗ @@ -33,6 +46,13 @@ parasails.registerPage('homepage', { closeModal: function() { this.modal = undefined; }, - + submittedNewsletterForm: async function() { + // Show the success message. + this.cloudSuccess = true; + this.formData = {}; + await setTimeout(()=>{ + this.cloudSuccess = false; + }, 10000); + }, } }); diff --git a/website/assets/styles/pages/homepage.less b/website/assets/styles/pages/homepage.less index a1846af704..12f09a1e93 100644 --- a/website/assets/styles/pages/homepage.less +++ b/website/assets/styles/pages/homepage.less @@ -708,7 +708,61 @@ } } } - + [purpose='newsletter-banner'] { + width: 660px; + margin-left: auto; + margin-right: auto; + margin-top: 32px; + margin-bottom: 32px; + border-radius: 8px; + border: 1px solid #E2E4EA; + background: #F9FAFC; + display: block; + padding: 8px 8px 8px 16px; + input { + border-radius: 6px; + border: 1px solid var(--ui-fleet-blue-15, #E2E4EA); + background: var(--Core-White, #FFF); + display: flex; + width: 235px; + padding: 8px 15px; + align-items: center; + flex-shrink: 0; + align-self: stretch; + height: 37px; + margin-right: 10px; + } + p { + color: #515774; + margin-bottom: 0px; + font-size: 14px; + font-weight: 400; + line-height: 21px; + } + [purpose='subscribe-button'] { + color: #FFF; + text-align: center; + display: flex; + padding: 16px; + justify-content: center; + align-items: center; + gap: 4px; + align-self: stretch; + border-radius: 4px; + background: #FF5C83; + height: 37px; + width: 92px; + /* Body XS (bold) */ + font-family: Inter; + font-size: 12px; + font-style: normal; + font-weight: 700; + line-height: 18px; /* 150% */ + } + [purpose='newsletter-form-input']::placeholder { + font-size: 14px; + } + } [purpose='video-modal'] { [purpose='modal-dialog'] { width: 100%; @@ -1229,7 +1283,61 @@ } } } - + [purpose='newsletter-banner'] { + width: 100%; + margin-left: auto; + margin-right: auto; + border-radius: 8px; + border: 1px solid #E2E4EA; + background: #F9FAFC; + display: block; + padding: 16px; + margin-top: 24px; + margin-bottom: 24px; + input { + border-radius: 6px; + border: 1px solid #E2E4EA; + background: #FFF; + display: flex; + width: 100%; + padding: 8px 15px; + align-items: center; + flex-shrink: 0; + align-self: stretch; + height: 37px; + margin-right: 0px; + margin-bottom: 10px; + } + p { + color: #515774; + margin-bottom: 8px; + font-size: 14px; + font-weight: 400; + line-height: 21px; + } + [purpose='subscribe-button'] { + color: #FFF; + text-align: center; + display: flex; + padding: 16px; + justify-content: center; + align-items: center; + gap: 4px; + align-self: stretch; + border-radius: 4px; + background: #FF5C83; + height: 37px; + width: 100%; + font-family: Inter; + font-size: 12px; + font-style: normal; + font-weight: 700; + line-height: 18px; /* 150% */ + } + [purpose='newsletter-form-input']::placeholder { + font-size: 14px; + } + } [purpose='video-modal'] { [purpose='modal-dialog'] { max-width: 97vw; diff --git a/website/config/routes.js b/website/config/routes.js index 6d2e62bbe6..b3a51680bf 100644 --- a/website/config/routes.js +++ b/website/config/routes.js @@ -518,6 +518,7 @@ module.exports.routes = { 'GET /g': (req,res)=> { let originalQueryStringWithAmp = req.url.match(/\?(.+)$/) ? '&'+req.url.match(/\?(.+)$/)[1] : ''; return res.redirect(301, sails.config.custom.baseUrl+'/?meet-fleet'+originalQueryStringWithAmp); }, 'GET /test-fleet-sandbox': '/register', 'GET /unsubscribe': (req,res)=> { let originalQueryString = req.url.match(/\?(.+)$/) ? req.url.match(/\?(.+)$/)[1] : ''; return res.redirect(301, sails.config.custom.baseUrl+'/api/v1/unsubscribe-from-marketing-emails?'+originalQueryString);}, + 'GET /unsubscribe-from-newsletter': (req,res)=> { let originalQueryString = req.url.match(/\?(.+)$/) ? req.url.match(/\?(.+)$/)[1] : ''; return res.redirect(301, sails.config.custom.baseUrl+'/api/v1/unsubscribe-from-all-newsletters?'+originalQueryString);}, 'GET /tables': '/tables/account_policy_data', 'GET /imagine/launch-party': 'https://www.eventbrite.com/e/601763519887', 'GET /blackhat2023': 'https://github.com/fleetdm/fleet/tree/main/tools/blackhat-mdm', // Assets from @marcosd4h & @zwass Black Hat 2023 talk diff --git a/website/views/layouts/layout-email-newsletter.ejs b/website/views/layouts/layout-email-newsletter.ejs index 89411b0eef..82f07e08f2 100644 --- a/website/views/layouts/layout-email-newsletter.ejs +++ b/website/views/layouts/layout-email-newsletter.ejs @@ -15,7 +15,7 @@

© <%= (new Date()).getFullYear() %> Fleet Device Management Inc. All trademarks, service marks, and company names are the property of their respective owners.

-

You received this email because you’re subscribed to the Fleet newsletter. Unsubscribe

+

You received this email because you’re subscribed to the Fleet newsletter. Unsubscribe

diff --git a/website/views/pages/homepage.ejs b/website/views/pages/homepage.ejs index 63abf90f65..e297c790cb 100644 --- a/website/views/pages/homepage.ejs +++ b/website/views/pages/homepage.ejs @@ -405,6 +405,25 @@ <%/* Cloud city banner */%> +
+
+
+
+

Please enter a valid work email

+

Thanks for subscribing!

+

Curious? Get product updates and news

+
+ +
+ +
+
+ Subscribe +
+
+
+
+

Your email preferences have been updated.