Self-Storage Rate Change Monitor | Web Rates & Promos
Under maintenancePricing
$25.00 / 1,000 unit rate extracteds
Self-Storage Rate Change Monitor | Web Rates & Promos
Under maintenanceMonitor supplied public self-storage facility pages for qualified changes to monthly web rates, promotions, and availability.
Pricing
$25.00 / 1,000 unit rate extracteds
Rating
0.0
(0)
Developer
Blake Panter
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 days ago
Last modified
Categories
Share
Track competitor self-storage pricing on facility pages you already know. Each paid result is an initial qualified monthly-rate observation or a later rate, promotion, or availability change—not every price found on the page.
Output includes previous/current values, source evidence, change type, and a stable deduplication key.
This Actor monitors only supplied public self-storage facility pages. It does not discover facilities, render JavaScript-only booking portals, or guarantee support for every operator's markup.
What qualifies as output
A unit card must contain both a recognizable size (for example, 5x10) and a dollar amount explicitly labelled as a web, online, monthly, or per-month rate. Move-in prices, savings amounts, insurance prices, and other unlabelled dollar values are not treated as monthly rates. Output includes rateEvidence and qualification so the parser decision is auditable.
Same-size units remain distinct only when stable page evidence—a unit identifier, climate/drive-up features, or unit type—distinguishes them. Exact duplicate markup collapses to one observation. If multiple cards have the same stable identity dimensions but conflicting rates or availability, all of those ambiguous cards are rejected; the Actor does not use DOM order or a current price to invent identities.
Input
{"startUrls": [{ "url": "https://operator.example/public-facility-page" }],"maxPages": 25,"maxItems": 100,"requestTimeoutSecs": 30,"maxHtmlBytes": 500000,"outboxCapacity": 1000,"snapshotCapacity": 10000}
maxPageslimits fetched URLs;maxItemsindependently limits paid events delivered in a run.maxHtmlBytesis a strict per-page byte bound. Oversized or incomplete HTML is rejected rather than parsed after truncation.- Only public HTTP(S) URLs on standard ports are accepted. Initial URLs and every redirect are DNS-checked; private, loopback, link-local, reserved, metadata, credential-bearing, and non-HTTP(S) destinations are rejected.
- Pages must return HTML. Individual fetch failures are skipped.
Stateful monitoring and delivery
State is stored in the named key-value store self-storage-price-monitor-state.
- A qualified unit first emits an
initialevent. - An unchanged repeat emits nothing.
- A changed monthly rate, availability value, or promotion emits a corresponding change event.
- Pending events are drained before newer observations are staged.
Delivery is at least once. An event is written to a bounded persistent outbox before PPE output and acknowledged only after Actor.pushData succeeds. A crash between output acceptance and acknowledgement can duplicate an event, so consumers should deduplicate using the stable dedupeKey. Each newly staged occurrence receives a durable monotonic occurrenceSequence: retries retain the same sequence and key, while later recurring transitions such as $10 → $20 → $10 → $20 receive distinct keys. Legacy state is migrated without rewriting pending retry keys. Full state capacities apply backpressure; the Actor does not silently evict unpaid work or tracked history. Avoid overlapping runs against the same state store.
Output contract
The dataset and Actor output schemas are wired in .actor/actor.json. An illustrative event shape is:
{"changeType": "rate_changed","changedFields": ["webRateAmount"],"facilityName": "Operator name from page","unitId": "A-101","unitSize": "5x10","climateControlled": true,"driveUp": false,"webRate": "$89.00","webRateAmount": 89,"previousWebRateAmount": 79,"currency": "USD","available": true,"qualification": "qualified-monthly-rate","rateEvidence": "Web rate $89.00 / month","sourceUrl": "https://operator.example/public-facility-page","detectedAt": "2026-08-26T12:00:00.000Z","identityKey": "...","occurrenceSequence": 42,"dedupeKey": "..."}
This is an illustrative contract example, not evidence from a live operator run.
Charging
The PPE event name is rate-change. Only records that pass the monthly-rate qualification gate reach Actor.pushData. maxItems is checked before staging newer payable work, and eventChargeLimitReached stops delivery immediately after the accepted event is acknowledged.
Supported and unsupported pages
The lightweight HTML parser recognizes common server-rendered unit cards (article, list/table rows, and common unit/rate classes). JavaScript-only inventory, bot challenges, login pages, booking/checkout flows, and operator-specific API calls are outside the current scope. Verify events against sourceUrl before making pricing decisions.
Local verification
The build uses exact direct dependency versions, a committed package-lock.json, npm ci, and a digest-pinned Node.js 24 image with npm 12.0.2. TypeScript is executed with tsx; tests use Vitest and linting uses Oxlint.
npm cinpm run lintnpm testnpm run typechecknpx --yes apify-cli validate-schema
Schema validation intentionally uses the Apify CLI's supported no-argument project command, which validates the input, dataset, and output schemas wired in .actor/actor.json. Passing dataset/output schema paths would incorrectly validate them as input schemas.
Tests use multiple local operator-style fixtures; no claim of current live-site compatibility is made from those fixtures.