Skip to content

Pixels and tags ​

Methods for Facebook pixels and Google tags: add a new one, change the token or conversion labels, archive and restore, attach to a PWA. For what pixels and tags do, see the "Metrics: pixels & tags" section of the guide.

MethodAddressWhat it does
GET/fb_pixelsList Facebook pixels
GET/fb_pixels/{id}One pixel
POST/fb_pixelsAdd a pixel
PUT/fb_pixels/{id}Update a pixel or restore it from archive
DELETE/fb_pixels/{id}Archive a pixel
GET/google_tagsList Google tags
GET/google_tags/{id}One tag
POST/google_tagsAdd a tag
PUT/google_tags/{id}Update a tag or restore it from archive
DELETE/google_tags/{id}Archive a tag

Replace YOUR_KEY and panel.example.com with your own.

List ​

GET/fb_pixels

GET/google_tags

Pixels and tags available to you, recently changed first. Archived ones are not shown.

ParameterWhat it filters
searchPart of the pixel or tag number
archived1 - show archived too
team_idTeam
page, per_pagePage and its size (100 by default)
bash
curl "https://panel.example.com/api/fb_pixels?search=1234" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$response = $api->get('fb_pixels', ['query' => ['search' => '1234']]);
$pixels = json_decode($response->getBody(), true)['data']['fb_pixels'];

foreach ($pixels as $pixel) {
    echo "{$pixel['id']}: pixel {$pixel['pixel_id']}" . PHP_EOL;
}
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

response = requests.get(f"{API}/fb_pixels", headers=HEADERS, params={"search": "1234"}, timeout=30)
pixels = response.json()["data"]["fb_pixels"]

