Golang — Send Push notifications to apps using FCM

Explore how your mobile gets the notifications...
Mar 14 2022 · 3 min read

Introduction

“Craving a pizza? 🍕 💛 Order now and get $5 off !!”

“Hurry up!! You get a 50% discount on a purchase of a minimum Rs.1000/- 🎉 .”

We become more excited on seeing our screen blinking with alerts like the above.
Ever think about how it reaches your mobile? Push notification is behind the scenes.

When we heard the word push notification for the first time, we must have a thought about how can our mobile be recognized by someone so that they can notify us.

In this blog, we will explore how push notifications are sent using Golang and Firebase.



1. Basic Introduction to Firebase and a device token

The device token is the main contestant, responsible for pushing notifications. It’s not a fancy word, it’s simply an id that is unique for each device. When we install any application, our device’s unique token is being stored on their server, using which they can notify us.

Firebase is the tool, used for pushing notifications to apps/mobiles/tablets.
It provides a setting to configure the cloud messaging (FCM) service, which is used for push notifications.

Note: The Firebase config files used at the app side (google_services.json file for Android and GoogleService-Info.plist for iOS) and service_account key must be created for the same project from the Firebase console.

In this blog, we will explore how push notifications are sent using Golang and Firebase.

Here, I’m assuming that you’re familiar with Firebase and configured your project in the Firebase console. If not done already, do it as instructed.

Let’s jump to implementation.

2. Configure Firebase auth key

Required packages:

  1. firebase.google.com/go
  2. firebase.google.com/go/messaging

It’s always better to use sensitive stuff in an encrypted format. To serve that purpose I’ve stored the service account key in format base64 encoded as an environment variable.

The sample service account key,

{
  "type": "service_account",
  "project_id": "fir-realtime-db-demo-xxxxx",
  "private_key_id": "9b40ce1e420b06c04b4c8e543bebbd43cd731a22",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIxxxxxxxxxxxxxxw0BAQEFAASCBKgwggSkAgEAAoIBAQDllkqdmGaEonsN\nSsACNopfNG92Ak548KEqDPzw+xxxxxxxxyRMj97Zzz50dY2cUXHmvCwFQhq3KRh7\n9VAFeNflKSmlhw5+ch8eiI1hfqiIpS6Vl+TwVcOSY7SJZaWP9WjCo1inKL6Ur829\nTrKw/54i7TAocaund54ZEFnlhbk0UTSdRwtfzUny5A35EvPXlJazjvkhB5VuB/+F\nxxxxx/ffFcbeqMBwi1Vb9hi1zT2BXV22NUmBxZyp6VQwVfl34XTEZBAutqnVinqz\nuCtkxo+RiZY5yG4csOIkVqsFJ7NYnZE6iwYc1cFtp5IKmP7TZEchyje4crtJUZTf\nC3jyAbrnAgMBAAECggEAXxDBaspNQQSKkXFvWjs9RrjOon3IApoZEfF410rPozAp\nXcbAZBd6vpPrF4wJjD3JPTKTw8WgjFEu+z0T2oA0XYaS4SCwZrlYm2sNp94raRGE\n3ZqcyMuqhLZWbkIxsQ98RoQe1HCxoZ2+QnIQ2euujmXKeCTBYEHOrDAyGTErBDcH\nC98ikFKq/pd6B8ZJ9PbCYIth8KgxQBk+TsY2zEMZN0zM+7fDuTEr914OstT6t6Bb\nAle5aXTYxZNHsTY2mR/4Zo88k4JazEZzQ26BHmi5vdcez6uJuqwoRru0jWAoneTi\nrsUKhajwuKK2nwn+t5m4PABy4hU2VlrJhwPr0o0diQKBgQD42EIP9f9d1JC4OJ3b\nJsQdytTEzcKziF12VAj4rPjGbnWMoIc/6UHO3DNSJyrdZUjakZnaXBnJZkljXsE4\nhJck2s5U80elXH2eWw4qNzLuOxeHlNrZs6HzTzoG0ZGEC2ALvGy5USUsO+a3idsO\nEnklJTEwFdBtqx4MEXPsiyQptQKBgQDsMEcnn9QZLi3SMC+mEeOQDmq7Jm4KygL2\neHVDrq4P4X1Pn7IYqi7iJDxWKBzgCutxFwQOJiZdoedhAg1HhIZckT4VFvkwUHlS\nxu0l21OTFmu/2OUANNDoS8cJwOx+NDe23xbOk6PrVjD4OJtSRc5CDd+reSm1lwVq\nIHizueHDqwKBgD7RWNvunahyIJZgtHi+MIPU0CFeT+hCZFWaoSklgSeWetYlL/9S\nQuqVa98xRADfsKR8XPpihZ/x0lTjdqNt1TnYgn2vbEayMoPnOIwvowvAnw/648RR\nNHDXby6JeNJ8jKJpzoh5k4i3Fmb+xe2nfC2EVgZte1A0AkHJphnwhhCBAoGBAIgl\n5D5xIYBKYFtzL2RZl4Xo6ZlsM67AeCi/k0kqnmfFIckOU0logJIXNTis8sgrQ0Dz\ndYD6eM8sjwYaerEpMZKWnuTlU0uIeAdBaF6UKX72Q7JZQth1mZ7uX5O9xBWT4DHo\nM2ttK+ZyztOnPdGVL6pf+PkNZP+qSJK+mRVxJzT1AoGBANqiyWyH/D26pi1VvoMR\n1DyCWgJIa+Lm0CwR/CE0a1ATdSw1H96WvjEd5oHxlGER7Y9j0nfmvPabWFyNxKbu\nP8ly2aiFffAPKI2e2ZmXXrpcesj0IS5Uk5Mk/1hVwOtNLxGN/ayvk0DqwoIbvFEM\n2EzEYqr/xxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
  "client_email": "firebase-adminsdk-2zjoi@fir-realtime-db-demo-xxxxx.iam.gserviceaccount.com",
  "client_id": "105636361475399593303",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-2zjoi%40fir-realtime-db-demo-fc492.iam.gserviceaccount.com"
}

