A time-based targeting descriptor for @targetd/api that enables content delivery based on date ranges.
| JS Runtime | Command |
|---|---|
| Node.js | npx jsr add @targetd/api @targetd/date-range |
| Bun | bunx jsr add @targetd/api @targetd/date-range |
| Deno | deno add jsr:@targetd/api jsr:@targetd/date-range |
@targetd/date-range provides a ready-to-use targeting descriptor that
evaluates date ranges. It's useful for:
- Time-limited campaigns: Launch features or content within specific date ranges
- Event-based content: Show content during events or time periods
- Scheduled releases: Automatically enable/disable features based on dates
- Historical queries: Query what content would have been shown at any point in time
The descriptor automatically uses the current system time when no query is provided, making it perfect for real-time targeting.
import { Data, DataSchema } from '@targetd/api'
import dateRangeTargeting from '@targetd/date-range'
import { z } from 'zod'
const schema = DataSchema.create()
.usePayload({
banner: z.string(),
})
.useTargeting({
dateRange: dateRangeTargeting,
})
const data = await Data.create(schema).addRules('banner', [
{
targeting: {
dateRange: {
start: '2024-12-01',
end: '2024-12-31',
},
},
payload: '🎄 Holiday Sale!',
},
{
targeting: {
dateRange: {
start: '2025-01-01',
},
},
payload: '🎉 New Year Special!',
},
{
payload: 'Regular banner',
},
])
// Query with current system time
const currentBanner = await data.getPayload('banner')
// Returns the banner matching the current date/timeDate ranges use ISO 8601 format and support both dates and date-times:
// Date only (YYYY-MM-DD)
{ start: '2024-12-01', end: '2024-12-31' }
// Date with time (YYYY-MM-DDTHH:mm:ss)
{ start: '2024-12-01T00:00:00', end: '2024-12-31T23:59:59' }
// With timezone offset
{ start: '2024-12-01T00:00:00Z', end: '2024-12-31T23:59:59-05:00' }
// Open-ended ranges
{ start: '2024-12-01' } // From date onwards
{ end: '2024-12-31' } // Up to dateBy default, queries without a dateRange parameter use the current system time:
.addRules('content', [
{
targeting: {
dateRange: {
start: '2024-01-01',
end: '2024-12-31'
}
},
payload: '2024 content'
},
{
payload: 'Default content'
}
])
// Uses current system time automatically
const content = await data.getPayload('content')Query what content would have been shown at any point in time:
// What was shown in 1940?
const wwiiContent = await data.getPayload('content', {
dateRange: { start: '1940-01-01', end: '1940-12-31' },
})Enable features only during specific periods:
.addRules('feature', [
{
targeting: {
dateRange: {
start: '2024-11-25T00:00:00',
end: '2024-11-29T23:59:59'
}
},
payload: { enabled: true, discount: 0.5 }
},
{
payload: { enabled: false }
}
])Create rules that start or end at a specific time:
.addRules('pricing', [
{
// Pricing effective from this date forward
targeting: {
dateRange: {
start: '2025-01-01'
}
},
payload: { price: 99.99 }
},
{
// Legacy pricing (before 2025)
payload: { price: 79.99 }
}
])Target multiple date ranges with an array:
.addRules('seasonalContent', [
{
targeting: {
dateRange: [
{ start: '2024-06-01', end: '2024-08-31' }, // Summer
{ start: '2024-12-01', end: '2024-12-31' } // Holiday
]
},
payload: 'Seasonal special content'
},
{
payload: 'Regular content'
}
])Here's a comprehensive example showing event-based content delivery:
import { Data, DataSchema } from '@targetd/api'
import dateRangeTargeting from '@targetd/date-range'
import { z } from 'zod'
const schema = DataSchema.create()
.usePayload({
event: z.object({
name: z.string(),
message: z.string(),
active: z.boolean(),
}),
})
.useTargeting({
dateRange: dateRangeTargeting,
})
const data = await Data.create(schema).addRules('event', [
{
targeting: {
dateRange: {
start: '1939-09-01',
end: '1945-09-02',
},
},
payload: {
name: 'World War II',
message: 'Historical period: 1939-1945',
active: true,
},
},
{
targeting: {
dateRange: {
start: '2020-01-01T00:00:00',
},
},
payload: {
name: 'Modern Era',
message: 'Welcome to the 2020s',
active: true,
},
},
{
payload: {
name: 'No Active Event',
message: 'No special event during this period',
active: false,
},
},
])
// Query with current time
const currentEvent = await data.getPayload('event')
// Returns event matching current date/time
// Query historical period
const historicalEvent = await data.getPayload('event', {
dateRange: { start: '1942-01-01', end: '1942-12-31' },
})
// Returns: { name: 'World War II', message: '...', active: true }
// Query future period
const futureEvent = await data.getPayload('event', {
dateRange: { start: '2025-06-01' },
})
// Returns: { name: 'Modern Era', message: '...', active: true }The date range predicate evaluates whether query and target ranges overlap:
- No query provided: Uses current system time
- Query with range: Checks if query range overlaps with target range
- Multiple target ranges: Returns true if query overlaps with any target range
Two ranges overlap if:
- Query start is before target end (or target has no end)
- Query end is after target start (or target has no start)
// These ranges overlap:
query: { start: '2024-06-01', end: '2024-06-30' }
target: { start: '2024-06-15', end: '2024-07-15' }
// These do NOT overlap:
query: { start: '2024-06-01', end: '2024-06-30' }
target: { start: '2024-07-01', end: '2024-07-31' }- @targetd/api - Core targeting and data querying API
- @targetd/server - HTTP server for serving targeted data
- @targetd/client - Type-safe HTTP client for querying servers
See LICENSE file for details.