Last updated: March 22, 2026

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 |

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