Overview
Enterprise users can define custom alert rules beyond the standard triggers. Set specific thresholds, combine conditions, and route alerts to different notification channels including webhooks.
How It Works
1. Admin creates custom alert rules
2. Each rule defines:
– Trigger conditions (score below X, specific property missing, type removed)
– Threshold values
– Notification channels (email, webhook)
– Affected URLs or projects
3. Rules are evaluated after each re-scan
4. Matching rules fire their configured notifications
Tier Availability
| Tier | Available |
|——|———–|
| Free | No |
| Pro | No |
| Agency | No |
| Enterprise | Yes |
Related Features
– Email Alerts: Standard alert system
– URL Monitoring: URLs that rules apply to
– Webhook Management: Route alerts to external systems
Quick Start: Create Custom Alert Rules
Step 1: Define a custom rule (Enterprise tier only)
curl -X POST https://api.validgraph.io/wp-json/validgraph/v1/alerts/rules
-H "Authorization: Bearer YOUR_API_KEY"
-H "Content-Type: application/json"
-d '{
"name": "Product pages below 75",
"description": "Alert when any product page drops below 75 score",
"conditions": {
"rule_type": "score_threshold",
"operator": "less_than",
"value": 75
},
"actions": {
"notify_via": ["email", "webhook"],
"recipients": ["[email protected]"],
"webhook_url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
"severity_level": "high"
},
"scope": {
"applies_to": "monitored_urls",
"url_pattern": "^https://example.com/products/.*"
}
}'
Step 2: Rule evaluates automatically after each rescan
Step 3: Actions trigger when conditions match (email, webhook to Slack, etc.)
Example scenario:
Configure rule: “Alert when Article score < 70 OR datePublished missing”. During daily rescan, an article’s score drops to 68 with missing datePublished. Rule fires → Slack webhook sends message to #schema-alerts channel + email to ops team.
Technical Details
Rule Creation Endpoint
Create alert rule:
POST /wp-json/validgraph/v1/alerts/rules
Full request with all options:
{
"name": "Article Quality Gate",
"description": "Enforce minimum quality standards for articles",
"enabled": true,
"conditions": {
"operator": "AND",
"rules": [
{
"rule_type": "score_threshold",
"property": "score",
"operator": "less_than",
"value": 75
},
{
"rule_type": "missing_property",
"schema_type": "Article",
"property": "image",
"operator": "is_missing"
}
]
},
"actions": {
"alert_channels": ["email", "webhook"],
"email_recipients": ["[email protected]", "[email protected]"],
"webhook": {
"url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
"method": "POST",
"headers": {
"X-Custom-Header": "ValidGraph"
}
},
"severity": "high",
"include_in_digest": false,
"rate_limit": {
"max_alerts_per_hour": 10,
"cooldown_minutes": 30
}
},
"scope": {
"applies_to": "urls",
"url_patterns": [
"^https://example.com/articles/.*",
"^https://blog.example.com/.*"
],
"exclude_patterns": [
"^https://example.com/articles/draft/.*"
],
"monitoring_ids": []
}
}
Response:
{
"success": true,
"data": {
"rule_id": "rule_article_quality_001",
"name": "Article Quality Gate",
"status": "active",
"created_at": "2024-03-21T10:00:00Z",
"conditions_summary": "score < 75 AND image is missing",
"scope_urls": 42,
"last_evaluated": null,
"next_evaluation": "2024-03-22T06:00:00Z (on next rescan)"
}
}
Rule Condition Types
score_threshold:
{
"rule_type": "score_threshold",
"operator": "less_than",
"value": 75
}
missing_property:
{
"rule_type": "missing_property",
"schema_type": "Article",
"property": "image"
}
error_count:
{
"rule_type": "error_count",
"operator": "greater_than",
"value": 0
}
schema_change:
{
"rule_type": "schema_change",
"severity": "high"
}
property_value_match:
{
"rule_type": "property_value_match",
"schema_type": "Organization",
"property": "name",
"operator": "contains",
"value": "deprecated"
}
Combined Conditions
AND logic:
{
"operator": "AND",
"rules": [
{"rule_type": "score_threshold", "operator": "less_than", "value": 75},
{"rule_type": "missing_property", "schema_type": "Article", "property": "image"}
]
}
Fires when ALL conditions match.
OR logic:
{
"operator": "OR",
"rules": [
{"rule_type": "error_count", "operator": "greater_than", "value": 2},
{"rule_type": "schema_change", "severity": "high"}
]
}
Fires when ANY condition matches.
Webhook Payload Example
When rule triggers:
{
"event": "alert_rule_triggered",
"rule_id": "rule_article_quality_001",
"rule_name": "Article Quality Gate",
"timestamp": "2024-03-21T06:15:00Z",
"severity": "high",
"url": "https://example.com/articles/example-article",
"monitoring_id": "mon_abc123",
"validation_id": "val_scan_456",
"conditions_matched": [
{
"condition": "score < 75",
"current_value": 72,
"threshold": 75
},
{
"condition": "image is missing",
"schema_type": "Article"
}
],
"previous_validation": {
"validation_id": "val_scan_455",
"score": 85,
"errors": 0
},
"current_validation": {
"validation_id": "val_scan_456",
"score": 72,
"errors": 1
},
"dashboard_link": "https://validgraph.io/validations/val_scan_456",
"manage_rule_link": "https://validgraph.io/alerts/rules/rule_article_quality_001"
}
Rule List and Management
List all custom rules:
GET /wp-json/validgraph/v1/alerts/rules
Get specific rule:
GET /wp-json/validgraph/v1/alerts/rules/rule_article_quality_001
Update rule:
PUT /wp-json/validgraph/v1/alerts/rules/rule_article_quality_001
{
"conditions": {...},
"actions": {...}
}
Delete rule:
DELETE /wp-json/validgraph/v1/alerts/rules/rule_article_quality_001
Test rule (evaluate against current monitored URLs):
POST /wp-json/validgraph/v1/alerts/rules/rule_article_quality_001/test
Response:
{
"rule_id": "rule_article_quality_001",
"test_result": true,
"urls_matching_conditions": 3,
"sample_matches": [
{
"url": "https://example.com/articles/low-quality-article",
"score": 72,
"matching_conditions": ["score < 75", "image is missing"]
}
],
"would_trigger_alert": true,
"would_notify_count": 1
}
Rule Evaluation Examples
Rule 1: Enforce rich snippet requirements
{
"name": "Rich Snippet Eligibility Gate",
"conditions": {
"operator": "AND",
"rules": [
{"rule_type": "missing_property", "schema_type": "Article", "property": "headline"},
{"rule_type": "missing_property", "schema_type": "Article", "property": "image"}
]
},
"actions": {
"alert_channels": ["email"],
"email_recipients": ["[email protected]"],
"severity": "critical"
}
}
Rule 2: Monitor schema type changes
{
"name": "Schema Type Change Detection",
"conditions": {
"rule_type": "schema_change",
"severity": "high"
},
"actions": {
"alert_channels": ["webhook"],
"webhook": {"url": "https://hooks.slack.com/..."},
"severity": "high"
}
}
Rule 3: Multi-property completeness check
{
"name": "Recipe Schema Completeness",
"conditions": {
"operator": "OR",
"rules": [
{"rule_type": "error_count", "operator": "greater_than", "value": 0},
{"rule_type": "missing_property", "schema_type": "Recipe", "property": "aggregateRating"}
]
},
"actions": {
"alert_channels": ["email", "webhook"],
"severity": "medium"
}
}
Rate Limiting and Cooldown
To avoid alert fatigue, rules support:
{
"rate_limit": {
"max_alerts_per_hour": 10,
"cooldown_minutes": 30
}
}
– max_alerts_per_hour: Max number of alerts this rule can fire in 60 minutes
– cooldown_minutes: After rule fires, wait this long before it can fire again for same URL
References
– Alert Rule Design Patterns: https://www.alertmanager.io/configuration/
– Webhook Best Practices: https://zapier.com/engineering/webhook/
– JSON Schema Validation: https://json-schema.org/
– LogQL Query Language: https://grafana.com/docs/loki/latest/logql/
– Custom Rule Examples: https://example.com/docs/custom-rules-guide