Hooks & filters
Yatra is built around a wide hook surface: every meaningful state change fires an action, and most rendered values pass through a filter so you can override them. This page lists the most useful actions and filters grouped by area, plus general guidance on using them.
Yatra exposes hundreds of hooks. The list below covers the ~80 you'll reach for most often.
Verify hook names against your version
Hook names can be added, renamed, or retired between plugin versions. Before you build something that depends on a specific hook, confirm it exists in your version by searching the plugin source:
bashgrep -rh "do_action.*yatra_booking_created" wp-content/plugins/yatra wp-content/plugins/yatra-pro grep -rh "apply_filters.*yatra_trip_price" wp-content/plugins/yatraEvery Yatra hook follows the
yatra_*prefix.
Conventions
- Actions are named
yatra_{noun}_{verb}and fire after the underlying change (e.g.yatra_booking_createdfires after the booking row is inserted). - Filters are named
yatra_{noun}_{property}and pass the value as the first argument. - Pro hooks carry no special prefix — Pro just adds more
yatra_*hooks. A few pro-specific hooks useyatra_pro_*(license, module activation). - Backwards compatibility: Yatra retires hooks with notice, never silently. Deprecated hooks keep firing for at least one minor version.
Trips
Fired around trip lifecycle and rendering.
| Hook | Type | Purpose |
|---|---|---|
yatra_trip_created | action | After a trip is inserted; receives $trip_id |
yatra_trip_updated | action | After a trip is updated |
yatra_trip_deleted | action | Before a trip is deleted (soft or hard) |
yatra_trip_loaded_with_relations | filter | Mutate the joined trip object (with classifications, attributes, etc.) |
yatra_trip_created_with_relations | action | After insert + relations save |
yatra_trip_updated_with_relations | action | After update + relations save |
yatra_trip_display_price | filter | Last-mile override for the displayed price |
yatra_dynamic_pricing_enabled | filter | Toggle Pro Dynamic Pricing per-trip |
yatra_availability_price | filter | Override price on a specific departure |
yatra_availability_horizon_months | filter | (int $months) — How far ahead the storefront offers dates (the Booking horizon setting, default 12, clamped 1–36). Return a different value per request, e.g. add_filter('yatra_availability_horizon_months', fn($m) => is_page('summer') ? 6 : $m);. Out-of-range returns are ignored. Callers that pass an explicit to_date are not affected. |
yatra_get_dynamic_pricing_display_settings | filter | Customize how dynamic-pricing surcharges/discounts render |
yatra_calculate_demand_scores | action | Override demand-score calculation (Pro) |
Bookings
Lifecycle and per-booking rendering.
| Hook | Type | Purpose |
|---|---|---|
yatra_booking_created | action | New booking submitted |
yatra_booking_updated | action | Booking row updated |
yatra_booking_status_changed | action | Every status transition. Args: ($bookingId, $oldStatus, $newStatus) |
yatra_booking_confirmed | action | Booking reached confirmed. Args: ($bookingId, $booking) |
yatra_booking_cancelled | action | Booking reached cancelled — admin, customer, unpaid-booking sweep or OTA. Args: ($bookingId, $booking) |
yatra_booking_expired | action | An unpaid booking was auto-cancelled by the expiry sweep. Args: ($bookingId) |
yatra_auto_expire_bookings | filter | Return false to disable the unpaid-booking expiry sweep |
yatra_booking_deleted | action | Before a booking is deleted |
yatra_booking_email_variables | filter | Augment the merge-tag map for booking emails |
yatra_booking_email_traveler_identity_field_keys | filter | Customize identity-table fields |
yatra_payment_completed | action | Fired across multiple gateways after capture |
Booking pricing pipeline
The price you see on the booking summary is the result of a chain of filters. Hooking these lets you adjust the math without touching gateway code.
| Filter | Stage |
|---|---|
yatra_before_calculation_params | Normalize incoming traveler counts, picked date, etc. |
yatra_booking_trip_price | Per-trip base price |
yatra_calculate_subtotal | After traveler categories, before extras |
yatra_booking_additional_services | Pro Additional Services subtotal |
yatra_calculate_payment_amounts | Compute deposit / partial / total payable now |
yatra_after_calculation_result | Final adjustments |
yatra_booking_email_variables | Variables passed to email templates |
The implementation lives in app/Services/CalculationService.php. Each filter receives the partial result and the booking context.
Payments
| Hook | Type | Purpose |
|---|---|---|
yatra_register_payment_gateways | action | Register a custom gateway class |
yatra_payment_gateway_config_saved | action | After a gateway's settings save |
yatra_before_payment_processing | action | Before a payment intent is created |
yatra_price_unit_label | filter | (string $label, string $unit, ?array $priceType) — wording shown next to a price: "per person" or "per group (1-2 pax)" ($unit is per_person / per_group). Return e.g. "per tour". |
yatra_payment_completed | action | After successful capture. Since Yatra 3.0.15 also fired when an admin-recorded payment becomes Completed (payload adds payment_id, source => 'manual', send_emails) |
yatra_send_manual_payment_emails | filter | (bool $send, int $bookingId, array $payment) — return false to keep the customer/admin "payment received" emails off for admin-recorded payments; yatra_payment_completed still fires with send_emails => false |
yatra_payment_failed | action | After failed capture |
yatra_after_payment_processing | action | Final hook after payment processing succeeds |
yatra_paypal_payment_completed | action | PayPal-specific success |
yatra_paypal_payment_refunded | action | PayPal-specific refund (use this instead of a generic yatra_payment_refunded — Yatra fires per-gateway refund actions) |
yatra_razorpay_refund_created | action | Razorpay-specific refund |
yatra_payment_amount_mismatch | action | (3.0.4+) Fires when a client-supplied amount in POST /payment/create-intent disagreed with the server's booking.amount_due. Args: ($booking_id, $client_amount, $server_amount). The transaction itself is forced to the server amount; this hook exists for fraud-monitoring integrations. |
yatra_pdf_remote_enabled | filter | (3.0.4+) Enable / disable dompdf remote image loading. Default true so PDFs can render the site logo and trip images. Return false to lock the PDF generator down to ABSPATH only (recommended if your invoices never contain external images). |
yatra_pro_writable_settings_schema | filter | (3.0.4+) Pro-only. Receives key => sanitizer-callable map of settings keys the POST /yatra/v1/settings REST endpoint is allowed to write. Modules can register their own keys here; anything not in this map is silently rejected by the endpoint. |
yatra_pass_gateway_ids_for_scheduled_payments | filter | Whether to forward the gateway's customer / payment-method IDs into the scheduled-payments pipeline even when save_card was off. Useful for gateways that auto-vault. |
yatra_confirm_booking_on_payment | filter | Override whether a successful payment auto-confirms the booking, on top of the Auto-Confirm mode. Args: ($shouldConfirm, bool $fullyPaid, int $bookingId, bool $autoConfirm). Default $shouldConfirm is true for mode all, or mode online when the balance is fully paid. $autoConfirm keeps its original meaning — the old on/off toggle, i.e. true only for mode all — so callbacks written against 3.0.10–3.0.14 behave the same; read the full mode with yatra_get_auto_confirm_mode() if you need to tell online from none. Example — confirm on any full payment regardless of mode: `add_filter('yatra_confirm_booking_on_payment', fn($c, $full) => $c |
Stripe-specific actions (Pro)
Fired only when the verified Stripe webhook handler dispatches a known event. Verification is HMAC-SHA256 against the configured webhook_secret with a 5-minute replay window — handlers attached here only ever see real, signed Stripe events.
| Hook | Type | Purpose |
|---|---|---|
yatra_stripe_payment_succeeded | action | (3.0.4+) payment_intent.succeeded. Receives the full PaymentIntent object as an array. |
yatra_stripe_payment_failed | action | (3.0.4+) payment_intent.payment_failed. Args: PaymentIntent object as array. |
yatra_stripe_charge_refunded | action | (3.0.4+) charge.refunded. Args: Charge object as array. |
Adding a custom gateway
The minimal recipe:
add_action( 'yatra_register_payment_gateways', function ( $registry ) {
$registry->register( 'my_gw', \My\Gateway\MyGateway::class );
} );Your MyGateway extends \Yatra\PaymentGateways\AbstractPaymentGateway and implements id, name, description, getConfigFields, processPayment, optionally processRefund and handleWebhook. See app/PaymentGateways/Gateways/PayPal/PayPalGateway.php for a complete reference.
Email
| Hook | Type | Purpose |
|---|---|---|
yatra_email_merge_tag_definitions | filter | (3.0.5+) Central merge-tag registry. Append / amend rows in Yatra\Services\EmailMergeTagRegistry. Tags added here automatically surface in the Pro Template Editor sidebar for every event they declare in events. Must be paired with a dispatcher-side injection (e.g. yatra_booking_email_variables) so the value actually renders. |
yatra_email_template_variables_catalog | filter | (3.0.5+) Legacy hook — applied AFTER the registry is grouped for the REST /email-templates/variables endpoint. Prefer yatra_email_merge_tag_definitions for new code. |
yatra_email_event_variables | filter | (3.0.5+) Extend the per-event variable whitelist for a single event. Args: (array $keys, string $eventKey). Keys not already in the registry surface in an "event-specific" group on the sidebar. |
yatra_send_transactional_email | filter | Short-circuit before sending; return false to suppress |
yatra_pro_email_automation_owns_transactional_type | filter | Let Pro Email Automation own a specific template type |
yatra_booking_email_variables | filter | Final mutation point for booking-event variables (after variablesFromBooking() + rich tags). Args: (array $variables, object $booking). |
yatra_email_template_trip_variables | filter | Add or rewrite the per-trip merge tags available to email templates |
yatra_email_template_preview_variables | filter | Same, for the template preview pane |
yatra_send_booking_status_email_html | filter | Rendered HTML for booking-status emails before send |
yatra_email_template_enquiry_admin / _received / _response | filter | Override the rendered HTML per enquiry email template |
Adding a merge tag end-to-end
The registry is the single source of truth — adding a tag means registering it AND wiring up the dispatcher value. Skip step 2 and your tag will render as an empty string; skip step 1 and the sidebar won't surface it.
// 1. Declare the tag so the editor sidebar lists it for the right events.
add_filter( 'yatra_email_merge_tag_definitions', function ( array $catalog ) {
$catalog['gst_invoice_number'] = [
'key' => 'gst_invoice_number',
'label' => 'GST Invoice Number',
'description' => 'Tax-invoice number printed on the GST receipt.',
'category' => 'booking',
'sample' => 'GST-2025-00042',
'events' => [ 'booking.created', 'booking.confirmed', 'payment.received' ],
];
return $catalog;
} );
// 2. Inject the real value so the rendered email actually contains it.
add_filter( 'yatra_booking_email_variables', function ( array $vars, $booking ) {
$vars['gst_invoice_number'] = (string) get_post_meta( $booking->id, '_gst_invoice_number', true );
return $vars;
}, 10, 2 );Enquiries
| Hook | Type | Purpose |
|---|---|---|
yatra_enquiry_created | action | After enquiry insert (carries the joined trip object since 3.0.3) |
yatra_enable_enquiry | filter | Master toggle for enquiry UI on the trip page |
yatra_enquiry_button_text | filter | Customise the "Make an Enquiry" CTA copy |
yatra_enquiry_form_show | filter | Show / hide the enquiry form per trip |
yatra_enquiry_form_title_text | filter | Override the enquiry form title |
yatra_email_template_enquiry_admin | filter | Rendered HTML for the admin enquiry notification |
yatra_email_template_enquiry_response | filter | Rendered HTML for the customer response email |
Account / customer
| Hook | Type | Purpose |
|---|---|---|
yatra_customer_created | action | New customer record |
yatra_customer_updated | action | After customer edit |
yatra_user_id | filter | Resolve the user ID for a customer / booking flow |
yatra_user_allowed_to_login | filter | Block / allow a specific user from the front-end login flow |
yatra_login_redirect_url | filter | Redirect destination after a successful login |
Front-end routing & templates
Yatra registers its own pretty URLs for the booking flow, account, email verification and remaining-balance checkout.
| Hook | Type | Purpose |
|---|---|---|
yatra_pretty_route_match | filter | Modify how a route resolves (final say on tab/template) |
yatra_plain_route_match | filter | Same but for ?yatra_* query-string URLs |
yatra_frontend_request_path | filter | Normalize the request path before matching |
yatra_register_rewrite_rules | action | Add additional rewrite rules |
yatra_build_archive_listing_url | filter | Override how Yatra builds catalog listing URLs |
yatra_get_trip_listing_url | filter | Override the URL Yatra generates for the trip archive |
Shortcodes and listings
| Hook | Type | Purpose |
|---|---|---|
yatra_trip_listing | filter | The full listing object Yatra renders into the trip catalog |
yatra_trip_listing_context | filter | The context array passed to the trip card template |
yatra_trip_listing_max_per_page | filter | Cap on the per_page shortcode attribute |
yatra_is_trip_listing | filter | Override Yatra's "are we on the trip-listing page" detection |
yatra_listing_nonce | filter | Customise the nonce field used inside listing-form posts |
Want to customise card markup?
Yatra doesn't currently expose a stable *_card_html filter for whole-card replacement. The supported customisation paths are: (1) override the card template in your child theme — copy templates/partials/trip-card.php into wp-content/themes/{your-theme}/yatra/partials/trip-card.php; or (2) hook into the listing-context filter above to mutate the variables the card template sees.
Frontend templating & block themes (FSE)
Yatra renders its own URL paths (/trips/, /trip/{slug}/, /book/, /my-account/, etc.) with a custom router rather than via real WordPress post types. The following extension points exist so themes and other plugins can integrate cleanly — particularly with Full Site Editing block themes.
| Hook | Type | Purpose |
|---|---|---|
pre_handle_404 (core hook, Yatra uses) | filter | Yatra short-circuits this for its own URLs so WP::handle_404() never sets is_404 = true for plugin pages. Return true from your own callback (priority < 10) to opt a custom URL in. |
body_class | filter | Yatra strips error404 for its pages and adds yatra-page plus a yatra-page-{type} class (e.g. yatra-page-trip). |
template_include | filter | Yatra hooks at priority 99. If a request matched a Yatra route, the chosen PHP template is returned here. Customise via yatra_template_path below or with a theme override at your-theme/yatra/{template}.php. |
yatra_template_path | filter | ($absolute_path, $template_name, $page_type) — last chance to swap the PHP file before it's included. Useful for shipping a template variant from another plugin. |
yatra_register_rewrite_rules | action | Fires after Yatra registers its rewrite tags and rules. Receives the resolved permalink bases. |
FSE / Site Editor
Yatra registers virtual block templates (Single Trip, Trip Listing, Destination, Activity, Booking, Booking Confirmation, My Account) so admins can find and customise Yatra layouts under Appearance → Editor → Templates.
- The customisation is saved by core as a
wp_templatepost. On the next request, Yatra detects it and renders that block template instead of the bundled PHP template. - Block templates embed a server-side block called Yatra Page Content (
yatra/page-content). At render time it includes the PHP template selected by Yatra's router, so customising the chrome (header / sidebar / footer placement) is fully editable while the content stays driven by Yatra. - Inside that block,
yatra_get_header()andyatra_get_footer()are no-ops — the canvas already emits the document and header/footer parts, so the PHP template only contributes its inner content.
Theme overrides without the editor
Drop a copy of any template at wp-content/themes/{your-theme}/yatra/{name}.php and locate_template() will pick it up first. No filter wiring needed. This works for classic and block themes alike.
Admin / settings / modules
| Hook | Type | Purpose |
|---|---|---|
yatra_admin_localized_data | filter | Inject extra props into window.yatraAdmin. Pro modules use this to expose flags like flexiblePaymentsEnabled so the React admin can conditionally render Pro-gated UI. |
yatra_module_active | action | When a module is enabled |
yatra_module_deactive | action | When a module is disabled |
yatra_module_enabled_status | filter | Authoritative is-this-module-enabled check |
yatra_module_capabilities | filter | Module-required capabilities |
yatra_module_assets | filter | Assets enqueued for a module |
yatra_default_modules | filter | Add to / remove from the default module registry |
yatra_enable_setup_wizard | filter | Show / hide the setup wizard |
yatra_clear_cache | action | Invalidate Yatra's internal cache |
Pro license & updater
| Hook | Type | Purpose |
|---|---|---|
yatra_is_pro_active | filter | Toggle Pro behavior (Pro returns true; you can short-circuit for testing) |
yatra_pro_available_modules | filter | Add or remove modules from the Modules screen |
yatra_pro_license_store_url | filter | Override the license store URL |
yatra_pro_license_item_id | filter | Override the EDD product ID |
yatra_pro_license_data_updated | action | After license data is saved |
yatra_pro_module_activated | action | After a Pro module activates (creates tables, etc.) |
yatra_pro_module_settings_updated | action | After a Pro module's settings save |
Pro: Dynamic Pricing
| Hook | Type | Purpose |
|---|---|---|
yatra_dynamic_pricing_enabled | filter | Whether DP applies to a given trip |
yatra_get_dynamic_pricing_display_settings | filter | Display settings for surcharge/discount badges |
yatra_price_breakdown | filter | The breakdown shown on the booking summary |
yatra_calculate_demand_scores | action | Override / extend demand calculation |
Pro: Flexible / Scheduled Payments
| Hook | Type | Purpose |
|---|---|---|
yatra_flexible_payments_enabled | filter | Master toggle (per-trip or globally) |
yatra_flexible_payment_setting | filter | Read individual setting values |
yatra_deposit_percentage | filter | ($default, $context = []) — Override deposit %. $context['trip_id'] lets the Pro module honour per-trip trip.deposit_percentage |
yatra_partial_payment_percentage | filter | ($default, $context = []) — Override partial-payment % (context unused today; passed for parity) |
yatra_calculate_amount_due | filter | ($amount_due, $total_amount, $payment_method, $context = []) — Final say on the payable-now amount. $context['trip_id'] lets Pro apply per-trip trip.deposit_amount (absolute) or trip.deposit_percentage |
yatra_payment_method_options | filter | ($options, $booking_data) — Adds Pay X% Deposit / Pay X% Now radios to the booking form. $booking_data['trip_id'] lets Pro show the deposit option whenever a trip has per-trip values, even with the global flag off |
yatra_scheduled_payments_module_active | filter | Whether scheduled payments processing should run |
yatra_scheduled_payment_setting | filter | Per-setting reads |
yatra_scheduled_payment_success | action | A scheduled (installment / balance) charge succeeded. Args: (int $scheduledPaymentId, array $gatewayResult, array $context). The first arg is the scheduled-payment row id, not the booking — read $context['booking_id']. $context also carries scheduled_payment_id, payment_id, amount, currency, gateway, method, transaction_id, payment_type, amount_due, fully_paid, plus the display-ready scheduled_amount_formatted, scheduled_date_formatted, payment_type_label, balance_after_formatted (formatted identically to the transactional email). Webhooks, WhatsApp and Email Automation bind their Scheduled payment succeeded event here. |
yatra_scheduled_payment_failed | action | A scheduled charge failed ($context['permanent'] is true once max attempts is reached). Args: (int $scheduledPaymentId, string $error, array $context) — the first two are unchanged from earlier releases; $context (booking_id, scheduled_payment_id, reason, error, failure_reason, permanent, gateway, amount, currency, payment_type, scheduled_amount_formatted, scheduled_date_formatted, payment_type_label) is new. Read the booking from $context['booking_id'], never from the first arg. |
Per-trip overrides
The $context argument added to yatra_deposit_percentage, yatra_calculate_amount_due, and yatra_payment_method_options since Yatra Free 3.0.5 / Pro 3.0.3 is what lets the Flexible Payments module read trip.deposit_amount / trip.deposit_percentage for a specific booking. If you implement your own filter callback that ignores $context, you'll only get site-wide behaviour — which is fine, but match the new signature if you want trip-aware behaviour.
Pro: Email Automation
| Hook | Type | Purpose |
|---|---|---|
yatra_pro_email_automation_owns_transactional_type | filter | Let Pro Email Automation own a specific template type so Pro's send pipeline runs instead of the free one |
Trip-specific override templates (Pro Email Automation) need no new hook: the module resolves the override inside its existing yatra_send_transactional_email takeover, using the trip_id merge variable the free plugin now puts in every booking email's variables (TransactionalEmailTemplateService::variablesFromBooking(), free 3.0.16+; older free plugins are handled by looking the trip up from booking_id). An override is a normal yatra_email_templates row whose settings JSON carries overrides (the global key), targets (trips / categories / trip_types) and priority; its event_key is stored empty so older Pro builds ignore it. REST: POST /email-templates/{id}/override, POST /email-templates/overrides/reorder, GET /email-templates/resolve?trip_id=N; preview and test accept trip_id.
Looking for sequence-step or payload filters?
Yatra's source emits sequence events through the email-template filter chain (see the Email section above). If you need pre-send mutation, hook into yatra_send_transactional_email (returns false to suppress) or the per-template filters like yatra_email_template_trip_variables.
Pro: Custom Landing Pages
| Hook | Type | Purpose |
|---|---|---|
yatra_destination_permalink | filter | Override the destination URL |
yatra_activity_permalink | filter | Override the activity URL |
yatra_category_permalink | filter | Override the trip-category URL |
Pro: Trip Consent
| Hook | Type | Purpose |
|---|---|---|
yatra_consent_signed | action | After a customer signs a consent form |
Customise consent email copy
The consent-request email is a normal Yatra template (trip_consent_request). Override the body via Settings → Email → Templates, or hook into yatra_email_template_trip_variables to rewrite the merge-tag values it receives.
Pro: Dynamic Form Field
| Hook | Type | Purpose |
|---|---|---|
yatra_booking_form_config | filter | The merged booking-form configuration as read by checkout, validation and the admin. Args: (array $config, ?int $tripId). $tripId (free 3.0.16+) is the trip being booked, or null when there is no trip context (the Settings editor). The Pro module uses it to resolve each section's per-trip conditions — the first condition matching the trip supplies the section's title, description and fields, and the raw conditions list is removed from the resolved config. Callbacks registered with one argument keep working. |
yatra_save_booking_form_config | filter | Runs on save, after the free sanitiser. Args: (array $sanitized, array $original). Use it to persist your own per-field keys from $original. |
yatra_dynamic_form_field_enabled | filter | Module on/off as seen by the free plugin (window.yatraAdmin.dynamicFormFieldEnabled). |
A section's conditions are stored as conditions => [ [ 'id', 'targets' => ['trips' => [ids], 'categories' => [ids], 'trip_types' => ['single_day'|'multi_day']], 'title', 'description', 'fields' => [...] ], ... ] and sanitised by the free plugin like the section's own fields. Read a trip's resolved config with yatra_get_booking_form_config( $trip_id ) or GET /yatra/v1/settings/booking-form?trip_id=N (readable by anyone who can view bookings); the argument-less call / request returns the global config with its conditions.
Pro: Additional Services
| Hook | Type | Purpose |
|---|---|---|
yatra_booking_additional_services | filter | Mutate selected services on a booking |
yatra_booking_save_services | action | After services are persisted |
yatra_booking_get_services | filter | Modify how services are fetched for display |
Practical recipes
Send a Slack notification on every booking
add_action( 'yatra_booking_created', function ( $booking_id ) {
$booking = yatra_get_booking( $booking_id );
if ( ! $booking ) return;
wp_remote_post( SLACK_WEBHOOK_URL, [
'body' => wp_json_encode( [
'text' => sprintf(
'New booking %s for %s · %d travelers · %s',
$booking->reference,
$booking->trip_title,
$booking->traveler_count,
yatra_price_html( $booking->total )
),
] ),
'headers' => [ 'Content-Type' => 'application/json' ],
] );
}, 10, 1 );Add 5% surcharge to all bookings on weekends
add_filter( 'yatra_booking_trip_price', function ( $price, $context ) {
$departure = $context['departure_date'] ?? null;
if ( ! $departure ) return $price;
$day = (int) date( 'N', strtotime( $departure ) );
if ( $day >= 6 ) { // Sat / Sun
$price *= 1.05;
}
return $price;
}, 10, 2 );Hide trips from a specific destination on a public listing
add_filter( 'yatra_trip_listing_filters', function ( $filters ) {
if ( is_admin() || ! empty( $filters['private_view'] ) ) return $filters;
$filters['exclude_destination'] = [ 99 ]; // hide destination ID 99 from public listings
return $filters;
} );Auto-tag Mailchimp subscribers based on the trip booked
add_action( 'yatra_booking_created', function ( $booking_id ) {
$booking = yatra_get_booking( $booking_id );
if ( ! $booking ) return;
$tag = sprintf( 'trip-%s', sanitize_title( $booking->trip_title ) );
do_action( 'yatra_mailchimp_add_tag', $booking->customer_email, $tag );
} );Block weekend bookings of a specific trip
add_filter( 'yatra_resolve_availability_object', function ( $availability, $trip_id, $date ) {
if ( $trip_id !== 42 ) return $availability;
$day = (int) date( 'N', strtotime( $date ) );
if ( $day >= 6 ) {
$availability['available'] = false;
$availability['message'] = 'This trip runs Mon–Fri only.';
}
return $availability;
}, 10, 3 );Discovering more hooks
cd wp-content/plugins/yatra
# All actions:
grep -rn "do_action\(\s*'yatra_" app/ | sort -t: -k1
# All filters:
grep -rn "apply_filters\(\s*'yatra_" app/ | sort -t: -k1Most hooks have a short docblock explaining the arguments and intent. The cleanest summary lives at the call site rather than in a separate hook reference, so reading the source is the canonical move when you're stuck.