Разработка кастомных Zap-интеграций Zapier
Когда встроенных приложений Zapier недостаточно, разрабатываются Custom Zapier Apps (через Zapier CLI) или используются Webhooks + Code by Zapier для кастомной логики.
Code by Zapier — JavaScript в Zap
Встроенный Code step позволяет писать JavaScript прямо в Zap:
// Входные данные из предыдущего шага
const orderData = inputData.orderPayload; // JSON-строка
const order = JSON.parse(orderData);
// Трансформация
const lineItems = order.items.map(item => ({
sku: item.product_code,
name: item.product_name,
qty: item.quantity,
price: (item.price_cents / 100).toFixed(2),
total: ((item.price_cents * item.quantity) / 100).toFixed(2)
}));
const totalDiscount = order.discounts.reduce((sum, d) => sum + d.amount_cents, 0);
// Возвращаем данные для следующих шагов
output = {
lineItemsJson: JSON.stringify(lineItems),
lineItemsCount: lineItems.length,
subtotal: (order.subtotal_cents / 100).toFixed(2),
discount: (totalDiscount / 100).toFixed(2),
total: (order.total_cents / 100).toFixed(2),
isHighValue: order.total_cents > 1000000, // > 10 000 ₽
formattedDate: new Date(order.created_at).toLocaleDateString('ru-RU', {
day: 'numeric', month: 'long', year: 'numeric'
})
};
Custom Zapier App (Zapier CLI)
Для публичной интеграции или повторного использования — полноценный Zapier App:
npm install -g zapier-platform-cli
zapier login
zapier init my-app --template=trigger
cd my-app
// triggers/newOrder.js
const subscribeHook = async (z, bundle) => {
const data = {
url: bundle.targetUrl,
event: 'order.created'
};
const response = await z.request({
url: `${process.env.BASE_URL}/webhooks`,
method: 'POST',
body: data,
});
return response.data;
};
const unsubscribeHook = async (z, bundle) => {
const webhookId = bundle.subscribeData.id;
return z.request({
url: `${process.env.BASE_URL}/webhooks/${webhookId}`,
method: 'DELETE',
});
};
const getOrder = async (z, bundle) => {
const response = await z.request({
url: `${process.env.BASE_URL}/orders/${bundle.cleanedRequest.id}`,
});
return [response.data];
};
module.exports = {
key: 'new_order',
noun: 'Order',
display: {
label: 'New Order',
description: 'Triggers when a new order is created.',
},
operation: {
type: 'hook',
performSubscribe: subscribeHook,
performUnsubscribe: unsubscribeHook,
perform: getOrder,
sample: { id: 1, total: 5000, status: 'paid' },
},
};
// creates/createContact.js
const createContact = async (z, bundle) => {
const response = await z.request({
url: `${process.env.BASE_URL}/contacts`,
method: 'POST',
body: {
email: bundle.inputData.email,
name: bundle.inputData.name,
phone: bundle.inputData.phone,
},
});
return response.data;
};
module.exports = {
key: 'create_contact',
noun: 'Contact',
display: {
label: 'Create Contact',
description: 'Creates a new contact.',
},
operation: {
inputFields: [
{ key: 'email', required: true, type: 'string' },
{ key: 'name', required: true, type: 'string' },
{ key: 'phone', required: false, type: 'string' },
],
perform: createContact,
sample: { id: 1, email: '[email protected]' },
},
};
Тестирование и деплой
# Тест отдельного триггера
zapier test
# Деплой в Zapier (private app)
zapier push
# Promote в public
zapier promote 1.0.0
Authentication в Custom App
// authentication.js — OAuth2
module.exports = {
type: 'oauth2',
oauth2Config: {
authorizeUrl: {
url: 'https://example.com/oauth/authorize',
params: { client_id: '{{process.env.CLIENT_ID}}', scope: 'read write' }
},
getAccessToken: {
url: 'https://example.com/oauth/token',
body: {
code: '{{bundle.inputData.code}}',
client_id: '{{process.env.CLIENT_ID}}',
client_secret: '{{process.env.CLIENT_SECRET}}',
}
},
refreshAccessToken: {
url: 'https://example.com/oauth/token',
body: {
refresh_token: '{{bundle.authData.refresh_token}}',
grant_type: 'refresh_token',
}
},
},
};
Сроки
Code by Zapier для кастомной трансформации — несколько часов. Полноценный Custom Zapier App с 2–3 триггерами и 3–5 actions — 1–2 недели.







