Galle, LK--:--5/6 sites live

Transparent Pricing and OTA Deep Links

A deterministic nightly rate from season, occupancy and lead time — with its reasoning attached — and honest Agoda / Booking.com search links instead of scraping.

18 Oct 20264 min read#Pricing#OTA#Tourism

Lesson 8 of 10 · Tourism Tech · built from Nora Travels, Nora Labs, Mahesh Travellers and my hospitality sites

Two rules for money on a travel site: explain every number, and never claim data you don't have.

Example — a rate with its reasoning

ExamplePython
def dynamic_rate(destination, stay_date, velocity_14d=0, lead_days=None):
    """Rolling-14-day velocity + seasonality + lead time → transparent nightly rate."""
    base = destination["avg_nightly_lkr"] or 9000
    occ = occupancy_forecast(destination, stay_date, velocity_14d)
    season = seasonal_factor(stay_date.month)
    demand_mult = 1 + (occ - 0.55) * 0.55
    lead = lead_days if lead_days is not None else (stay_date - date.today()).days
    lead_mult = 1.12 if lead <= 3 else 1.04 if lead <= 10 else 0.96 if lead >= 60 else 1.0
    rate = int(round(base * season * demand_mult * lead_mult / 100.0) * 100)
    return {
        "base_lkr": base, "dynamic_lkr": rate,
        "explanation": f"Base LKR {base:,} adjusted by season x{season:.2f}, "
                       f"forecast occupancy {occ:.0%} and {lead}-day lead time.",
    }

Same destination and date → same rate, every time. The explanation travels with the number.

ExamplePython
def booking_url(destination, *, checkin=None, checkout=None, nights=2, adults=2,
                children=0, rooms=1, currency="LKR", filters=None, max_price=None):
    ci = _parse_date(checkin)
    co = _parse_date(checkout, ci + timedelta(days=max(1, nights)))
    params = {
        "ss": f"{destination}, Sri Lanka", "checkin": _iso(ci), "checkout": _iso(co),
        "group_adults": adults, "group_children": children, "no_rooms": rooms,
        "selected_currency": currency, "lang": "en-gb",
    }
    if max_price:
        params["nflt"] = f"price={currency}-min-{max_price}-1"
    aid = get_settings().affiliate_booking          # optional affiliate ID from config
    if aid:
        params["aid"] = aid
    return "https://www.booking.com/searchresults.html?" + urlencode(params, quote_via=quote)

A natural-language parser turns "eco stay in Sinharaja for 3 nights, 2 adults, under LKR 12000 with breakfast" into these parameters, and an itinerary gets one deep link per overnight stop.

Exercise

Add a min_review_score parameter. Booking.com expects it ×10 — why might an API use integers like that?


Keep going: ← Lesson 7 · Lesson 9 →

ExerciseKnowledge check

What does Nora Labs' OTA agent do with Booking.com?

Finished this one?

Progress is saved in this browser.

Guide