ADL-001
Read the AdsLab task feed and normalise it
The endpoint is a path, not a query string, and the field names change per task type. Normalising once at the edge keeps the rest of your site from caring.
AdsLab's Task API puts every parameter in the URL path rather than a query string, which is unusual enough to get wrong on the first try: publisher id, API key, country, your user id, the visitor's address, then the type.
The part that costs more time is the response. Field names are not consistent across task types — the same concept arrives as id or _id, title or name, icon or image, reward or reward_usd. Rendering straight from the feed means every template carries that mess.
Normalise once, on the way in. Everything downstream then sees one shape, and when they add a type or rename a field it is one function to change.
function adslab_tasks(string $placementId, string $apiKey, string $country, string $userId, string $ip, string $type = 'all'): array
{
// Path parameters, not a query string.
$url = 'https://adslab.me/api/tasks-share/'
. rawurlencode($placementId) . '/' . rawurlencode($apiKey) . '/'
. rawurlencode($country) . '/' . rawurlencode($userId) . '/'
. rawurlencode($ip) . '/' . rawurlencode($type);
$body = fetch_guarded($url, 12);
$data = $body === null ? null : json_decode($body, true);
if (!is_array($data) || empty($data['tasks'])) {
return [];
}
return array_values(array_filter(array_map('adslab_normalise', $data['tasks'])));
}
/** One shape for every task type, whichever field names arrived. */
function adslab_normalise(array $t): ?array
{
$id = $t['id'] ?? $t['_id'] ?? null;
$title = $t['title'] ?? $t['name'] ?? null;
if ($id === null || $title === null) {
return null;
}
// Keep the reward as a decimal STRING. Floats lose the small ones.
$reward = (string) ($t['reward'] ?? $t['reward_usd'] ?? '0');
return [
'id' => (string) $id,
'title' => (string) $title,
'icon' => (string) ($t['icon'] ?? $t['image'] ?? ''),
'url' => (string) ($t['url'] ?? $t['link'] ?? ''),
'reward' => $reward,
'type' => (string) ($t['type'] ?? 'task'),
'country' => strtoupper((string) ($t['country'] ?? '')),
];
}
Using it
Pass the visitor's real country. The feed is filtered by it, and sending the wrong one is the usual reason a wall looks empty from one country and full from another.
Render the feed in your own design rather than embedding their wall. The hosted wall cannot be styled, and the feed carries everything you need to build a task list.
Cache the feed for a minute per (country, type). It changes slowly and the call is not fast.
What bites people
Rewards are decimal strings. Cast them to float for display if you must, but do the money arithmetic in integers.
reviews currently answers "Reviews disabled temporarily" while review tasks still appear in the all feed. Filter them or your list shows items that cannot be started.
A failed fetch should render the page with no tasks, not a fatal. An ad network being down is not your site being down.