Virtual page from API without getting all API results

I’m building a tool that uses Shopify as a source of virtual pages and am running into performance issues caused by inefficient architecture on my end.
I was able to follow the docs on Virtual Pages and now have a big list of Shopify products in the Kirby panel! (Awesome!)

My issue is this:
If I visit, refresh, or save an individual virtual page, the master “get all” API call is made, which can take some time and ends up making the panel feel sluggish.

Is there a way to define the model for just the child of a virtual page?
Happy to provide any other source code to help illustrate my problem.


class ProductsPage extends Page

    public function subpages()
        return Pages::factory($this->inventory()['children'], $this);
    public function children()
        $base_url = "";

        $results = [];
        $pages   = [];
        $request = Remote::get($base_url . "/admin/api/2020-04/products.json?limit=250&fields=id,title,product_type,published_at,template_suffix");

        if ($request->code() === 200) {
            $results = $request->json(false)->products;

        foreach ($results as $key => $product) {

            $slug = Str::slug($product->id);
            $page = $this->subpages()->find($slug);

            //dont do "advanced editing" on pages that don't have a dedicated template in Shopify
            $template = $product->template_suffix;
            if ($template == "" || !$template) continue;

            //dynamic content fields
            $conent = [];
            if ($page){
              foreach( $page->content()->fields() as $f ){
                $key = $f->key();
                $content[$key] = $page->$key()->value();

            $content["title"] = $product->title;

            $pages[] = [
                'slug'     => $slug,
                'template' => "product." . $template,
                'content'  => $content

        return Pages::factory($pages, $this);

Might be easier to use the shopify plugin…

But in answer to your question, you should be probably be caching the result from the API so your not constantly hitting it.

See here

The default cache life is 30 minutes, but you can use shopify webhooks to auto rebuild it when stuff changes on Shopify (like a product add or delete).

However, all that stuff is already in the plugin i mentioned.

1 Like

@jimbobrjames That plugin doesn’t quite do what I need it to, and caching will make for a delayed/laggy experience when the client is setting up a new product (they’ll have to wait for the cache to expire before seeing it in Kirby).

I feel like this is a brushing up against what seems like a feature request for Kirby, or hopefully just a documentation update.

Thats what the hooks i mentioned are for. You enable them in the shopify control panel, and create api end points in Kirby to recieve the hook. That way you can invalidate the cache when things happen in the shopify control panel, you dont have to wait for the cache to expire.