Xây công cụ rút gọn link Zalo: những bài toán phía sau slug, chống spam và SEO directory
Khi nhìn bên ngoài, một công cụ rút gọn link có vẻ khá đơn giản:
- Người dùng dán link gốc.
- Hệ thống tạo một slug ngắn.
- Người khác truy cập slug đó và được chuyển hướng tới link gốc.
Nhưng khi bắt đầu làm thật, đặc biệt với một ngách cụ thể như link Zalo, mình nhận ra bài toán không chỉ là “shorten URL”. Nó còn liên quan đến xác thực định dạng link, chống spam, tránh trùng lặp, kiểm duyệt nội dung, xử lý link chết, và nếu làm dạng thư viện/danh bạ thì còn có thêm bài toán SEO cho nhiều URL.
Mình đang xây một sản phẩm nhỏ tên là ZoLink.vn, tập trung vào các link liên quan đến hệ sinh thái Zalo như:
- Nhóm Zalo
- Kênh OA
- Mini App Zalo
- Link cá nhân Zalo hợp lệ
Mục tiêu không phải làm một URL shortener đại trà, mà là tạo một lớp tổ chức lại cho các link Zalo công khai: dễ đọc hơn, dễ nhớ hơn, dễ chia sẻ hơn và có thể được đưa vào thư viện nếu phù hợp.
Bài này chia sẻ một số bài toán kỹ thuật và sản phẩm mình gặp trong quá trình làm.
1. Vì sao link Zalo cần được rút gọn?

Nhiều link Zalo không hẳn quá dài, nhưng lại khó nhớ hoặc khó nhận diện.
Ví dụ link Kênh OA có thể là dạng toàn số:
https://zalo.me/1234553679280354321
Link Mini App có thể có dạng:
https://zalo.me/s/12349955691594321
Link nhóm Zalo có thể chứa chuỗi ký tự không gợi nghĩa:
https://zalo.me/g/abc123xyz456789
Các link này vẫn hoạt động bình thường. Nhưng khi gửi cho khách hàng, học viên, phụ huynh, thành viên cộng đồng hoặc đưa lên bài viết, người nhận gần như không biết link đó dẫn tới đâu.
Một link dễ đọc hơn như:
https://zolink.vn/shop-xinh
hoặc:
https://zolink.vn/dat-lich-spa
giúp người nhận có thêm ngữ cảnh trước khi bấm.
Điểm mấu chốt không chỉ là “ngắn hơn”, mà là có nghĩa hơn.
2. Không nên cho phép mọi loại link

Một quyết định sản phẩm khá quan trọng là: ZoLink không rút gọn mọi URL.
Nếu cho phép mọi website, hệ thống sẽ nhanh chóng gặp các vấn đề quen thuộc của shortener công khai:
- Spam link
- Link lừa đảo
- Link độc hại
- Nội dung 18+
- Redirect tới domain nguy hiểm
- Người dùng tạo hàng loạt slug không kiểm soát
Vì vậy, ZoLink chỉ tập trung vào link Zalo hợp lệ.
Các dạng được hỗ trợ gồm:
- Link Nhóm Zalo
- Link Kênh OA
- Link Mini App Zalo
- Link cá nhân Zalo nếu định dạng hợp lệ
Việc giới hạn phạm vi giúp hệ thống dễ kiểm soát hơn, và cũng giúp sản phẩm có định vị rõ hơn.
3. Kiểm tra định dạng link đầu vào

