Adding a Webhook trigger to your account

Setting up a Webhook trigger

Publishing to a Webhook trigger

Events

Examples

Unpublishing a project

Webhook allows you to publish projects with user-defined HTTP callbacks.

You can add an optional header that allows a webhook receiver to verify the content (secret needs to be set). Our webhook integration is very simple and waits for users' service to respond with 2xx; all other response codes are interpreted as an error. All requests have a 20-second timeout.

➕ Adding a Webhook trigger to your account

  • In the dashboard, click the User tab on the top right corner

  • Select Hosting

  • Click on Add domain

  • Enter your domain or sub-domain (e.g www.mywebsite.com)

  • Select Advanced hosting option

  • Choose Webhook trigger from the list

  • Within Access options, toggle if you want to share your domain across your team. It'll be off by default making it only available for you

  • Click on Add domain

⚙️ Setting up a Webhook trigger

You'll need to supply a number of parameters to properly connect your Webhook trigger, some of them are optional depending on how your server is set up.

Have a look at the chart below to understand how each parameter works.

Parameter

Required

Description

Webhook URL

Yes

The address where Vev will send the contents when you Publish from Vev. If you do not have a server/endpoint available, you can use a tunneling service such as Ngrok to send contents to your local computer.

Page content to send in addition to body

Send full page: Check off if you want Vev to generate the full page (<html /> and all). Without this setting on, only the HTML to render the content will be sent.

Send plugin settings: Add the generated data from the Hosting Plugins of your project and attach them as a JSON attribute.

Ping

No

Check off to grant Vev permission to send pings

Unpublish

No

Check off to grant Vev permission to unpublish the content

Adding a Web Path

You can add a Path to your domain at the core level, which means it will be used as a base path in all projects that the domain is added to. Follow the steps below to learn how to do it.

  • In the dashboard, click the User tab on the top right corner

  • Select Hosting

  • Select your domain

  • Enter your path in the Web path field

Signature

The token is set by you and can be anything; it is used to verify that the content is sent from Vev. To see or generate a Secret for your webhook, go to the Hosting overview and click on Generate token. This string of characters is used in the Webhook server code.

When publishing to a Webhook all requests from Vev is signed with a header X-Vev-Signature for clients to verify that Vev is the actual sender. In order to verify the signature from the request, you need the secret set by you in Vev and a crypto library to create HMAC digests.

X-Vev-Signature value consists of an algorithm to generate a hash and the signature itself, e.g 'sha512=super-long-hashed-value'. For now, we only support sha512 as an algorithm to create a signature. If you use the payload and secret with sha512, you get the same value as the signature.

Endpoint security

It is used to communicate with users' endpoints in the correct way. We support non-secured endpoints, basic, and token-based. OpenID Connect (OIDC) is not supported yet.

Tip: Go to our roadmap and submit your request if you'd like OpenID endpoints to be supported.

Adding a Favicon

Follow the steps below to learn how to add a Favicon to your domain.

  • In the dashboard, click the User tab on the top right corner

  • Select Hosting

  • Select your domain

  • Scroll down to the Favicon section

  • Drag and drop your file or click to upload it from your computer

📚 Publishing to a Webhook trigger

Once your Webhook trigger has been properly set you'll need to add it to your project so that you can publish to it. Read the steps below to learn how to do it.

  • Open the project you want to publish

  • Click the Publish button on the top right corner

  • Select Add publish destination from the publish dialog

  • Choose your domain from the dropdown list

  • Add a path to your domain or leave it blank if you want to publish to its root (the path will only be added at a project level)

  • Hit Add publish destination

  • Open the publish dialog

  • Hit Publish project

Events

All requests are sent as type events, every event contains meta information for the event, and every event has a payload. We currently support two types of events: Ping and Publish. Ping is used for testing the webhook integration with your backend. Publish event contains all necessary HTML, CSS, and JavaScript to display the project.

WebhookRequest

export interface WebhookRequest {
id: string;
hosting: string;
event: WebhookEvent;
payload: Json;
}


PublishWebhookPayload

export interface PublishWebhookPayload {
projectId: string;
version: number;
dir: string;
pages: WebhookPage[];
workspace?: IWorkspace;
team?: FSTeam;
css: ExternalFile[];
js: ExternalFile[];
other: ExternalFile[];
pluginsData?: any;
}

PingPayload

interface PingPayload {
message: string;
html: string;
css: ExternalFile[];
js: ExternalFile[];
}


PublishPayload

interface PublishPayload {
projectId: string;
version: number;
dir: string;
pages: WebhookPage[];
workspace?: IWorkspace;
team?: FSTeam;
css: ExternalFile[];
js: ExternalFile[];
other: ExternalFile[];
pluginsData?: any;
}

interface WebhookPage {
html: string;
key: string;
title: string;
path: string;
cover?: string;
image?: { thumb: string; location: string };
index?: boolean;
settings?: any;
}

interface ExternalFile {
url: string;
contentType?: string;
cacheControl?: string;
}

🚀 Examples

Vev JSON request

Download an example of the JSON which is sent from Vev here.

Implementation Examples

These examples are for NodeJS and PHP, but you can use any language you like (.NET, Ruby) as long as you can run a web server that can receive a POST request and parse it as JSON.

NodeJS

  • Create a folder called vev-webhook-server

  • Create the file index.js as per below

  • Run npm install express body-parser crypto

  • Run node index.js

Note: NodeJS (server-side JavaScript, requires NodeJS & Node Package Manager to run).

index.js (server code):

