Implementing Lookalike Audiences Based on Site Data

Suppose you've already collected a CRM email base of customers who made a purchase. Cold traffic gives a CPA above 1500₽, and you need to scale cheaper. The solution is lookalike audiences built on a segment of best buyers. But many upload "raw" lists—all random registrations. The algorithm builds a

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1283
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1237
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    980
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1029
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    552

Suppose you've already collected a CRM email base of customers who made a purchase. Cold traffic gives a CPA above 1500₽, and you need to scale cheaper. The solution is lookalike audiences built on a segment of best buyers. But many upload "raw" lists—all random registrations. The algorithm builds a similar audience, but it yields a CPA no lower than the original. The secret lies in a high-quality seed segment: only those who brought real revenue. Below is a proven pipeline with real numbers and ready code.

Segments for seed audiences: which work best

The quality of the resulting audience directly depends on the seed data. The more accurately we describe the "portrait" of a converted user, the higher the precision. Here are typical segments:

Segment Minimum size Quality
Buyers in last 90 days 500–1000 Very high
Users with LTV > 5000₽ 500 High
Completed trial → paid plan 300 High
Viewed key pages 1000+ Medium
All registered users 5000+ Low

A segment of 500 buyers gives 3x higher accuracy than a list of 5000 random registrations. Therefore, we always start with CRM analysis and selecting the core—users with the highest LTV. Additionally, we enrich data through CRM and event analytics to exclude inactive contacts.

In one e-commerce project with a turnover of 50 million ₽, we isolated a segment of buyers with LTV > 5000₽ (800 records total). After creating a lookalike, CPA dropped from 1200₽ to 750₽, and conversion increased by 40%. The key was a high-quality seed segment.

To choose the platform, compare the main parameters of Meta and VK:

Parameter Meta (Facebook/Instagram) VK Ads
Minimum seed size 200 records 500 records
Data format SHA-256 only Open or SHA-256 with prefix
Lookalike size 1%–10% of country Up to 1,000,000
Auto-update Via API Via import

Why hashing contacts is critical for lookalike?

Before sending to ad systems, emails and phones must be normalized and hashed with SHA-256. Otherwise, the system will reject the data or reduce match quality. In Laravel, this is done with one class—see example below.

Why SHA-256 specifically?It is an irreversible hash function recommended by ad platforms. It transforms data into a fixed-length string that cannot be reversed. More about SHA-256 can be read in Wikipedia.
class AudienceExporter { public function exportHighValueCustomers(): array { return User::query() ->join('orders', 'orders.user_id', '=', 'users.id') ->where('orders.status', 'completed') ->where('orders.created_at', '>=', now()->subDays(90)) ->groupBy('users.id', 'users.email', 'users.phone') ->havingRaw('SUM(orders.total) >= ?', [5000]) ->get(['users.email', 'users.phone']) ->map(fn($user) => [ 'email' => hash('sha256', strtolower(trim($user->email))), 'phone' => $user->phone ? hash('sha256', $this->normalizePhone($user->phone)) : null, ]) ->toArray(); } private function normalizePhone(string $phone): string { $digits = preg_replace('/\D/', '', $phone); if (strlen($digits) === 10) $digits = '7' . $digits; return '+' . $digits; } public function exportToCsv(array $data, string $filename): string { $path = storage_path("app/audiences/{$filename}.csv"); $fp = fopen($path, 'w'); fputcsv($fp, ['email', 'phone']); foreach ($data as $row) { fputcsv($fp, [$row['email'], $row['phone'] ?? '']); } fclose($fp); return $path; } } 

How to upload an audience to Meta (Facebook/Instagram)?

Meta provides the Custom Audiences API. To upload, follow these steps:

  1. Create a custom audience via API.
  2. Transfer hashed emails in batches of up to 10,000 records.
  3. Build a lookalike based on this audience.

Sequence: create custom audience -> upload hashes -> build lookalike. It's important to specify the schema EMAIL_SHA256. The code below does this automatically.