Ở mức cơ bản, hệ thống cần nhận diện link người dùng gửi vào có thuộc nhóm được hỗ trợ hay không.
Ví dụ có thể chia thành các nhóm pattern:
zalo.me/g/...
zalo.me/s/...
zalo.me/{oa_id}
zalo.me/{username_or_profile}
Một rule đơn giản có thể là:
$isZaloLink = str_contains($url, 'zalo.me');
Nhưng rule này quá lỏng. Người dùng có thể gửi các link không hợp lệ hoặc các URL giả mạo có chứa zalo.me trong query string.
Tốt hơn nên parse URL và kiểm tra host:
$host = parse_url($url, PHP_URL_HOST);
$allowedHosts = [
'zalo.me',
'www.zalo.me',
];
if (! in_array($host, $allowedHosts, true)) {
throw new InvalidArgumentException('Link không được hỗ trợ.');
}
Sau đó mới kiểm tra path để phân loại:
$path = parse_url($url, PHP_URL_PATH);
if (str_starts_with($path, '/g/')) {
$type = 'group';
} elseif (str_starts_with($path, '/s/')) {
$type = 'mini_app';
} elseif (preg_match('/^\/[0-9]+$/', $path)) {
$type = 'oa';
} else {
$type = 'profile_or_unknown';
}
Tùy cách thiết kế, mình có thể cho phép profile_or_unknown vào luồng kiểm tra riêng thay vì tự động public.
4. Quy tắc slug: càng đơn giản càng tốt

ZoLink chỉ cho phép slug gồm:
- chữ thường
a-z - số
0-9 - dấu gạch ngang
-
Ví dụ hợp lệ:
shop-xinh
dat-lich-spa
oa-my-pham
nhom-hoc-tieng-anh
Regex có thể dùng:
^[a-z0-9]+(?:-[a-z0-9]+)*$
Rule này giúp tránh các trường hợp:
- Slug có dấu tiếng Việt
- Slug chứa ký tự đặc biệt
- Slug có khoảng trắng
- Slug nhìn giống mã độc
- Slug khó đọc hoặc khó copy
Ví dụ kiểm tra trong PHP:
function isValidSlug(string $slug): bool
{
return preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $slug) === 1;
}
Một số slug cũng nên bị chặn trước, ví dụ:
admin
login
api
dashboard
support
help
about
terms
privacy
Đây là nhóm reserved slug để tránh xung đột route và tránh người dùng tạo link gây hiểu nhầm.
5. Một link gốc không nên có quá nhiều slug

Một vấn đề thực tế: nếu cho phép cùng một link gốc tạo nhiều slug khác nhau, database sẽ rất nhanh bị rác.
Ví dụ một người có thể tạo:
zolink.vn/shop-xinh
zolink.vn/shop-xinh-1
zolink.vn/shop-xinh-free
zolink.vn/shop-xinh-sale
zolink.vn/nhom-shop-xinh
Tất cả cùng trỏ về một link Zalo gốc.
Việc này gây ra nhiều vấn đề:
- Trùng lặp dữ liệu
- Khó quản lý abuse
- Dễ spam
- SEO bị phân tán
- Người dùng không biết link nào là link chính
Vì vậy, một nguyên tắc hợp lý là:
Nếu link gốc đã từng được rút gọn, hệ thống trả lại link ngắn hiện có thay vì tạo thêm link mới.
Ở mức database, có thể lưu hash của normalized URL:
$normalizedUrl = normalizeUrl($originalUrl);
$urlHash = hash('sha256', $normalizedUrl);
Sau đó kiểm tra:
$existing = ShortLink::where('url_hash', $urlHash)->first();
if ($existing) {
return $existing;
}
Việc normalize URL cũng quan trọng. Cùng một link có thể khác nhau ở trailing slash, query tracking, hoặc scheme.
6. Không phải link nào cũng nên được public trong thư viện
Rút gọn link và đưa link vào thư viện công khai là hai việc khác nhau.
Một link có thể được rút gọn để người dùng chia sẻ riêng, nhưng chưa chắc nên được public trong directory.
Ví dụ:
- Nhóm nội bộ
- Nhóm riêng tư
- Link cá nhân
- Link chưa đủ mô tả
- Link chưa được kiểm tra
- Link bị báo cáo
- Link có dấu hiệu spam
Vì vậy, hệ thống nên có trạng thái riêng:
pending
public
private
dead
junk
blocked
Trong đó:
pending: vừa gửi, chờ kiểm trapublic: đủ điều kiện hiển thị công khaiprivate: chỉ dùng link rút gọn, không đưa vào thư việndead: link không còn hoạt độngjunk: nội dung rác, không phù hợpblocked: bị khóa do vi phạm
Điều quan trọng là dead và junk không nên index, không nên đưa vào sitemap, và nên được đẩy xuống cuối hệ thống quản trị để xử lý riêng.
7. SEO cho directory: index nhiều là bình thường, nhưng phải đúng URL