/**
* Vev Examples - Webhook Server
*
* A NodeJS + Express example server for receiving
* PUBLISH events from Vev securely.
*
* [Read more here](https://help.vev.design/hosting/custom/webhook)
*/
const express = require("express");
const fs = require("fs");
const crypto = require("crypto");
const bodyParser = require("body-parser");
const path = require("path");

// This should not be stored in plain text

const VEV_SECRET = "...";
const VEV_IP = "34.72.55.20";

const app = express();
// Add this to get IP information (no required, just an additional layer of security)
app.set("trust proxy", true);

// Since the large full websites can be sent over the web
const LargeJSONBodyParser = bodyParser.json({
limit: "150mb"
});
app.use(express.static(path.join(__dirname, "..", "public")));

// Creating a post route to handle the the webhook call
// Adding json body parser midleware
// Also Adding vev signature validator (you find the implementation at the bottom)
app.post(
"/webhook-receiver",
LargeJSONBodyParser,
VevSignatureMiddleware,
async (req, res) => {
const { payload, event } = req.body;
console.log("event: ", event);
console.log("payload: ", payload);
if (event === "PUBLISH") {
await Promise.all(payload.pages.map(StoreVevPage));
} else if (event === "PING") {
console.log("Webhook test ping recieved from: " + req.ip);
}

res.send({ message: "I received your webhook!!" });
}
);

async function StoreVevPage(page) {
// Putting the files in the public dir
// if page is index page then set the path to be public/index.html
let pagePath = path.join("./public", page.index ? "index.html" : page.path);
// Page path can have file extntion
if (!path.extname(pagePath)) pagePath = path.join(pagePath, "index.html");

// Creating the dir to put the file in
// Remeber that in vev the page path can be nested (example dir1/dir2/index.html)
// So important to create dir recursive
const dir = path.dirname(pagePath);
try {
fs.promises.access(dir);
} catch (e) {
await fs.promises.mkdir(dir, { recursive: true });
}

//Writing the file to the page path
await fs.promises.writeFile(pagePath, page.html);
}

function VevSignatureMiddleware(req, res, next) {
const signatureHeader = req.get("X-Vev-Signature");
if (!signatureHeader) return next("Missing signature");

// For extra secuirty you can validate that the IP is the vev IP address
if (req.ips.indexOf(VEV_IP) === -1)
return next("Invlid IP request (not from vev)");

const [algorithm, signature] = signatureHeader.split("=");
if (!algorithm || !signature) return next("Invalid signature");

// Validating signature of request
// Done by comparing the signature with HMAC (hash-based message authentication code)) using the secret key for hasing
const hmac = crypto.createHmac(algorithm, VEV_SECRET);
const generatedSignature = hmac
.update(JSON.stringify(req.body))
.digest("hex");

// Comparing the request signature with the generated
// This will validate that the sender knows the secret
// and that the content was not tampered with and that the
if (generatedSignature !== signature) {
console.error("Webhook trigered with invalid signature");
return next("Invliad signature");
}

next();
}

app.listen(8001, () => console.log(`Example app listening on port 8001!`));

Note: You will still need to set the Webhook URL in your webhook settings to a URL that points to where you are running your webhook server.

PHP

<?php

/**
* Vev Examples - Webhook endpoint
*
* PHP example script for receiving PUBLISH events from Vev securely.
*
* [Read more here](https://help.vev.design/hosting/custom/webhook)
*/

const VEV_SECRET = '85806154-43ae-4427-8f27-479af8239b2e';

if (!isset($_SERVER['X-Vev-Signature'])) return 'Missing signature';

$signatureHeader = $_SERVER['X-Vev-Signature'];

if (!$signatureHeader) return 'Missing signature';

list($algorithm, $signature) = explode('=', $signatureHeader);

if (!$algorithm || !$signature) return 'Invalid signature';

if (!in_array($algorithm, hash_hmac_algos())) return 'Invalid algorithm';

$requestBody = json_decode(file_get_contents('php://input'));

// Validating signature of request
// Done by comparing the signature with HMAC (hash-based message authentication code)) using the secret key for hasing
$generatedSignature = hash_hmac($algorithm, json_encode($requestBody), VEV_SECRET);

// Comparing the request signature with the generated
// This will validate that the sender knows the secret and that the content was not tampered with
if ($generatedSignature !== $signature) return 'Invalid signature';

$ip = $_SERVER['REMOTE_ADDR'];

if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
if (!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];

function storeVevPage ($page) {

// Putting the files in the public dir
// if page is index page then set the path to be public/index.html
$pagePath = './public/' . ($page['index'] ? 'index.html' : $page['path']);

if (!str_contains($pagePath, '.')) $pagePath .= '/index.html';

$directory = substr($pagePath, 0, strrpos($pagePath, '/') - 1);

if (!file_exists($directory)) mkdir($directory, 0777, true);

// Writing the file to the page path
file_put_contents($pagePath, $page['html']);

}

$payload = $requestBody['payload'];
$event = $requestBody['event'];

echo $payload;
echo $event;

switch ($event) {

case 'PUBLISH':

foreach ($payload['pages'] as $page) {

storeVevPage($page);

}

break;

case 'PING':

echo "Webhook test ping received from {$ip}";

break;

}

echo 'I received your webhook';

🔙 Unpublishing a project

To unpublish your project from your Webhook:

  • In the dashboard, click the User tab on the top right corner

  • Click "Hosting"

  • Select your domain

  • Click the "Projects" tab on the top

  • Click the three dots next to the project you want to unpublish and click "Unpublish".

The project will no longer appear on the list.

Did this answer your question?