Construction Company Website Development on 1C-Bitrix
A construction company website is not a business card with a phone number and a photo of an excavator. A general contractor operates in two directions simultaneously: a homeowner looking for a renovation crew and a corporate client submitting a 40-page RFQ for a warehouse build. Both scenarios demand different content structures, different contact forms, and different levels of technical detail. Bitrix can serve both audiences from a single site, but the data architecture must account for this duality from day one.
Service Catalog: Info Block Structure
Construction services are inherently hierarchical. There are categories (residential, commercial, industrial, renovation and reconstruction) and specific services within each (cottage construction, steel-frame building, office overhaul). Each service has parameters that a potential client wants to see before picking up the phone.
Info block SERVICES with sections by category:
- Residential construction — cottages, townhouses, low-rise buildings
- Commercial construction — office buildings, retail centers, warehouses
- Industrial construction — production facilities, hangars
- Renovation and reconstruction — major repairs, facade restoration, space reconfiguration
Element properties for a service:
| Property | Code | Type | Purpose |
|---|---|---|---|
| Description | DESCRIPTION | HTML | Detailed service description |
| Photo gallery | PHOTO_GALLERY | F (file, multiple) | Process and result photos |
| Typical timeline | TYPICAL_TIMELINE | S (string) | "3 to 8 months" |
| Minimum area | MIN_AREA | N (number) | Entry threshold, sqm |
| Materials | MATERIALS | E (element link) | Link to materials info block |
| Client category | CLIENT_TYPE | L (list) | B2B / B2C / Both |
| Icon | ICON_SVG | S | SVG icon code for catalog display |
The CLIENT_TYPE property is critical for frontend filtering: a homeowner doesn't want to see "industrial facility design," and a procurement manager doesn't want "bathroom renovation." Filtering via bitrix:catalog.smart_filter with FILTER_NAME=arrServiceFilter and a custom template that renders a "For Home / For Business" toggle instead of a standard checkbox.
Completed Projects Portfolio
The portfolio lives in a separate info block PORTFOLIO — not as a subsection of services. Reason: a project has its own data structure that doesn't overlap with a service description. A project is a specific object with an address, client, timeline, and square footage. A service is a description of a capability.
Portfolio element properties:
| Property | Code | Type |
|---|---|---|
| Before photos | PHOTO_BEFORE | F (file, multiple) |
| After photos | PHOTO_AFTER | F (file, multiple) |
| Object area | OBJECT_AREA | N |
| Execution time | EXECUTION_TIME | S |
| Materials used | USED_MATERIALS | S (multiple) |
| Client testimonial | CLIENT_TESTIMONIAL | HTML |
| Service link | SERVICE_LINK | E (link to SERVICES info block) |
| Coordinates | COORDINATES | S ("lat,lng") |
| Completion year | COMPLETION_YEAR | N |
The SERVICE_LINK binding is the key relationship. On the "Cottage Construction" service page, related projects load automatically via CIBlockElement::GetList with filter ['PROPERTY_SERVICE_LINK' => $serviceId]. On the portfolio map — clustered markers via ymaps.Clusterer; clicking a marker opens a popup with the "after" photo, area, and a link to the full project card.
Before/after comparison on the project card uses a JavaScript slider component: two images in a container with overflow: hidden, one clipped via clip-path or absolute positioning. A mousedown/touchstart handler on the divider moves the clipping boundary.
Cost Calculator: Deep Dive
The calculator is the highest-converting element on a construction company website. Visitors don't want to call just to learn the order of magnitude. They want to drag sliders and watch the total change. A multi-step form with AJAX calculation at each stage is the right approach.
Calculator architecture. Four steps:
- Work type — select from list: new construction, major renovation, reconstruction, finishing
- Object parameters — area (slider + manual input), number of floors, foundation type (for new construction), current condition (for renovation)
- Materials — preset packages: economy, standard, premium; or manual selection by category (walls, roofing, finishing)
- Result — cost range, estimated timeline, "Get a Detailed Estimate" button
Storing rate coefficients. Base rates and multipliers live in a Highload block CALC_RATES:
| Field | Type | Example |
|---|---|---|
| UF_WORK_TYPE | list | new_build, renovation, reconstruction |
| UF_MATERIAL_CLASS | list | economy, standard, premium |
| UF_BASE_RATE | number | 450 (USD/sqm) |
| UF_FLOOR_COEFF | number | 1.15 (multiplier for 2+ floors) |
| UF_FOUNDATION_COEFF | number | 1.20 (strip) / 1.35 (slab) |
| UF_REGION_COEFF | number | 1.0 (capital) / 0.85 (regions) |
A manager updates coefficients through the Highload block admin interface — no developer needed. A new work type means a new row in the block; the calculator picks it up automatically.
Server side. A custom component project:calc.estimate with an AJAX controller. Bitrix provides AJAX handling via Bitrix\Main\Engine\Controller:
namespace Project\Component;
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Engine\ActionFilter;
class CalcEstimateController extends Controller
{
public function configureActions(): array
{
return [
'calculate' => [
'prefilters' => [
new ActionFilter\HttpMethod([ActionFilter\HttpMethod::METHOD_POST]),
new ActionFilter\Csrf(),
],
],
];
}
public function calculateAction(
string $workType,
float $area,
int $floors,
string $materialClass,
string $foundation = ''
): array {
$rates = HighloadManager::getRow('CALC_RATES', [
'UF_WORK_TYPE' => $workType,
'UF_MATERIAL_CLASS' => $materialClass,
]);
if (!$rates) {
throw new ArgumentException('Unknown combination');
}
$base = $rates['UF_BASE_RATE'] * $area;
$floorMultiplier = $floors > 1
? pow($rates['UF_FLOOR_COEFF'], $floors - 1)
: 1.0;
$foundationMultiplier = 1.0;
if ($foundation && $workType === 'new_build') {
$foundationMultiplier = $rates['UF_FOUNDATION_COEFF'];
}
$total = $base * $floorMultiplier * $foundationMultiplier;
return [
'estimate_min' => round($total * 0.85),
'estimate_max' => round($total * 1.15),
'timeline_weeks' => $this->estimateTimeline($workType, $area),
'breakdown' => [
'base' => round($base),
'floor_adjustment' => round($base * ($floorMultiplier - 1)),
'foundation_adjustment' => round(
$base * $floorMultiplier * ($foundationMultiplier - 1)
),
],
];
}
}
Frontend flow. Each step is a separate screen with a transition animation. Steps 1-3 accumulate data in a state object. Step 2 fires an AJAX request for dynamic option updates — selecting "new construction" reveals a foundation type picker; selecting "renovation" shows a current-condition dropdown. Step 4 sends the full parameter set to calculateAction.
The result displays as a range: "from $120,000 to $163,000." Not a single number — this matters legally and commercially. Below it, a breakdown: base cost, floor surcharge, foundation surcharge. The client sees what goes into the estimate and understands where they can cut costs.
Saving calculations. Every calculation is written to a Highload block CALC_RESULTS with fields: input parameters, result, timestamp, IP address, UTM tags. This feeds analytics: which work types are calculated most often, what's the average requested budget, at which step users drop off (if step 4 is never reached — log it on beforeunload). UTM tags tie calculations to ad campaigns.
The "Get a Detailed Estimate" button opens a form with fields: name, phone, email, comments. On submit — a CRM lead is created (if Bitrix24 is connected) or an email fires via CEvent::Send() with mail event type CALC_REQUEST. The email body automatically includes all calculation parameters — the manager doesn't need to ask again.
Tender/RFQ System for B2B
A corporate client doesn't arrive with "how much does it cost" — they arrive with a 40-page technical specification. They need a submission form with file uploads.
The tender form is a custom component built on bitrix:form.result.new or a standalone controller. Fields: company name, tax ID, contact person, email, phone, project description (textarea), specification files (multiple upload, up to 5 files, PDF/DOC/DWG/ZIP, 50MB total limit). Frontend validation checks extensions and size before submission. Backend — a second pass via CFile::CheckFile().
Uploaded files are saved to the TENDER_REQUESTS info block as an element with file-type properties. Mail event TENDER_NEW_REQUEST notifies the responsible manager. An auto-reply to the applicant — a separate mail event TENDER_CONFIRM with the text "Your request #ID has been received; expect a response within 2 business days."
Certificates, Licenses, Permits
For a construction company, the licenses section isn't decoration. SRO membership, ISO certifications, design licenses — clients verify these before signing a contract. Info block CERTIFICATES with minimal fields: document name, number, issue date, expiration date, scan (file). Frontend — a gallery with full-size scan viewing via lightbox. Expiration tracking via a CAgent: 30 days before expiry — admin notification.
Team with Specialization Binding
Info block TEAM linked to services via a multiple property SPECIALIZATION (type E, bound to SERVICES info block). On an employee page — their projects from the portfolio (linked via PROPERTY_MANAGER_ID in PORTFOLIO). On a service page — a "Our Specialists" block auto-populated by the binding.
Construction Progress Tracking
A client portal for active customers — a separate section behind authentication. Info block CONSTRUCTION_PROGRESS with report elements: date, stage description, photos, completion percentage. Linked to a project via PROPERTY_PROJECT_ID and to a client via PROPERTY_CLIENT_USER_ID. An authenticated client sees only their projects — filter ['PROPERTY_CLIENT_USER_ID' => $USER->GetID()].
Photo reports are uploaded by the site foreman through a simplified admin form or the mobile frontend via bitrix:iblock.element.add.form. Client notification on new report — via mail event PROGRESS_UPDATE.
1C Integration for Project Accounting
The sale module isn't needed — a construction company doesn't sell products through a cart. But data exchange with 1C:Construction Management is relevant: contractor directories, contract statuses, work completion certificates. Integration via 1C REST API or an intermediary database. Data from 1C is pulled into Bitrix Highload blocks via a cron job, refreshed hourly.
SEO for "Work Type + City" Queries
Target queries — "cottage construction Boston," "office renovation Chicago," "industrial construction Texas." SEO templates via service info block settings:
-
ELEMENT_META_TITLE=#ELEMENT_NAME# in {city} | {company} -
SECTION_META_TITLE=#SECTION_NAME# — construction services | {company}
For geo-targeted landing pages — separate sections or a landing component with dynamic city substitution from a "Service Regions" Highload block. Schema.org markup with GeneralContractor and Service:
{
"@context": "https://schema.org",
"@type": "GeneralContractor",
"name": "Company Name",
"areaServed": {"@type": "City", "name": "Boston"},
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Services",
"itemListElement": [
{"@type": "Offer", "itemOffered": {"@type": "Service", "name": "Cottage Construction"}}
]
}
}
Stages and Timelines
| Project Scale | Timeline |
|---|---|
| Brochure site with service catalog and portfolio | 3-5 weeks |
| Full site with calculator, tender system, client portal | 8-14 weeks |
| Corporate portal with 1C integration, construction monitoring, multilingual | 14-24 weeks |
- Analysis (1-2 weeks) — service catalog structure, calculator logic, wireframes
- Design (2-3 weeks) — homepage, catalog, project card, calculator, mobile layouts
- Core development (3-5 weeks) — info blocks, templates, filtering, portfolio with map
- Calculator and forms (2-3 weeks) — multi-step estimation, tender form, client portal
- Integrations (1-3 weeks) — 1C, CRM, mail events
- Testing and launch (1-2 weeks) — cross-browser, mobile devices, SEO audit
Timelines exclude portfolio content population and calculator coefficient tuning — that's the client's job, running in parallel with development.