for pixel in pixels:
    print(pixel["id"], "pixel", pixel["pixel_id"])
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const params = new URLSearchParams({ search: '1234' });
const response = await fetch(`${API}/fb_pixels?${params}`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

for (const pixel of data.fb_pixels) {
  console.log(pixel.id, 'pixel', pixel.pixel_id);
}
Response
json
{
  "data": {
    "meta": { "current_page": 1, "per_page": 100, "last_page": 1, "total": 1 },
    "fb_pixels": [
      {
        "id": "WZAX",
        "pixel_id": "1234567890123456",
        "access_token": "EAAB...",
        "archived": false,
        "team": { "id": "WQby", "name": "Team A" },
        "groups": [],
        "created_at": "05 Oct 2026 14:23",
        "updated_at": "05 Oct 2026 14:23"
      }
    ]
  }
}

The tag list comes the same way, but under the google_tags key, and instead of pixel_id and access_token each tag has tag_id, install_label, registration_label and deposit_label.

Only the common errors - see "API introduction".

Responses contain the pixel token

access_token is returned in every pixel response. Don't write these responses to shared logs and don't forward them - it is as much a secret as the API key.

One pixel or tag ​

GET/fb_pixels/{id}

GET/google_tags/{id}

The response is in data.fb_pixel or data.google_tag, the fields are the same as in the list.

bash
curl https://panel.example.com/api/google_tags/Lm3T \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json"
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$tag = json_decode($api->get('google_tags/Lm3T')->getBody(), true)['data']['google_tag'];

echo "{$tag['id']}: tag {$tag['tag_id']}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

tag = requests.get(f"{API}/google_tags/Lm3T", headers=HEADERS, timeout=30).json()["data"]["google_tag"]

print(tag["id"], "tag", tag["tag_id"])
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const response = await fetch(`${API}/google_tags/Lm3T`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log(data.google_tag.id, 'tag', data.google_tag.tag_id);
Errors
CodemessageWhen
403This action is unauthorized.A pixel or tag of another team
404Not foundNo such identifier (for tags - GoogleTag)

Adding a pixel ​

POST/fb_pixels

FieldRequiredWhat it is
pixel_idyesPixel number from Facebook, 5 to 20 digits. Unique within a team
access_tokennoConversions API token. Without it conversions are not sent to Facebook from the server
team_idfor team_lead and adminTeam; for a customer it is filled in automatically
bash
curl -X POST https://panel.example.com/api/fb_pixels \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"pixel_id": "1234567890123456", "access_token": "EAAB...", "team_id": "WQby"}'
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$response = $api->post('fb_pixels', ['json' => [
    'pixel_id' => '1234567890123456',
    'access_token' => 'EAAB...',
    'team_id' => 'WQby',
]]);
$pixelId = json_decode($response->getBody(), true)['data']['fb_pixel']['id'];

echo "Pixel added, id for the PWA: {$pixelId}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

response = requests.post(f"{API}/fb_pixels", headers=HEADERS, json={
    "pixel_id": "1234567890123456",
    "access_token": "EAAB...",
    "team_id": "WQby",
}, timeout=30)
pixel_id = response.json()["data"]["fb_pixel"]["id"]

print("Pixel added, id for the PWA:", pixel_id)
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const response = await fetch(`${API}/fb_pixels`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    pixel_id: '1234567890123456',
    access_token: 'EAAB...',
    team_id: 'WQby',
  }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Pixel added, id for the PWA:', data.fb_pixel.id);

The response is the created pixel in data.fb_pixel. Remember its id (WZAX) - that's what attaches the pixel to a PWA, the pixel number won't work for that.

Errors
CodemessageWhen
422The pixel id field format is invalid.pixel_id is not 5-20 digits
422The pixel id has already been taken.The team already has this pixel (including in the archive)
422The team id field is required.A team_lead or admin didn't pass team_id
422You do not have access to this teamteam_id of another team
422The access token field must not be greater than 512 characters.The token is longer than 512 characters

Adding a tag ​

POST/google_tags

FieldRequiredWhat it is
tag_idyesIdentifier: AW-… (Google Ads), G-… (Analytics) or GTM-… (Tag Manager). Unique within a team
install_label, registration_label, deposit_labelnoGoogle Ads conversion labels for install, registration and deposit
team_idfor team_lead and adminTeam; for a customer it is filled in automatically
bash
curl -X POST https://panel.example.com/api/google_tags \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"tag_id": "AW-123456789", "install_label": "AbC-install", "team_id": "WQby"}'
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$response = $api->post('google_tags', ['json' => [
    'tag_id' => 'AW-123456789',
    'install_label' => 'AbC-install',
    'team_id' => 'WQby',
]]);
$tagId = json_decode($response->getBody(), true)['data']['google_tag']['id'];

echo "Tag added, id for the PWA: {$tagId}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

response = requests.post(f"{API}/google_tags", headers=HEADERS, json={
    "tag_id": "AW-123456789",
    "install_label": "AbC-install",
    "team_id": "WQby",
}, timeout=30)
tag_id = response.json()["data"]["google_tag"]["id"]

print("Tag added, id for the PWA:", tag_id)
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const response = await fetch(`${API}/google_tags`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    tag_id: 'AW-123456789',
    install_label: 'AbC-install',
    team_id: 'WQby',
  }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Tag added, id for the PWA:', data.google_tag.id);

The response is the created tag in data.google_tag.

Errors
CodemessageWhen
422The tag id field format is invalid.tag_id doesn't look like AW-…, G-… or GTM-…
422The tag id has already been taken.The team already has this tag (including in the archive)
422The team id field is required.A team_lead or admin didn't pass team_id

Updating ​

PUT/fb_pixels/{id}

PUT/google_tags/{id}

Change only the fields passed, accept the same fields as adding. Changes take effect right away in every PWA with this pixel or tag - the PWAs themselves don't need to be re-saved.

bash
curl -X PUT https://panel.example.com/api/fb_pixels/WZAX \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"access_token": "EAAB-new"}'
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$response = $api->put('fb_pixels/WZAX', ['json' => ['access_token' => 'EAAB-new']]);
$pixel = json_decode($response->getBody(), true)['data']['fb_pixel'];

echo "Token of pixel {$pixel['pixel_id']} updated" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

response = requests.put(f"{API}/fb_pixels/WZAX", headers=HEADERS, json={"access_token": "EAAB-new"}, timeout=30)
pixel = response.json()["data"]["fb_pixel"]

print("Token of pixel", pixel["pixel_id"], "updated")
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const response = await fetch(`${API}/fb_pixels/WZAX`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({ access_token: 'EAAB-new' }),
  signal: AbortSignal.timeout(30000),
});
const { data } = await response.json();

console.log('Token of pixel', data.fb_pixel.pixel_id, 'updated');

The response is the pixel or tag after the change.

Errors
CodemessageWhen
403This action is unauthorized.A pixel or tag of another team
422The pixel id field format is invalid.The same field checks as on adding

Archive ​

DELETE/fb_pixels/{id}

DELETE/google_tags/{id}

Archive instead of deleting. PWAs keep referring to it, but events don't go to an archived pixel or tag. To restore it - PUT with "archived": false: the PWAs start using it again without reconfiguring.

bash
# Archive
curl -X DELETE https://panel.example.com/api/fb_pixels/WZAX \
  -H "Authorization: Bearer YOUR_KEY" -H "Accept: application/json"

# Restore from archive
curl -X PUT https://panel.example.com/api/fb_pixels/WZAX \
  -H "Authorization: Bearer YOUR_KEY" -H "Accept: application/json" \
  -H "Content-Type: application/json" -d '{"archived": false}'
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

// Archive
$archived = json_decode($api->delete('fb_pixels/WZAX')->getBody(), true)['data']['fb_pixel'];
echo 'Archived: ' . var_export($archived['archived'], true) . PHP_EOL;

// Restore from archive
$restored = json_decode($api->put('fb_pixels/WZAX', ['json' => ['archived' => false]])->getBody(), true)['data']['fb_pixel'];
echo 'Archived: ' . var_export($restored['archived'], true) . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

# Archive
archived = requests.delete(f"{API}/fb_pixels/WZAX", headers=HEADERS, timeout=30).json()["data"]["fb_pixel"]
print("Archived:", archived["archived"])

# Restore from archive
restored = requests.put(f"{API}/fb_pixels/WZAX", headers=HEADERS, json={"archived": False}, timeout=30).json()["data"]["fb_pixel"]
print("Archived:", restored["archived"])
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

// Archive
const archiveResponse = await fetch(`${API}/fb_pixels/WZAX`, {
  method: 'DELETE',
  headers,
  signal: AbortSignal.timeout(30000),
});
const archived = (await archiveResponse.json()).data.fb_pixel;
console.log('Archived:', archived.archived);

// Restore from archive
const restoreResponse = await fetch(`${API}/fb_pixels/WZAX`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({ archived: false }),
  signal: AbortSignal.timeout(30000),
});
const restored = (await restoreResponse.json()).data.fb_pixel;
console.log('Archived:', restored.archived);