class MetaAudienceService { private const API_VERSION = 'v19.0'; private string $accessToken; private string $adAccountId; public function createCustomAudience(string $name, string $description): string { $response = Http::post( "https://graph.facebook.com/{$this->API_VERSION}/act_{$this->adAccountId}/customaudiences", [ 'name' => $name, 'subtype' => 'CUSTOM', 'description' => $description, 'customer_file_source' => 'USER_PROVIDED_ONLY', 'access_token' => $this->accessToken, ] ); return $response->json('id'); } public function uploadUsers(string $audienceId, array $hashedEmails): void { foreach (array_chunk($hashedEmails, 10000) as $chunk) { $payload = [ 'schema' => ['EMAIL_SHA256'], 'data' => array_map(fn($email) => [$email], $chunk), ]; Http::post( "https://graph.facebook.com/{$this->API_VERSION}/{$audienceId}/users", [ 'payload' => json_encode($payload), 'access_token' => $this->accessToken, ] ); } } public function createLookalike(string $sourceAudienceId, string $country, float $ratio = 0.01): string { $response = Http::post( "https://graph.facebook.com/{$this->API_VERSION}/act_{$this->adAccountId}/customaudiences", [ 'name' => "Lookalike {$country} {$ratio}", 'subtype' => 'LOOKALIKE', 'origin_audience_id' => $sourceAudienceId, 'lookalike_spec' => json_encode([ 'type' => 'similarity', 'country' => $country, 'ratio' => $ratio, ]), 'access_token' => $this->accessToken, ] ); return $response->json('id'); } } 

Uploading an audience to VK Ads

VK accepts emails both in open form and hashed (with a prefix). Algorithm: create a retargeting group -> import contacts. Note: business accounts have their own limits, but the basic pipeline is the same.

class VkAudienceService { public function uploadToRetargeting(string $name, array $hashedEmails): int { $content = implode("\n", $hashedEmails); $response = Http::withToken($this->token) ->post('https://api.vk.com/method/ads.createTargetGroup', [ 'account_id' => $this->accountId, 'name' => $name, 'v' => '5.199', ]); $groupId = $response->json('response.id'); Http::withToken($this->token) ->post('https://api.vk.com/method/ads.importTargetContacts', [ 'account_id' => $this->accountId, 'target_group_id' => $groupId, 'contacts' => $content, 'v' => '5.199', ]); return $groupId; } } 

Automating lookalike audience updates

Lookalike audiences become outdated as new conversions appear. Manual export every week is unnecessary. We set up automatic updates via Schedule—it works like clockwork.

class UpdateLookalikeAudiences implements ShouldQueue { public function handle(): void { $exporter = app(AudienceExporter::class); $data = $exporter->exportHighValueCustomers(); $emails = array_column($data, 'email'); app(MetaAudienceService::class)->uploadUsers( config('ads.meta.buyer_audience_id'), $emails ); Log::info("Lookalike audience updated", ['count' => count($emails)]); } } 

Step-by-step setup algorithm

  1. Analyze existing site data (CRM, forms, events)—isolate the seed segment.
  2. Develop an export module with hashing and validation.
  3. Integrate with selected ad platforms (Meta, VK).
  4. Configure automatic updates via cron or scheduler.
  5. Monitor—log errors and audience freshness.

What's included in the work

  • Data analysis and selection of the optimal seed segment.
  • Development of an exporter with SHA-256 hashing and support for Meta and VK formats.
  • Integration with ad platform APIs (one or several).
  • Setup of automatic weekly updates.
  • Documentation and post-launch consultation.

Timeline and how to get started

The audience export system with hashing and automatic updates for one platform takes 4–6 working days. For multiple platforms, the timeline extends to 8–10 days. We have been working with lookalike audiences for over 5 years and have completed 30+ successful projects—this guarantees reliability and quality.

Order the export system setup—we will prepare the seed segment, configure integration, and set up auto-updates. Contact us for a consultation.