Platform Announcements
Communicate important information to users through platform-wide announcements and notifications.
Overview
Platform announcements allow administrators to:
- Notify users of new features
- Announce maintenance windows
- Share important updates
- Communicate policy changes
- Celebrate milestones
Current Implementation Status
Note: BookWish does not currently have a formal announcement system implemented. This guide outlines recommended approaches and best practices for when the system is built.
Announcement Types
System Announcements
Maintenance Notifications:
- Scheduled downtime
- Performance upgrades
- Database migrations
- Feature deployments
System Issues:
- Current outages
- Degraded performance
- Known bugs
- Workarounds
Feature Announcements
New Features:
- Major feature launches
- Enhanced functionality
- UI/UX improvements
- New integrations
Feature Changes:
- Deprecation notices
- Breaking changes
- Migration guides
- Timeline for changes
Policy Announcements
Policy Updates:
- Terms of Service changes
- Privacy Policy updates
- Community Guidelines revisions
- Fee structure changes
Compliance:
- Legal requirements
- Regulatory changes
- Geographic restrictions
- Age restrictions
Community Announcements
Platform Milestones:
- User growth milestones
- Feature usage stats
- Success stories
- Thank you messages
Events & Promotions:
- Platform events
- Promotional periods
- Contests or giveaways
- Partner announcements
Recommended Implementation
Database Schema
CREATE TABLE announcements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
type VARCHAR(50) NOT NULL, -- 'info', 'warning', 'error', 'success'
priority VARCHAR(50), -- 'low', 'medium', 'high', 'urgent'
-- Targeting
target_tiers TEXT[], -- ['free', 'premium'], NULL = all
target_user_ids TEXT[], -- Specific users, NULL = all
-- Scheduling
start_at TIMESTAMP NOT NULL,
end_at TIMESTAMP, -- NULL = no expiration
-- Display settings
dismissible BOOLEAN DEFAULT true,
show_banner BOOLEAN DEFAULT false,
show_notification BOOLEAN DEFAULT true,
require_acknowledgment BOOLEAN DEFAULT false,
-- Tracking
created_by VARCHAR(255) NOT NULL, -- Admin user ID
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE announcement_reads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
announcement_id UUID NOT NULL REFERENCES announcements(id) ON DELETE CASCADE,
user_id VARCHAR(255) NOT NULL,
read_at TIMESTAMP DEFAULT NOW(),
acknowledged_at TIMESTAMP,
UNIQUE(announcement_id, user_id)
);
CREATE INDEX idx_announcements_active ON announcements(start_at, end_at);
CREATE INDEX idx_announcement_reads_user ON announcement_reads(user_id);
Announcement Model
interface Announcement {
id: string;
title: string;
message: string;
type: 'info' | 'warning' | 'error' | 'success';
priority: 'low' | 'medium' | 'high' | 'urgent';
// Targeting
targetTiers?: UserTier[];
targetUserIds?: string[];
// Scheduling
startAt: Date;
endAt?: Date;
// Display
dismissible: boolean;
showBanner: boolean;
showNotification: boolean;
requireAcknowledgment: boolean;
// Meta
createdBy: string;
createdAt: Date;
updatedAt: Date;
}
Creating Announcements
General Announcement
All Users:
INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
dismissible,
created_by
) VALUES (
'New Feature: Dark Mode',
'Dark mode is now available in settings! Toggle between light and dark themes to match your preference.',
'info',
'medium',
NOW(),
true,
'admin_user_id'
);
Maintenance Announcement
Scheduled Downtime:
INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
end_at,
dismissible,
show_banner,
created_by
) VALUES (
'Scheduled Maintenance - Dec 15',
'BookWish will be undergoing scheduled maintenance on December 15 from 2:00 AM to 4:00 AM EST. The platform will be unavailable during this time. We apologize for any inconvenience.',
'warning',
'high',
NOW(),
'2025-12-15 04:00:00',
false,
true,
'admin_user_id'
);
Targeted Announcement
Premium Users Only:
INSERT INTO announcements (
title,
message,
type,
priority,
target_tiers,
start_at,
created_by
) VALUES (
'New Premium Feature: Unlimited Collections',
'Thank you for being a premium subscriber! You now have access to unlimited book collections. Create as many custom collections as you want to organize your reading.',
'success',
'medium',
ARRAY['premium'],
NOW(),
'admin_user_id'
);
Store Owners Only:
INSERT INTO announcements (
title,
message,
type,
priority,
target_tiers,
start_at,
show_banner,
created_by
) VALUES (
'New Store Feature: Bulk Import',
'You can now bulk import inventory using CSV files! Visit your store dashboard to try this time-saving feature.',
'info',
'high',
ARRAY['bookstore'],
NOW(),
true,
'admin_user_id'
);
Urgent Announcement
Critical Issue:
INSERT INTO announcements (
title,
message,
type,
priority,
start_at,
dismissible,
show_banner,
require_acknowledgment,
created_by
) VALUES (
'Security Update Required',
'We have detected a security issue affecting some accounts. Please reset your password immediately. Click here to reset: [link]',
'error',
'urgent',
NOW(),
false,
true,
true,
'admin_user_id'
);
Managing Announcements
Viewing Active Announcements
All Active:
SELECT * FROM announcements
WHERE start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW())
ORDER BY priority DESC, start_at DESC;
By Type:
SELECT * FROM announcements
WHERE type = 'warning'
AND start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW());
By Tier:
SELECT * FROM announcements
WHERE 'premium' = ANY(target_tiers)
OR target_tiers IS NULL -- Include announcements for all users
AND start_at <= NOW()
AND (end_at IS NULL OR end_at > NOW());
Updating Announcements
Update Message:
UPDATE announcements
SET message = 'Updated message content',
updated_at = NOW()
WHERE id = 'announcement_id';
Extend Duration:
UPDATE announcements
SET end_at = '2025-12-20 00:00:00',
updated_at = NOW()
WHERE id = 'announcement_id';
Change Priority:
UPDATE announcements
SET priority = 'urgent',
updated_at = NOW()
WHERE id = 'announcement_id';
Ending Announcements
End Immediately:
UPDATE announcements
SET end_at = NOW(),
updated_at = NOW()
WHERE id = 'announcement_id';
Delete Announcement:
-- Only delete if not started or mistakenly created
DELETE FROM announcements
WHERE id = 'announcement_id';
Delivery Methods
In-App Banner
Top Banner:
- Displayed at top of app/website
- Visible on all pages
- Color-coded by type (info=blue, warning=yellow, error=red)
- Can be dismissed (if dismissible)
Implementation:
// Frontend component
function AnnouncementBanner() {
const announcements = useAnnouncements({ showBanner: true });
if (!announcements.length) return null;
return (
<div className="announcement-banner">
{announcements.map(a => (
<Banner
key={a.id}
type={a.type}
message={a.message}
dismissible={a.dismissible}
onDismiss={() => markRead(a.id)}
/>
))}
</div>
);
}
Push Notifications
Mobile/Browser Notifications:
- Sent when announcement published
- Respects user notification preferences
- Can be targeted by tier
- Tracked for delivery/open rates
Implementation:
// When creating announcement
async function publishAnnouncement(announcement: Announcement) {
await db.announcements.insert(announcement);
if (announcement.showNotification) {
await pushService.sendToUsers({
title: announcement.title,
body: announcement.message,
targetTiers: announcement.targetTiers,
targetUserIds: announcement.targetUserIds,
});
}
}
Email Notifications
Critical Announcements:
- Sent for urgent/high-priority items
- Respects email preferences
- Formatted email template
- Tracking for opens/clicks
When to Email:
- Urgent security issues
- Major breaking changes
- Extended outages
- Critical policy updates
In-App Notification Center
Notification Inbox:
- List of all announcements for user
- Mark as read
- Archive/dismiss
- Link to full details
Implementation:
GET /api/announcements
Authorization: Bearer <user_token>
Response:
{
"announcements": [
{
"id": "...",
"title": "...",
"message": "...",
"type": "info",
"read": false,
"createdAt": "..."
}
]
}
Targeting Announcements
By User Tier
Free Users:
target_tiers = ARRAY['free']
Premium Users:
target_tiers = ARRAY['premium']
Store Owners:
target_tiers = ARRAY['bookstore']
Multiple Tiers:
target_tiers = ARRAY['premium', 'bookstore']
All Users:
target_tiers = NULL
By Specific Users
Beta Testers:
target_user_ids = ARRAY['user1', 'user2', 'user3']
Affected Users:
-- Users affected by specific issue
target_user_ids = (
SELECT ARRAY_AGG(user_id)
FROM affected_users_table
WHERE condition = true
)
By Geography
Note: Requires user location data
-- Store in announcement metadata or separate field
metadata = {
"targetCountries": ["US", "CA"],
"targetRegions": ["NA"]
}
Scheduling Announcements
Immediate Announcement
start_at = NOW()
end_at = NULL -- No end date
Scheduled Start
start_at = '2025-12-15 09:00:00' -- Future date
end_at = NULL
Limited Duration
start_at = NOW()
end_at = NOW() + INTERVAL '7 days' -- Expires in 7 days
Recurring Announcements
Manual Recurring:
- Create new announcement each time
- Copy from template
- Adjust dates
Automated Recurring (Future):
-- Potential future schema
recurrence_rule = 'WEEKLY' -- or 'MONTHLY', 'DAILY'
recurrence_end_date = '2026-01-01'
Tracking & Analytics
Read Rates
Announcement Read Rate:
SELECT a.title,
COUNT(DISTINCT ar.user_id) as read_count,
(SELECT COUNT(*) FROM users WHERE tier = ANY(a.target_tiers OR ARRAY['free', 'premium', 'bookstore', 'admin'])) as target_count
FROM announcements a
LEFT JOIN announcement_reads ar ON a.id = ar.announcement_id
WHERE a.id = 'announcement_id'
GROUP BY a.id, a.title;
Acknowledgment Tracking
For Critical Announcements:
SELECT a.title,
COUNT(ar.user_id) FILTER (WHERE ar.acknowledged_at IS NOT NULL) as acknowledged,
COUNT(ar.user_id) as read
FROM announcements a
LEFT JOIN announcement_reads ar ON a.id = ar.announcement_id
WHERE a.require_acknowledgment = true
GROUP BY a.id, a.title;
Engagement Metrics
Click-Through Rates:
- Track links in announcement
- Monitor user actions
- Measure effectiveness
Best Practices
Writing Announcements
Be Clear and Concise:
- Lead with the most important info
- Use simple language
- Avoid jargon
- Include call-to-action
Be Timely:
- Announce features when ready
- Give advance notice for changes
- Update status regularly
- Archive old announcements
Be Helpful:
- Explain the impact
- Provide next steps
- Link to more information
- Offer support contact
Frequency
Don't Over-Announce:
- Combine related updates
- Avoid announcement fatigue
- Respect user attention
- Use appropriate channels
Priority Levels:
- Reserve "urgent" for critical issues
- Use "high" sparingly
- Most should be "medium" or "low"
Testing
Before Publishing:
- Preview the announcement
- Test on different devices
- Check targeting logic
- Verify links work
- Proofread carefully
Announcement Templates
New Feature Launch
Title: New Feature: [Feature Name]
Message: We're excited to announce [feature name]! [Brief description of what it does and why it's valuable]. [How to access/use it]. Learn more: [link]
Type: info
Priority: medium
Maintenance Window
Title: Scheduled Maintenance - [Date]
Message: BookWish will undergo scheduled maintenance on [date] from [start time] to [end time] [timezone]. The platform will be unavailable during this period. We apologize for any inconvenience and appreciate your patience.
Type: warning
Priority: high
Show Banner: true
Security Issue
Title: Important Security Update
Message: We've identified a security issue affecting [scope]. Please [required action] immediately. [What we're doing]. Questions? Contact security@bookwish.com
Type: error
Priority: urgent
Require Acknowledgment: true
Show Banner: true
Policy Update
Title: Updated Terms of Service
Message: We've updated our Terms of Service to [reason]. Key changes include: [bullet points]. The new terms take effect [date]. Review full terms: [link]
Type: info
Priority: medium
Admin API Endpoints
Proposed Endpoints
Create Announcement:
POST /api/admin/announcements
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"title": "Announcement Title",
"message": "Announcement message",
"type": "info",
"priority": "medium",
"targetTiers": ["premium"],
"startAt": "2025-12-15T09:00:00Z"
}
List Announcements:
GET /api/admin/announcements
GET /api/admin/announcements?active=true
GET /api/admin/announcements?type=warning
Authorization: Bearer <admin_token>
Update Announcement:
PUT /api/admin/announcements/:id
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"message": "Updated message",
"endAt": "2025-12-20T00:00:00Z"
}
Delete Announcement:
DELETE /api/admin/announcements/:id
Authorization: Bearer <admin_token>
Get Analytics:
GET /api/admin/announcements/:id/analytics
Authorization: Bearer <admin_token>
Response:
{
"reads": 1500,
"acknowledged": 1200,
"targetUsers": 2000,
"readRate": 75
}