Overview
Web2Wave can send real-time notifications about events in your project via webhooks. This allows you to integrate with external systems and react to user actions as they happen.
Webhook Delivery Options
You can choose one of the following options for receiving webhooks:
Option 1: Single Webhook URL
Send all webhooks to a single URL endpoint. This is the simplest option if you have one system that needs to receive all webhook events.
- Pros: Simple setup, direct integration
- Cons: All events go to one endpoint, no built-in filtering or logging
Option 2: Webhook Gateway (Powered by Convoy)
Use our integrated Webhook Gateway for advanced webhook management capabilities.
- Multiple Endpoints: Send different webhook types to different URLs
- Event Logging: View a complete log of all sent webhooks
- Custom Filters: Filter webhooks based on event data using Convoy subscription filters
- Retry Management: Automatic retry handling for failed deliveries
- Portal Access: Visual interface to manage your webhooks
To use Webhook Gateway, click "Add Webhook Gateway Portal" and the system will generate a portal token for you.
Note: You can only use one option at a time - either a single webhook URL or the Webhook Gateway.
Available Webhook Types
user_property
- Sent when user properties are created or updatedevent
- Sent for analytics events tracked in your applicationsubscription
- Sent when subscription status changesCompleteRegistration
- Sent when a user completes the quiz and reaches the paywall
General Requirements
-
URL Requirements:
- Must be specified in project settings
- Must begin with
http://
orhttps://
- If no URL is specified, no events will be sent
-
Timeout: Server response time must not exceed 3 seconds or the connection will be terminated
-
Format: All data is sent as JSON with UTF-8 encoding
-
Authentication: Each webhook request includes a
Webhooks-Token
header containing your project's webhook secret for verification
Webhook Structure
All webhooks follow this basic structure:
{
"type": "webhook_type",
"data": {
// Type-specific data
}
}
Fields:
type
(string): The webhook event typedata
(object): Event-specific data
Webhook Types
type: "user_property"
Sent every time a user property is added or modified. This includes quiz answers, UTM parameters, user location data (country_code, language), and any custom properties.
When triggered:
- New user property is set
- Existing user property is updated
Data fields:
Field | Type | Description |
---|---|---|
project_domain | string | Domain of the project |
user_id | string | Unique user identifier (GUID) |
property | string | Property name (e.g., "email", "utm_source", "answer_1") |
value | string | Property value (multiple values separated by "||") |
Example:
{
"type": "user_property",
"data": {
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "2_question",
"value": "Of course, yes"
}
}
type: "event"
Sent for every analytics event tracked in your application.
When triggered: Any custom event is logged (e.g., button clicks, page views, form submissions)
Data fields:
Field | Type | Description |
---|---|---|
created_at | string | Event timestamp (ISO 8601) |
user_id | string | Unique user identifier (GUID) |
project_domain | string | Domain of the project |
quiz_id | string | Quiz identifier |
quiz_name | string | Name of the quiz |
event_name | string | Name of the event |
event_value | string | Event value |
event_properties | string|null | JSON-encoded event properties |
url | string | Page where event occurred |
initial_url | string | Initial page URL with UTM parameters |
user_agent | string | User's browser information |
user_time | string | User's local time |
user_locale | string | User's language/locale |
app_version | string | Application version |
quiz_version | string|null | Quiz version |
experiment | string|null | A/B test experiment name |
experiment_group | string|null | A/B test variant |
additional_data | string|null | JSON-encoded additional data |
ip | string | User's IP address |
paywall_name | string|null | Paywall name if applicable |
paywall_version | string | Paywall version |
user_visit | string | Visit identifier |
Example:
{
"type": "event",
"data": {
"created_at": "2024-06-12T19:19:18.000000Z",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"project_domain": "app.web2wave.com",
"quiz_id": "5",
"quiz_name": "Product Quiz",
"event_name": "Answer radio 2_question",
"event_value": "Of course, yes",
"event_properties": "{\"value\":\"Of course, yes\"}",
"url": "https://app.web2wave.com/#2_question",
"initial_url": "https://app.web2wave.com/?utm_source=google&utm_campaign=my_campaign",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"user_time": "9:19:18 PM",
"user_locale": "en",
"app_version": "1.0",
"quiz_version": null,
"experiment": null,
"experiment_group": null,
"additional_data": null,
"ip": "192.168.1.1",
"paywall_name": null,
"paywall_version": "1.0",
"user_visit": "visit_123"
}
}
type: "CompleteRegistration"
Sent when a user completes the quiz and reaches the paywall, including all user properties. This is useful for tracking quiz completions and passing all collected user data to your systems.
When triggered:
- User finishes the quiz and is shown the paywall
- Only sent if "CompleteRegistration event with User Properties" is enabled in webhook settings
Data fields:
Field | Type | Description |
---|---|---|
created_at | string | Event timestamp |
user_id | string | Unique user identifier (GUID) |
project_domain | string | Domain of the project |
event_name | string | Always "CompleteRegistration" |
properties | array | All user properties (same format as user_property webhook) |
Example:
{
"type": "CompleteRegistration",
"data": {
"created_at": "2024-06-12T19:20:00.000000Z",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"project_domain": "app.web2wave.com",
"event_name": "CompleteRegistration",
"properties": [
{
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "email",
"value": "[email protected]"
},
{
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "utm_source",
"value": "google"
},
{
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "answer_1",
"value": "Option A"
},
{
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "user_country_code",
"value": "US"
},
{
"project_domain": "app.web2wave.com",
"user_id": "f555ab28-a2b8-447d-9fe9-3c17e6ac70f4",
"property": "user_language",
"value": "en"
}
]
}
}
type: "subscription"
Sent when subscription status changes (created, renewed, cancelled, etc.).
When triggered:
- New subscription created
- Subscription renewed
- Subscription cancelled
- Payment succeeded/failed
- Subscription status changed
Data fields:
Field | Type | Description |
---|---|---|
created_at | string | Subscription creation timestamp (ISO 8601) |
updated_at | string | Last update timestamp (ISO 8601) |
payment_system | int | Payment system identifier |
payment_system_label | string | Payment system name (e.g., "Stripe") |
real_payment | int | Production mode (1) or test mode (0) |
pay_system_id | string | Payment system's subscription ID |
project_domain | string | Project domain |
quiz_name | string | Associated quiz name |
quiz_id | string | Quiz identifier |
paywall_name | string | Paywall name |
paywall_id | string | Paywall identifier |
price_id | string | Price/plan identifier |
amount | float | Amount in cents |
amount_real | float | Amount in real currency |
currency | string | Currency code (e.g., "usd", "gbp") |
canceled_at | string|null | Cancellation timestamp or null |
customer | string | Customer ID in payment system |
status | string | Subscription status (see Status Options below) |
next_charge_date | string|null | Next payment date (ISO 8601) |
last_charge_date | string|null | Last payment date (ISO 8601) |
charges_count | int | Total number of charges |
total_revenue | int | Total revenue in cents |
total_revenue_usd | int | Total revenue in USD cents |
user_id | string | User identifier |
user_email | string | User's email address |
manage_link | string|null | Subscription management URL |
event_type | string | Payment system event (e.g., "charge.succeeded") |
price | object | Detailed price information |
invoices_new | array | List of invoice objects |
properties | array|null | User properties (if enabled) |
user_visit | object | Visit tracking information |
Status Options:
active
- Active subscriptionincomplete
- Incomplete setupincomplete_expired
- Setup expiredtrialing
- In trial periodpast_due
- Payment overduecanceled
- Subscription canceledunpaid
- Payment failedpaused
- Subscription paused
Example: [Full subscription webhook example available in the original documentation above]
Configuration Options
In your project webhook settings, you can configure:
Event Type Filtering
- User Property: Every user answer, UTM tags, location data, etc.
- Analytics Events: All tracked events in your application
- Subscription updated: When subscription status changes
- CompleteRegistration event with User Properties: When quiz is completed
Additional Options
- Filter specific events: Specify exact event names to receive (one per line)
- Filter user properties: Specify which user properties to include (one per line)
- Include User Properties with Subscriptions: Add all user properties to subscription webhooks
Testing Webhooks
Use webhook.site for testing and debugging your webhook integration.
Best Practices
- Verify webhook authenticity using the
Webhooks-Token
header - Respond quickly (within 3 seconds) to avoid timeouts
- Return 2xx status codes to acknowledge receipt
- Handle duplicates - webhooks may be sent multiple times
- Process asynchronously - acknowledge receipt immediately, then process in background
- Log webhook data for debugging and audit purposes
Error Handling
- Webhooks that timeout or receive non-2xx responses may be retried
- Failed webhooks are logged for troubleshooting
- Ensure your endpoint can handle concurrent requests
Using Webhook Gateway Filters
When using the Webhook Gateway option, you can create advanced filters using Convoy's JSON-based filter syntax. This allows you to:
- Route different event types to different URLs
- Filter based on specific field values
- Create complex conditions using logical operators
- Use regex patterns for flexible matching
Filter Examples for Web2Wave
Simple Filters
Send only active subscriptions:
{
"data": {
"status": "active"
}
}
Send only events from a specific quiz:
{
"data": {
"quiz_id": "123"
}
}
Send only CompleteRegistration events:
{
"type": "CompleteRegistration"
}
Complex Filters
Send only high-value subscriptions ($50+):
{
"data": {
"amount_real": {
"$gte": 50
}
}
}
Send subscriptions from specific payment systems:
{
"data": {
"payment_system_label": {
"$in": ["Stripe", "PayPal"]
}
}
}
Send only failed or cancelled subscriptions:
{
"$or": [
{
"data": {
"status": "canceled"
}
},
{
"data": {
"status": "unpaid"
}
}
]
}
Send events matching specific patterns:
{
"data": {
"event_name": {
"$regex": "^CompleteRegistration|Purchase|Subscribe$"
}
}
}
Complex subscription filter (high-value active subscriptions):
{
"$and": [
{
"data": {
"status": "active"
}
},
{
"data": {
"amount_real": {
"$gte": 29.99
}
}
},
{
"data": {
"currency": {
"$in": ["usd", "eur", "gbp"]
}
}
}
]
}
Filter user properties by specific answers:
{
"$and": [
{
"type": "user_property"
},
{
"data": {
"property": "email"
}
}
]
}
Send only events with specific UTM sources:
{
"$and": [
{
"type": "user_property"
},
{
"data": {
"property": "utm_source"
}
},
{
"data": {
"value": {
"$in": ["google", "facebook", "instagram"]
}
}
}
]
}
Filter subscriptions with nested price data:
{
"data": {
"price": {
"currency": "usd"
}
}
}
Filter by user visit data:
{
"data": {
"user_visit": {
"utm_source": "facebook"
}
}
}
Supported Filter Operators
Operator | Type | Description | Example |
---|---|---|---|
(none) | all | Direct match | {"data": {"status": "active"}} |
$eq | all | Equal to | {"data": {"amount": {"$eq": 100}}} |
$neq | all | Not equal to | {"data": {"status": {"$neq": "canceled"}}} |
$gt | number | Greater than | {"data": {"amount_real": {"$gt": 50}}} |
$gte | number | Greater than or equal | {"data": {"amount_real": {"$gte": 50}}} |
$lt | number | Less than | {"data": {"charges_count": {"$lt": 3}}} |
$lte | number | Less than or equal | {"data": {"charges_count": {"$lte": 3}}} |
$in | array | Value in array | {"data": {"currency": {"$in": ["usd", "eur"]}}} |
$nin | array | Value not in array | {"data": {"status": {"$nin": ["trialing", "incomplete"]}}} |
$or | array | Any condition matches | {"$or": [{"type": "event"}, {"type": "subscription"}]} |
$and | array | All conditions match | {"$and": [{"type": "subscription"}, {"data": {"status": "active"}}]} |
$regex | string | Regex pattern match | {"data": {"event_name": {"$regex": "^Complete"}}} |
$exist | bool | Field exists | {"data": {"user_email": {"$exist": true}}} |
For complete filter documentation and more examples, see the Convoy Filters Documentation.