Skip to main content

🌐 InstaSites Notifications

📖 Overview

The InstaSites Notifications module handles notifications for the InstaSites website builder product, specifically monitoring build failures and completion status for customer websites.

Environment Flag: INSTASITES_ENABLED=true

Trigger Types:

  • Change Stream on InstaSitesBuildStatus collection (build failures)
  • Change Stream on InstaSitesViewedStatus collection (site view tracking)

Notification Types: bell (FCM), browser push
Location: notifications/services/instasites/

🏗️ Architecture

System Flow

graph TB
subgraph "Triggers"
BUILD[Build Failure<br/>Status Insert]
VIEW[Site Viewed<br/>Status Insert]
end

subgraph "Processing"
DETECT1[Detect Build Failure]
DETECT2[Detect Site Viewed]
FETCH[Fetch User & Domain]
VERIFY[Verify Preferences]
CREATE[Create Notifications]
end

subgraph "Delivery"
BELL[Bell Notification]
BROWSER[Browser Push]
end

BUILD --> DETECT1
VIEW --> DETECT2
DETECT1 --> FETCH
DETECT2 --> FETCH
FETCH --> VERIFY
VERIFY --> CREATE
CREATE --> BELL
CREATE --> BROWSER

⚙️ Configuration

Environment Variables

# Module flag
INSTASITES_ENABLED=true # Enable InstaSites notifications

# External dependencies (inherited)
GENERAL_SOCKET=http://localhost:4000 # For bell notifications
FIREBASE_CREDENTIALS=... # For browser push

Change Stream Configuration

Build Failure Stream

const buildFailureStream = InstaSitesBuildStatus.watch(
[
{
$match: {
operationType: 'insert',
'fullDocument.status': 'failed',
},
},
],
{
fullDocument: 'updateLookup',
},
);

buildFailureStream.on('change', async data => {
await processFailedNotification(data);
});

Site Viewed Stream

const viewedStream = InstaSitesViewedStatus.watch(
[
{
$match: {
operationType: 'insert',
},
},
],
{
fullDocument: 'updateLookup',
},
);

viewedStream.on('change', async data => {
await processViewedNotification(data);
});

Stream Filters:

  • Build failure: Only insert operations with status: 'failed'
  • Site viewed: All insert operations for view tracking

📧 Notification Templates

1. Build Failed

Trigger: InstaSite build process fails
Type: bell, browser push
Recipients: Site creator

Notification Content:

{
title: "Instasite build failed",
body: "A instasite build is failed.",
click_action: "https://app.dashclicks.com/instasites/my-instasites",
module: "instasites",
type: "build_fail",
subType: "bell" // or "browser"
}

2. Site Viewed (Optional)

Trigger: Customer views their InstaSite
Type: bell, browser push
Recipients: Site creator

Notification Content:

{
title: "InstaSite viewed",
body: "Your InstaSite has been viewed by a customer",
click_action: "https://app.dashclicks.com/instasites/my-instasites",
module: "instasites",
type: "site_viewed",
subType: "bell" // or "browser"
}

🔍 Processing Logic

Build Failure Notification

// From services/instasites/failed-notifications.js
async function processFailedNotification(data) {
try {
const buildStatus = data.fullDocument;

// 1. Fetch user who created the site
const user = await User.findById(buildStatus.created_by);

if (!user) {
logger.warn({
message: 'User not found for InstaSite build failure',
build_status_id: buildStatus._id,
created_by: buildStatus.created_by,
});
return;
}

// 2. Get active domain for the account
const domainName = await getActiveDomain({
accountId: buildStatus.account_id?.toString(),
proto: true,
});

const baseURL = `${domainName}/instasites/my-instasites`;

// 3. Send bell notification
await processFCMv2({
verification: {
module: 'instasites',
type: 'build_fail',
subType: 'bell',
},
content: {
title: 'Instasite build failed',
body: 'A instasite build is failed.',
click_action: baseURL,
},
recipient: {
accountID: buildStatus.account_id,
users: [user._id],
},
user_check: true, // Verify user preferences
});

// 4. Send browser push notification
await processFCMv2({
verification: {
module: 'instasites',
type: 'build_fail',
subType: 'browser',
},
content: {
title: 'Instasite build failed',
body: 'A instasite build is failed.',
click_action: baseURL,
},
recipient: {
accountID: buildStatus.account_id,
users: [user._id],
},
user_check: true,
});

logger.info({
message: 'InstaSite build failure notification sent',
build_status_id: buildStatus._id,
user_id: user._id,
});
} catch (err) {
logger.error({
initiator: 'notification/instasite/failed-notification',
message: 'Error in instasite failed notification',
error: err,
});
}
}

Site Viewed Notification

