
Implement a server-side verified reward ads and digital coins system using AdMob, backed by MongoDB Atlas, with user permissions, consent policy integration, and production deployment.
Create a new android studio project with a compose activity for reward system app, and set up a compose bom with dependencies like lifecycle, splash, navigation, ads, and UMP consent.
Define a four-screen android ad reward navigation graph using a sealed screen class with unique routes, and a final screen that accepts a user id for server-side verification.
This is a Test Ad ID that you need to add in your AndroidManifest.xml file. This is needed or otherwise you'll get a compile-time error when you launch the app:
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />
Configure Google authentication via a Google Cloud project and MongoDB Atlas, create Android and Web OAuth credentials, enable device sync, and set custom JWT authentication to manage user coins.
Implement sign in with google to authenticate users, log the token id, and store user data in a realm and mongodb atlas with a user model.
Persist user information locally in an Android app using data store and Dagger Hilt; define a persisted user model, implement save/read operations, and inject them into the authentication flow.
Implement an alert dialog on the authentication screen to handle Google sign-in errors when Google account not found, guiding users to enable sign in prompts via a browser link.
exports = async function(authEvent) {
const user = authEvent.user;
const myUserCollection = context.services.get("mongodb-atlas").db("mydb").collection("MyUser");
try {
const existingUser = await myUserCollection.findOne({ ownerId: user.id });
if (!existingUser) {
const newUser = {
ownerId: user.id,
coins: 0,
name: user.data.firstName,
email: user.data.email,
picture: user.data.picture
};
const result = await myUserCollection.insertOne(newUser);
console.log(result)
if (result.insertedId) {
console.log(newUser)
return newUser;
} else {
console.log("Insert failed.");
return null;
}
} else {
console.log("User already exists.");
return null;
}
} catch (error) {
console.error("Error:", error);
return null;
}
};
Implement dynamic start destination by reading a persisted user from the data store in a launched effect, then navigate from the splash screen to the home screen when data exists.
Read and display user information on the home screen by reading from MongoDB, using a view model, and showing a profile card with a photo, name, and email.
Observe coins updating in real time by adding two text elements below the profile card and using MongoDB’s device sync; a back end server updates after ad verification.
Add a top-bar overflow menu with logout and settings, show a confirmation alert on logout, then clean up the data store and reset MongoDB realm before navigating back to authentication.
Implement ad consent handling with a Google Umwpe workaround, read shared preferences to detect consent, and add a settings view toggle that re-prompts and updates the ad configuration.
Enable ad consent for users in other countries by storing a boolean in data store, update the settings with a toggle and a Hilt-annotated view model, removing the consent dialog.
exports = async function(changeEvent) { try {
if (changeEvent.operationType === "insert") {
const serviceName = "mongodb-atlas";
const databaseName = "mydb";
const myUserCol = "MyUser"
const rewardCol = "Reward"
const ownerId = changeEvent.fullDocument.ownerId
const title = changeEvent.fullDocument.title
const myUserCollection = context.services.get(serviceName).db(databaseName).collection(myUserCol);
const rewardCollection = context.services.get(serviceName).db(databaseName).collection(rewardCol);
const reward = await rewardCollection.findOne({ title: title});
const updateQuery = { ownerId: ownerId };
const updateCoins = { $inc: { coins: -reward.coins } };
await myUserCollection.updateOne(updateQuery, updateCoins);
}
} catch(err) {
console.log("error performing mongodb write: ", err.message);
}
};
In this course I'm gonna teach you how to implement a Reward ad/Digital Coins System in your app with a Server-Side Verification (SSV). This same approach I've used in my own app to allow users to earn digital coins by viewing ads. In return, users can spend those coins, to redeem certain rewards that you want to provide.
We will use:
Admob mobile advertising platform which is developed by Google, to display a reward type of ad in our application. We will configure it to accept a server-side verification.
Google's User Messaging Platform (UMP) to handle the new European Consent Policy. Because if you don't implement it, users from over 30 countries will be able to suspend your ads and reduce a huge amount of money that you can potentially earn.
MongoDB Atlas to host the database where we will store all information about the users and their digital coins. We will handle user and admin permissions, collection schemas, network access list, authentication and database triggers, custom functions and more.
Our own Backend Server which will be used to validate reward ads and add Coins to our users. The server itself should receive requests from the Admob SDK, when a callback fires up after a user successfully completes a task of viewing an ad. That adds an extra layer of security by processing and verifying user actions on the server rather than solely relying on client-side verification. This reduces the risk of manipulation or tampering by malicious users who may attempt to manipulate the client-side verification process to fraudulently claim rewards.
And at the end we will deploy our Backend server so that we can use it in a production as well.
Bottom line, quite interesting topic that opens the door for monetization in your app.