The response is the pixel or tag with archived: true (after DELETE) or false (after restoring). The DELETE response comes without team and groups.

Errors
CodemessageWhen
403This action is unauthorized.A pixel or tag of another team

Attaching to a PWA ​

A PWA has one Facebook pixel and one Google tag. They are set in config.metrics when updating the PWA (see the API section "PWA"):

FieldWhat it is
facebook.pixelIdThe pixel's id from the API response (WZAX), not the pixel number
facebook.eventsWhich Facebook event to send on install, registration and deposit: Lead, CompleteRegistration, Purchase, Subscribe, StartTrial, PageView and other standard events
google.tagIdThe tag's id from the API response

The pixel and tag must be from the same team as the PWA.

config is replaced as a whole

As with any config change, first get the PWA's current config, change metrics in it and send it back as a whole - see the API section "PWA".

bash
curl https://panel.example.com/api/pwas/WZAX \
  -H "Authorization: Bearer YOUR_KEY" -H "Accept: application/json" > pwa.json

jq '{team_id: .data.pwa.team.id, config: (.data.pwa.config
     | .metrics.facebook.pixelId = "WZAX"
     | .metrics.facebook.events = {"install": "Lead", "registration": "CompleteRegistration", "deposit": "Purchase"}
     | .metrics.google.tagId = "Lm3T")}' pwa.json \
| curl -X PUT https://panel.example.com/api/pwas/WZAX \
    -H "Authorization: Bearer YOUR_KEY" -H "Accept: application/json" \
    -H "Content-Type: application/json" -d @-
php
<?php
// composer require guzzlehttp/guzzle
require 'vendor/autoload.php';

$api = new GuzzleHttp\Client([
    'base_uri' => 'https://panel.example.com/api/',
    'headers' => ['Authorization' => 'Bearer YOUR_KEY', 'Accept' => 'application/json'],
    'timeout' => 30,
]);

$pwa = json_decode($api->get('pwas/WZAX')->getBody(), true)['data']['pwa'];

$config = $pwa['config'];
$config['metrics']['facebook']['pixelId'] = 'WZAX';
$config['metrics']['facebook']['events'] = [
    'install' => 'Lead',
    'registration' => 'CompleteRegistration',
    'deposit' => 'Purchase',
];
$config['metrics']['google']['tagId'] = 'Lm3T';

$api->put('pwas/WZAX', ['json' => ['team_id' => $pwa['team']['id'], 'config' => $config]]);

echo "Pixel and tag attached to {$pwa['name']}" . PHP_EOL;
python
# pip install requests
import requests

API = "https://panel.example.com/api"
HEADERS = {"Authorization": "Bearer YOUR_KEY", "Accept": "application/json"}

pwa = requests.get(f"{API}/pwas/WZAX", headers=HEADERS, timeout=30).json()["data"]["pwa"]

config = pwa["config"]
config["metrics"]["facebook"]["pixelId"] = "WZAX"
config["metrics"]["facebook"]["events"] = {
    "install": "Lead",
    "registration": "CompleteRegistration",
    "deposit": "Purchase",
}
config["metrics"]["google"]["tagId"] = "Lm3T"

requests.put(f"{API}/pwas/WZAX", headers=HEADERS, json={"team_id": pwa["team"]["id"], "config": config}, timeout=30)

print("Pixel and tag attached to", pwa["name"])
js
// Node.js 18+, no dependencies; save as script.mjs
const API = 'https://panel.example.com/api';
const headers = { Authorization: 'Bearer YOUR_KEY', Accept: 'application/json', 'Content-Type': 'application/json' };

const getResponse = await fetch(`${API}/pwas/WZAX`, {
  method: 'GET',
  headers,
  signal: AbortSignal.timeout(30000),
});
const pwa = (await getResponse.json()).data.pwa;

const config = pwa.config;
config.metrics.facebook.pixelId = 'WZAX';
config.metrics.facebook.events = {
  install: 'Lead',
  registration: 'CompleteRegistration',
  deposit: 'Purchase',
};
config.metrics.google.tagId = 'Lm3T';

await fetch(`${API}/pwas/WZAX`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({ team_id: pwa.team.id, config }),
  signal: AbortSignal.timeout(30000),
});

console.log('Pixel and tag attached to', pwa.name);
Errors
CodemessageWhen
422The selected resource does not existNo such id - for example, the pixel number was passed instead of the id
422You do not have access to this resourceA pixel or tag of a team you have no access to
422The selected install is invalid.Unknown Facebook event in events (the same for registration and deposit)

PWA clones get the same pixel and tag as the original.