Data Consistency with Webhook Functions
Aaron Pavlick
Posted on June 21, 2022
In my previous post, I explained how I was able to edit the primary photo for each entity in my Knowledge Graph utilizing a Typescript function plugin, the Cloudinary Image Transformation API, and the Data Connectors framework. If my Knowledge Graph continues to expand with new Beverage entities, I want to ensure that their new photos have the same format as all the existing photos.
With Webhooks, I was able to apply the same logic to create a newly computed field called Transformed Photo.
Updating my Function Plugin
I didn’t need to change any of the existing code that I already wrote. I just needed to add a few things to make it compatible with a Webhook invocation.
First, I added types.ts
for some type definitions used for validating the input to the Webhook function.
// types.ts
export interface WebhookPayload {
changedFields: ChangedFields;
entityId: string;
primaryProfile: PrimaryProfile;
meta: {
eventType: string;
};
}
export interface PrimaryProfile {
primaryPhoto: PrimaryPhoto;
}
export interface PrimaryPhoto {
image: Image;
}
export interface Image {
url: string;
}
export interface ChangedFields {
fieldNames: string[];
}
In api.ts
, I added a Knowledge API client function for editing the newly created entity.
// api.ts
import axiod from "https://deno.land/x/axiod@0.23.2/mod.ts";
declare const YEXT_ACCOUNT_API_KEY: string;
export const editEntity = async (
entityId: string,
// deno-lint-ignore no-explicit-any
data: Record<string, any>
) => {
try {
// using fetch instead of axios works too. I just prefer axios syntax.
await axiod.put(
`https://api-sandbox.yext.com/v2/accounts/me/entities/${entityId}`,
data,
{
params: {
api_key: YEXT_ACCOUNT_API_KEY,
v: "20220322",
},
}
);
} catch (error) {
if (error.response) {
console.error(`${error.response.status}: ${error.response.data}`);
}
throw error;
}
console.log(`Edited entity ${entityId}`);
};
Lastly, I added the removeBackgroundHook
function to mod.ts
that checks if the primary photo is a changed field. If the primary photo field is updated, the function calls my removeBackground
function to get the new Image URL, and then calls the edit entity API and updates a new field I added to the beverage entity called c_transformedPhoto
.
// mod.ts
export const removeBackgroundHook = async (payload?: WebhookPayload) => {
if (payload?.changedFields.fieldNames.includes("primaryPhoto")) {
console.log(`Transforming primaryPhoto for Entity ${payload?.entityId} `);
const imageUrl = await removeBackground(
`${payload.entityId}|${payload.primaryProfile.primaryPhoto.image.url}`
);
if (imageUrl) {
await editEntity(payload.entityId, {
c_transformedPhoto: { url: imageUrl },
});
}
}
};
Before running yext resources apply
, I updated my _resource.json
to include the additional variables I am going to need to call the Edit Entity API.
{
"$id": "TransformImagePlugin",
"$schema": "https://schema.yext.com/config/platform/plugin/v1",
"globals": {
"CLOUDINARY_API_KEY": "${{CLOUDINARY_API_KEY}}",
"CLOUDINARY_API_SECRET": "${{CLOUDINARY_API_SECRET}}",
"YEXT_ACCOUNT_API_KEY": "${{YEXT_ACCOUNT_API_KEY}}"
}
}
Adding a Webhook in the Developer Console
In the Developer Console of my account, I added a new Webhook to my existing app. The API Key that I uploaded along with my plugin needs permission to update entities so I needed to add Read/Write access to the Entities Knowledge API in the API Credentials screen.
Then, I set the Webhook Type which determines when the hook should be trigged.
After selecting the Webhook Type, I gave my new hook a name, description, and the function it should invoke when triggered.
To make sure my hook was working correctly, I added a new primary photo to an entity in my Knowledge Graph and then checked to see the c_transformedPhoto field changed.
You can see that any time the Primary Photo field changes, I get a new value added to the Transformed Photo field. Whether I create or edit entities via the UI, CSV upload, Data connector, or API call, the webhook will be called to create a new transformed photo. Webhooks can also be configured to run based on a variety of other events and could be used to call an API rather than a function.
You can find the complete Webhook function plugin code here.
Posted on June 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.