Event Promotion
This document covers the automatic event/tournament promotion capabilities of the CRM & Marketing Platform.
Overview
When a competition is published in TeeTime, CRM can automatically:
- Create campaign targeting relevant segment
- Generate content from competition details
- Schedule posts across all channels
- Send reminders as event approaches
Event Promotion Workflow
┌─────────────────────────────────────────────────────────────────┐
│ EVENT PROMOTION WORKFLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ TeeTime CRM Platform │
│ │ │ │
│ │ competition.published │ │
│ │──────────────────────────────▶│ │
│ │ │ │
│ │ │ Check auto-promote │
│ │ │ settings for club │
│ │ │─────────┐ │
│ │ │ │ │
│ │ │◀────────┘ │
│ │ │ │
│ │ │ If enabled: │
│ │ │ │
│ │ │ 1. Create campaign │
│ │ │ 2. Build segment │
│ │ │ 3. Generate content │
│ │ │ 4. Schedule: │
│ │ │ - Email blast │
│ │ │ - Social posts │
│ │ │ - SMS reminder │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘
EventPromotion Configuration
interface EventPromotion {
id: string;
tenantId: string;
clubId: string;
// Source
sourceType: 'COMPETITION' | 'CLUB_EVENT';
sourceId: string; // TeeTime competition ID
// Settings
autoPromote: boolean;
channels: Channel[]; // EMAIL, SMS, FACEBOOK, INSTAGRAM
// Timing
announceAt: Date; // Initial announcement
reminderDays: number[]; // Days before: [7, 3, 1]
// Targeting
segmentId?: string; // Custom segment
targetRadius?: number; // km from club for geo
// Content
emailTemplateId?: string;
smsTemplateId?: string;
socialContent?: string;
}
Source Types
COMPETITION
Tournaments and competitions from TeeTime service.
Event trigger: teetime.competition.published
Data available:
- Competition name
- Start date/time
- Entry fee
- Format (strokeplay, matchplay, etc.)
- Max entries
- Current entries
CLUB_EVENT
General club events (social events, demos, etc.).
Event trigger: club.event.published
Data available:
- Event name
- Date/time
- Description
- Capacity
- RSVP status
Auto-Promotion Settings
Club-Level Defaults
interface ClubAutoPromoteConfig {
clubId: string;
// Enable/disable
autoPromoteCompetitions: boolean;
autoPromoteEvents: boolean;
// Default channels
defaultChannels: Channel[];
// Default timing
defaultReminderDays: number[];
// Default targeting
defaultSegmentId?: string;
notifyMembersOnly: boolean;
}
Override Per Event
Individual events can override club defaults:
// Club default: announce immediately, reminders at 7, 3, 1 days
// Override: announce 2 weeks before, reminders at 7, 1 days
const promotion = {
announceAt: eventDate.minus({ weeks: 2 }),
reminderDays: [7, 1],
};
Content Generation
Default Content Templates
Email
Subject: Join us for {{competitionName}}!
Hi {{firstName}},
We're excited to announce {{competitionName}} on {{date}}.
Format: {{format}}
Entry Fee: {{entryFee}}
Spots: {{spotsRemaining}} remaining
[Register Now]
See you on the course!
{{clubName}}
SMS
{{clubName}}: {{competitionName}} on {{shortDate}}.
{{spotsRemaining}} spots left.
Register: {{shortLink}}
Social
{{competitionName}} is coming!
📅 {{date}}
⛳ {{format}}
💰 {{entryFee}}
Limited spots available - register now!
#golf #tournament #{{clubHashtag}}
Custom Content
Club admins can customize:
const promotion = {
socialContent: `
🏆 Club Championship 2025 🏆
Our biggest event of the year is here!
Defend your title or claim a new one.
📅 March 15-16
⛳ 36 holes strokeplay
🎁 Amazing prizes
Who's ready? 💪
#ClubChampionship #Golf #Competition
`,
emailTemplateId: "custom-tournament-invite",
};
Reminder Schedule
Default Pattern
| Days Before | Channel | Message Type |
|---|---|---|
| 14 | EMAIL + SOCIAL | Announcement |
| 7 | First reminder | |
| 3 | SMS | Urgency reminder |
| 1 | PUSH | Final reminder |
Configurable
reminderDays: [14, 7, 3, 1]
// Each trigger creates appropriate message
Segment Targeting
Default Segments
| Competition Type | Default Segment |
|---|---|
| General | All members with email opt-in |
| Men's | Male members |
| Ladies | Female members |
| Seniors | Members 55+ |
| Juniors | Members under 18 |
| Low handicap | Handicap < 10 |
Custom Targeting
// Target specific segment
const promotion = {
segmentId: "platinum-members-low-handicap",
};
// Or inline filters
const promotion = {
filters: {
rules: [
{ field: "handicap", operator: "lt", value: 15 },
{ field: "membershipTier", operator: "in", value: ["Gold", "Platinum"] },
]
}
};
Execution Flow
async handleCompetitionPublished(event): Promise<void> {
// 1. Get or create promotion config
const promotion = await this.getOrCreatePromotion(event);
if (!promotion.autoPromote) return;
// 2. Create campaign
const campaign = await this.campaignService.create({
name: `${event.competitionName} Promotion`,
type: "ONE_TIME",
segmentId: promotion.segmentId,
channels: promotion.channels.filter(c => c !== 'SOCIAL'),
});
// 3. Schedule announcement
await this.campaignService.schedule(
campaign.id,
promotion.announceAt ?? new Date()
);
// 4. Create social posts
if (promotion.channels.includes('SOCIAL')) {
await this.createSocialPosts(promotion, event);
}
// 5. Schedule reminders
for (const days of promotion.reminderDays) {
await this.scheduleReminder(promotion, event, days);
}
}
Analytics
Track promotion effectiveness:
| Metric | Description |
|---|---|
| Reach | Total people who saw promotion |
| Engagement | Opens, clicks, social engagement |
| Registrations | Entries attributed to promotion |
| Conversion rate | Registrations / Reach |
Attribution
// Track registration source
const registration = {
competitionId: "comp_123",
playerId: "player_456",
source: "campaign",
sourceId: "campaign_789", // CRM campaign ID
};