However, you also can use it in raw format, if security is not concerned.

Here, FIREBASE_AUTH_KEY contains a base64 encoded service account key.

First, let’s decode the service account key.

func getDecodedFireBaseKey() ([]byte, error) {
  
  fireBaseAuthKey := os.Getenv("FIREBASE_AUTH_KEY")
  
  decodedKey, err :=  base64.StdEncoding.DecodeString(fireBaseAuthKey)
  if err != nil {
     return nil, err
  }
  
  return decodedKey, nil
}

The above method will return the decoded service account key that will be used in the next step.

Retrieve the decoded key and Initialize the Firebase app, using the below code.

decodedKey, err := getDecodedFireBaseKey()
if err != nil {
   return err
}

opts :=  []option.ClientOption{option.WithCredentialsJSON(decodedKey)}

// Initialize firebase app
app, err := firebase.NewApp(context.Background(), nil, opts...)

if err != nil {
   log.Debug("Error in initializing firebase app: %s", err)
   return err
}

3. Initialize Firebase client

Create fcmClient for messaging(pushing notifications).

fcmClient, err := app.Messaging(context.Background())

if err != nil {
   return err
}

Finally, let’s write a code to send a notification.

4. Send Push notifications to a single device

response, err := fcmClient.Send(context.Background(), &messaging.Message{
  
  Notification: &messaging.Notification{
    Title: "Congratulations!!",
    Body: "You have just implement push notification",
  },
    Token: "sample-device-token", // it's a single device token
})

if err != nil {
     return err
}

The above code will send a push notification to a single device.

5. Send Push notifications to multiple devices

Consider a scenario if you want to notify multiple devices. It will be almost the same as we send a push notification to a single device, just need to replace fcmClient’s Send() method with SendMulticast().

response, err := fcmClient.SendMulticast(context.Background(), &messaging.MulticastMessage{
   Notification: &messaging.Notification{
     Title: "Congratulations!!",
     Body:  "You have just implemented push notification",
   },
   Tokens: deviceTokens, // it's an array of device tokens
  })

  if err != nil {
     return err
  }

log.Debug("Response success count : ", response.SuccessCount)
log.Debug("Response failure count : ", response.FailureCount)

Conclusion 

Yay !! You have implemented push notifications in your Golang project 🎊.
The response variable will contain the success count and failure count of sent notifications.

Find the full code at FCM with Golang. Invoke SendPushNotification() and boom !! Check a notification received in the application.

Meanwhile, you can also check to debug logs, as it has SuccessCount and failureCount. It will help to verify that notifications are pushed to how many tokens. In case of finding failureCount > 0, you must verify whether you’re giving a valid device token or not.

Keep notifying !!


Code, Build, Repeat.
Stay updated with the latest trends and tutorials in Android, iOS, and web development.
nidhi-d image
Nidhi Davra
Web developer@canopas | Gravitated towards Web | Eager to assist
nidhi-d image
Nidhi Davra
Web developer@canopas | Gravitated towards Web | Eager to assist
canopas-logo
We build products that customers can't help but love!
Get in touch

Talk to an expert
get intouch
Our team is happy to answer your questions. Fill out the form and we’ll get back to you as soon as possible
footer
Follow us on
2024 Canopas Software LLP. All rights reserved.