// From services/instasites/viewed-notifications.js
async function processViewedNotification(data) {
try {
const viewedStatus = data.fullDocument;

// 1. Fetch site details
const site = await InstaSite.findById(viewedStatus.site_id);

if (!site) {
logger.warn({
message: 'InstaSite not found for viewed notification',
site_id: viewedStatus.site_id,
});
return;
}

// 2. Fetch site creator
const user = await User.findById(site.created_by);

if (!user) {
logger.warn({
message: 'User not found for site viewed notification',
user_id: site.created_by,
});
return;
}

// 3. Get active domain
const domainName = await getActiveDomain({
accountId: site.account_id?.toString(),
proto: true,
});

const baseURL = `${domainName}/instasites/my-instasites`;

// 4. Send notifications
await processFCMv2({
verification: {
module: 'instasites',
type: 'site_viewed',
subType: 'bell',
},
content: {
title: 'InstaSite viewed',
body: 'Your InstaSite has been viewed by a customer',
click_action: baseURL,
},
recipient: {
accountID: site.account_id,
users: [user._id],
},
user_check: true,
});

await processFCMv2({
verification: {
module: 'instasites',
type: 'site_viewed',
subType: 'browser',
},
content: {
title: 'InstaSite viewed',
body: 'Your InstaSite has been viewed by a customer',
click_action: baseURL,
},
recipient: {
accountID: site.account_id,
users: [user._id],
},
user_check: true,
});

logger.info({
message: 'InstaSite viewed notification sent',
site_id: site._id,
user_id: user._id,
});
} catch (err) {
logger.error({
initiator: 'notification/instasite/viewed-notification',
message: 'Error in site viewed notification',
error: err,
});
}
}

🚨 Error Handling

Change Stream Management

// Graceful shutdown
process.on('SIGINT', async () => {
logger.log({
initiator: 'notifications/instasites',
message: 'Closing InstaSites streams',
});

await buildFailureStream.close();
await viewedStream.close();
process.exit(0);
});

// Stream error handling
buildFailureStream.on('error', error => {
logger.error({
initiator: 'notifications/instasites/failed-stream',
message: 'Change stream error',
error: error,
});
});

viewedStream.on('error', error => {
logger.error({
initiator: 'notifications/instasites/viewed-stream',
message: 'Change stream error',
error: error,
});
});

💡 Examples

Example 1: Build Failure

Trigger Event:

// InstaSitesBuildStatus insert
{
operationType: 'insert',
fullDocument: {
_id: ObjectId("507f1f77bcf86cd799439011"),
account_id: ObjectId("507f1f77bcf86cd799439012"),
site_id: ObjectId("507f1f77bcf86cd799439013"),
created_by: ObjectId("507f1f77bcf86cd799439014"),
status: "failed",
error_message: "Template compilation error: Missing required asset",
build_duration: 45,
created_at: new Date("2025-10-13T14:30:00Z")
}
}

Resulting Notifications:

  1. Bell - "Instasite build failed"
  2. Browser - Same content via web push

User Action: Click notification to navigate to InstaSites dashboard

Example 2: Site Viewed

Trigger Event:

// InstaSitesViewedStatus insert
{
operationType: 'insert',
fullDocument: {
_id: ObjectId("507f1f77bcf86cd799439011"),
site_id: ObjectId("507f1f77bcf86cd799439013"),
viewer_ip: "192.168.1.100",
viewer_location: "New York, USA",
viewed_at: new Date("2025-10-13T15:00:00Z")
}
}

Resulting Notifications:

  1. Bell - "InstaSite viewed"
  2. Browser - "Your InstaSite has been viewed by a customer"

📈 Metrics

Key Metrics:

  • Build success rate: ~95%
  • Build failures per day: ~15
  • Average build time: 2 minutes
  • Site views per day: ~500

Monitoring:

// Build failures today
db.getCollection('instasites.build_status').count({
status: 'failed',
created_at: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) },
});

// Successful builds today
db.getCollection('instasites.build_status').count({
status: 'completed',
created_at: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) },
});

// Site views today
db.getCollection('instasites.viewed_status').count({
viewed_at: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) },
});

// Notifications sent
db.getCollection('notifications.queue').count({
origin: 'instasites',
created_at: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) },
});

🔧 Troubleshooting

Issue: Build failure notifications not received

Symptoms: Site build fails but no notification sent

Diagnosis:

// 1. Check build status record
db.getCollection('instasites.build_status').findOne({
site_id: ObjectId('site_id'),
status: 'failed',
});

// 2. Verify user exists
db.getCollection('users').findOne({
_id: ObjectId('user_id'),
});

// 3. Check change stream is running
// Look for log: "InstaSites failed stream started"

Solutions:

  • Ensure INSTASITES_ENABLED=true
  • Verify MongoDB replica set configuration
  • Check user notification preferences for instasites module
  • Verify Firebase credentials

Issue: Duplicate notifications

Symptoms: Multiple notifications for same build failure

Cause: Change stream may replay events if not properly acknowledged

Solutions:

  1. Implement deduplication in processing logic
  2. Check for existing notification before creating new one
  3. Use resume tokens properly in change stream

Issue: Generic error message

Symptoms: Notification says "build failed" but no details

Enhancement: Consider including error details in notification body:

// Enhanced notification
{
title: 'Instasite build failed',
body: `Build failed: ${buildStatus.error_message}`,
click_action: baseURL
}

🔗 Integration Points

InstaSites Product Integration

  • Build Pipeline - Monitors build process status
  • Template Engine - Tracks template compilation errors
  • Asset Management - Detects missing asset errors
  • Domain Configuration - Links to customer domain setup

Queue Manager Integration

InstaSites builds are typically processed by Queue Manager:

  • Build jobs queued for processing
  • Status updates written to InstaSitesBuildStatus
  • Failures trigger notification change stream

Module Type: Change Stream
Environment Flag: INSTASITES_ENABLED
Dependencies: MongoDB (replica set), Firebase (FCM)
Notification Channels: Bell, Browser Push (no email)
Primary Use Case: Website builder status monitoring
Status: Active - critical for product health monitoring

💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM