Firebase Extensions

Firebase extensions are third party functionalities which we can easily add to our application. In this code lab we shall add an extension which will automatically. For this code lab we'll assume you have already created a firebase project. You can view code lab 1 for a guide on how to do that. This codelab will use the same project from code lab1.

Go to the firebase console of your project and navigate to the database then click "create database".

Next set the rules to production mode

Then leave the default location and finish.

Next we shall set security rules to determine how writes can be made to the database. Because we want to receive public feedback we open the messages collection to public writes.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    match /messages/{message} {
      allow write: if true;
    }
    
  }
}

Then press publish.

Your firestore should now be initialized.

Click the following link to open the project workspace in gitpod.

Open Gitpod Workspace

After the workspace loads we login to the firebase cli with the following command

firebase login --no-localhost

Then we initialize the cli only enabling hosting.

firebase init

First we need to create a contact us form. This form will send the data to a firebase collection.

In this code lab we use bootstrap material already included on the page to style our User Interface.

Task 2.1

Add the following markup to index.html after the nav element.

<main class="container">
    <div class="row">
        <div class="col col-sm-12" id="projects">
            <form id="contactForm">
                <div class="form-group">
                    <label for="name">Name</label>
                    <input type="text" class="form-control" name="name" placeholder="Your name">
                </div>
                <div class="form-group">
                    <label for="email">Email address</label>
                    <input type="email" class="form-control" name="email" placeholder="name@example.com">
                </div>
                <div class="form-group">
                    <label for="message">Message</label>
                    <textarea class="form-control" name="message" rows="3"></textarea>
                </div>
                <div class="form-group">
                    <input type="submit" value="Submit" class="btn btn-primary" >
                </div>
            </form>
        </div>
    </div>
</main>

Here we used the classes of bootstrap material to style the form. The form is given an id of "contactForm" and has three input fields named ‘name', ‘email' and ‘message' and a submit button.

Task 2.2

Next we want to add the firebase sdk to our project just as we did in codelab 1. Update index.html adding the following before the main.js script tag :

<script src="/__/firebase/7.14.1/firebase-app.js"></script>
<script src="/__/firebase/7.14.2/firebase-firestore.js"></script>
<script src="/__/firebase/init.js"></script>
<!-- main.js comes after -->

Task 2.3

Finally we add some javascript which would take the data from the form and send it to firebase. Add the following to main.js

const db = firebase.firestore();//get firestore object after initializing firebase


async function sendToFirestore(event){
    event.preventDefault();//prevents the default html5 form submit which redirects the page
    
    const form = event.target;//get the form element from the event
    const fields = form.elements;//get the form fields form the form

    const data = {
        "name"    : fields["name"].value,
        "email"   : fields["email"].value,
        "message" : fields["message"].value
    }

    console.log(data);
    const documentRef = await db.collection("messages").add(data);//send the data to firebase

    console.log("Message added with id: ", documentRef.id);
    
    alert("Message Received!");
    form.reset();//reset the form

}


//attach sendToFirestore function to the submit event of contactFOrm
document.forms["contactForm"].addEventListener('submit', sendToFirestore);

In this snippet we do the following:

  1. Prevent the page redirect of the page submit
  2. Extract the data from the form
  3. Add the data to the message collection in firebase
  4. Reset the form
  5. Attach the sendToFIrebase function to the submit event of the form

After submitting the form the "Message Received" alert should appear. Now return to the firebase console and navigate to the database. You should see the data from the form.

Navigate to extension in the firebase console. Then scroll to the trigger email extension then click install.

Then click next, upgrade project, next. Firebase extensions require a paid pay as you go account however you won't be charged for your first 1 million invocations.

Next set the following to configure the extensions.

We configure the extension to pull messages from the messages collection in the database. We also need to provide credentials for an email account which has smtp access enabled. We also set the template collection to handlebar which will be explained later. Then click "Install Extension"

After the extension installs we can then manage the extension from the firebase console.

You can then view an explainer of how to use the extension.

To trigger emails from firestore we need to restructure the data in our messages collection to store details such as a to email address, cc address and a message field which can take a subject and html body.

Task 5

Update sendToFirestore() in main.js as follows.

async function sendToFirestore(event){
    event.preventDefault();//prevents the default html5 form submit which redirects the page
    
    const form = event.target;//get the form element from the event
    const fields = form.elements;//get the form fields form the form

    const name = fields["name"].value;
    const email = fields["email"].value;
    const message = fields["message"].value;

    let data = {
        to: ['receiver@mail.com'],
        cc: [ email ],
        message: {
            subject: `New contact from ${name}`,
            html:`
                <div>
                    <h2>Message from ${name}</h2>
                    <p>${message}</p>
                </div>
            `
        }
    };

    console.log(data);
    const documentRef = await db.collection("messages").add(data);//send the data to firebase

    console.log("Message added with id: ", documentRef.id);
    
    alert("Message Received!");
    form.reset();//reset the form

}

We restructured the data to send the email to a specific email address but cc the address given in the form. The body of the email shows the name and message from the form.

If your extension credentials checks out the receiver email account should receive an email from the email address given in the firebase extension configuration.

And that's how you can add automatic email notifications to your application using firebase extensions.

References & Additional Reading

Trigger Email Extension