Với mô hình thư viện/danh bạ, việc có nhiều URL được index là bình thường.
Ví dụ mỗi item có thể là một trang riêng:
/nhom-zalo/abc
/kenh-oa/shop-xinh
/mini-app/dat-lich-spa
Vấn đề không phải là “index nhiều quá”. Vấn đề là index nhầm các URL không có giá trị:
- URL filter động
- URL sort
- URL search rỗng
- URL có query string
- Trang dead/junk
- Trang trùng canonical
- Trang không có nội dung chính
Với ZoLink, rule mình ưu tiên là:
LIVE item: index
DEAD/JUNK/BLOCKED: noindex
Search/filter động: noindex hoặc canonical
Category/tag có dữ liệu: index
Category/tag rỗng: noindex
Sitemap cũng nên tách theo loại:
sitemap_blogs.xml
sitemap_groups.xml
sitemap_oa.xml
sitemap_mini_apps.xml
sitemap_categories.xml
Điều này giúp quản lý crawl tốt hơn khi dữ liệu lớn dần.
8. Link rút gọn cần cơ chế chống lạm dụng
Một số rule chống abuse cơ bản:
Rate limit
Không cho một IP hoặc một tài khoản tạo quá nhiều link trong thời gian ngắn.
10 links / 10 minutes
50 links / day
Tùy giai đoạn sản phẩm mà chỉnh.
Duplicate detection
Cùng một link gốc thì trả lại link đã có.
Report flow
Người dùng có thể báo cáo link:
- Link hỏng
- Link không phù hợp
- Link lừa đảo
- Link mạo danh
- Link sai mô tả
Manual review
Một số loại link nên được kiểm tra trước khi public.
Blocklist
Chặn slug hoặc nội dung có từ khóa rủi ro.
9. Rút gọn nhanh và gửi link đầy đủ nên là hai luồng riêng
Một điểm UX mình thấy quan trọng: người dùng có hai nhu cầu khác nhau.
Nhu cầu 1: Rút gọn nhanh
Người dùng chỉ muốn:
- Dán link
- Bấm rút gọn
- Nhận link ngắn dùng ngay
Không muốn điền nhiều thông tin.
Nhu cầu 2: Gửi vào thư viện công khai
Người dùng muốn nhóm/kênh/app của họ được nhiều người biết hơn. Lúc này cần thêm:
- Tên hiển thị
- Mô tả
- Danh mục
- Ảnh đại diện nếu có
- Trạng thái public/private
- Link rút gọn mong muốn
Hai luồng này nên tách rõ để tránh làm người dùng mới bị rối.
10. Kết luận
Một công cụ rút gọn link nhìn bên ngoài có vẻ nhỏ, nhưng khi gắn với một hệ sinh thái cụ thể như Zalo, bài toán trở nên thú vị hơn.
Không chỉ là redirect.
Nó bao gồm:
- Validate link đầu vào
- Thiết kế slug dễ đọc
- Chống trùng link
- Chống spam
- Kiểm duyệt nội dung
- Quản lý trạng thái live/dead/junk
- SEO cho directory nhiều URL
- Tối ưu UX cho hai luồng: rút gọn nhanh và gửi vào thư viện
Mình đang xây ZoLink.vn theo hướng đó: một công cụ rút gọn và thư viện mở cho các link Zalo công khai như Nhóm Zalo, Kênh OA và Mini App.
Nếu bạn từng làm URL shortener, directory, hoặc hệ thống có nhiều URL public, mình rất muốn nghe thêm kinh nghiệm về:
- Cách chống spam
- Cách xử lý duplicate URL
- Cách phân loại nội dung public/private
- Cách tối ưu sitemap/canonical/noindex cho directory lớn
Demo sản phẩm: