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.
Top comments (0)