Firebase functions are a lot of fun. They allow you to uncouple business logic from your app.
Instead of running computationally expensive tasks on your server you can leverage firebase functions.
Here's a quick and dirty guide to using Firebase functions to send welcome emails.
var functions = require('firebase-functions')
var mailgun = require('mailgun-js')({apiKey, domain})
exports.sendWelcomeEmail = functions.database.ref('users/{uid}').onWrite(event => {
// only trigger for new users [event.data.previous.exists()]
// do not trigger on delete [!event.data.exists()]
if (!event.data.exists() || event.data.previous.exists()) {
return
}
var user = event.data.val()
var {email} = user
var data = {
from: 'app@app.com',
subject: 'Welcome!',
html: `<p>Welcome! ${user.name}</p>`,
'h:Reply-To': 'app@app.com',
to: email
}
mailgun.messages().send(data, function (error, body) {
console.log(body)
})
})
In the above code snippet, we use the transactional service Mailgun to send a welcome email. We're also using the node package mailgun-js, a wrapper around Mailgun's API.
Things to note:
apiKey
- this is your Mailgun API key.domain
- this is your domain name registered with Mailgun.Let's say that instead of sending one welcome email, we want to initiate a drip campaign.
In that case, we could write to our firebase database and update a field (like { subscribed: true }).
One thing to be mindful of is cloud functions that write to the same database path that triggers them. If you're not careful you might induce an infinite loop.
var functions = require('firebase-functions');
var admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase);
var mailgun = require('mailgun-js')({apiKey, domain})
exports.subscribeUser = functions.database.ref('users/{uid}').onWrite(event => {
var user = event.data.val()
var {uid} = event.params
// Exit if the user was deleted or the user is currently subscribed
if (!event.data.exists() || user.subscribed ) {
return
}
let members = {
address: user.email
}
var listId = 'your mailgun list id'
// Add the user to our mailgun list
return mailgun.lists(listId).members().add({members, subscribed: true}, function (err, body) {
if(!err) {
return admin.database().ref('users/' + uid + '/subscribed').set(true)
}
})
})
Here's what we did in the snippet above:
users/{uid}/subscribed
to true.Instead of using a transactional email service like Mailgun or Sendgrid, you could also use Mailchimp (which is just a user-friendly wrapper around Mailgun).
Here's how you'd use Mailchimp's API.
var fetch = require('isomorphic-fetch')
var btoa = require('btoa');
// POST /lists/{list_id}/members
// Add a new list member
function createFetch () {
var MAILCHIMP_API_KEY = ''
// NOTE: mailchimp's API uri differs depending on your location. us6 is the east coast.
var url = 'https://us6.api.mailchimp.com/3.0/lists/' + listId + '/members'
var method = 'POST'
var headers = {
'authorization': "Basic " + btoa('randomstring:' + MAILCHIMP_API_KEY),
'Accept': 'application/json',
'Content-Type': 'application/json'
}
var body = JSON.stringify({email_address: user.email, status: 'subscribed'})
return fetch(url, {
method,
headers,
body
}).then(resp => resp.json())
.then(resp => {
console.log(resp)
})
}
npm i btoa --save
for this to work. btoa binary encodes data to base 64-encoded ascii.npm i firebase-tools -g # install firebase cli
cd my-project
firebase login
firebase init functions
Now add your code to ./functions/index.js:
exports.sendEmail = ...
And npm install any required packages. (firebase-functions and firebase-admin should be preinstalled after firebase init functions).
Finally deploy with:
firebase deploy --only functions