# Landing page developer guidelines
This document contains technical tips and rules for developers who create landing pages for work in the tracker-sandbox
environment.
# Using curl
in PHP
To prevent scripts from being interrupted unexpectedly, it is important to consider the execution time limits:
The maximum time for a PHP script to run is set via the
TRACKER_LANDING_PAGES_TIMEOUT
variable (in seconds).If a
curl
request runs longer than this time, it is forcibly interrupted.Make sure to specify the timeout via
CURLOPT_TIMEOUT
— the value is 1 second less thanTRACKER_LANDING_PAGES_TIMEOUT
.
Example of setting the timeout:
$systemTimeout = getenv('TRACKER_LANDING_PAGES_TIMEOUT') ?: 10;
$curlTimeout = max(1, $systemTimeout - 1);
$ch = curl_init('https://example.com/api');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $curlTimeout);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Curl error: ' . curl_error($ch);
} else {
echo 'Response: ' . $response;
}
curl_close($ch);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Timeouts in
curl
are especially important when working with slow external APIs or when chainingcurl
calls inside a landing page.
# Using Guest Redis
The tracker-sandbox
container has a built-in Redis service intended only for temporary data storage, debugging, and testing. Use it if caching in memory, or files is not suitable.
# Features
Redis is only available locally, inside the container.
Connection is made using authorization data, which the system provides through environment variables.
Store data in Redis only temporarily — it can be deleted or overwritten.
Timeouts in curl
are especially important when working with slow external APIs or when using a chain of curl
calls inside a landing page.
# Example of connecting to PHP 8.3 using phpredis
<?php
$redis = new Redis();
try {
$redisHost = getenv('GUEST_REDIS_HOST');
$redisPort = getenv('GUEST_REDIS_PORT');
$redisUser = getenv('GUEST_REDIS_KEITARO_USER');
$redisPassword = getenv('GUEST_REDIS_KEITARO_PASSWORD');
$redis->connect($redisHost, $redisPort);
if (!$redis->auth([$redisUser, $redisPassword])) {
throw new RedisException("Redis authorization error: invalid username or password");
}
$redis->set('example_key', 'hello world');
$value = $redis->get('example_key');
echo "Received value: " . $value . PHP_EOL;
} catch (RedisException $e) {
echo "Redis error: " . $e->getMessage() . PHP_EOL;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Discard file_put_contents
in favor of Redis
Using the file system (file_put_contents()
, fopen()
, fwrite()
, etc.) is not recommended for the following reasons:
Files may conflict with parallel requests.
Temporary files are not guaranteed to be saved after the request is completed.
File system may be cleaned or reinitialized between container restarts.
Potential issues with permissions and
open_basedir
restrictions.
It is recommended to use guest Redis as a safe and fast storage for temporary data.
# Example: replacing file_put_contents
Produced:
$data = json_encode(['foo' => 'bar']);
file_put_contents('/tmp/my-cache.json', $data);
2
Now:
$redis->set('my-cache-key', json_encode(['foo' => 'bar']));
# Example: replacing file_get_contents
Produced:
$data = file_get_contents('/tmp/my-cache.json');
$array = json_decode($data, true);
2
Now:
$data = $redis->get('my-cache-key');
$array = json_decode($data, true);
2
Use logical keys, possibly with prefixes (
landing:lead_data:123
), to avoid overlaps and simplify debugging.
If data needs to be stored for a limited time, use setex()
:
$redis->setex('temp:token', 60, 'abc123'); // expires in 60 seconds