DEV Community

Aaron Pavlick for Yext

Posted on • Edited on • Originally published at hitchhikers.yext.com

3 3

Data Consistency with Webhook Functions

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[];
}
Enter fullscreen mode Exit fullscreen mode

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}`);
};
Enter fullscreen mode Exit fullscreen mode

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 },
      });
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

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}}"
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

api credentials

Then, I set the Webhook Type which determines when the hook should be trigged.

webhook type

After selecting the Webhook Type, I gave my new hook a name, description, and the function it should invoke when triggered.

webhook settings

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.

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay