> Portal Navigation: > > - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version. > - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages). > - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`). > - Top-level index of all portals: https://dev.wix.com/docs/llms.txt > - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt ## Resource: Creating Data Hooks for Dynamic Pages ## Article: Creating Data Hooks for Dynamic Pages ## Article Link: https://dev.wix.com/docs/develop-websites/articles/databases/wix-data/hooks/creating-data-hooks-for-dynamic-pages.md ## Article Content: # Velo: Creating Data Hooks for Dynamic Pages Creating a data binding router hook allows you to intercept the process of a dynamic page's data getting bound to the page. This article takes you through what code you have to write in order to make a data binding router work. To learn more about what a data binding router hook is and why you would want to create one, see [About Data Binding Router Hooks](https://dev.wix.com/docs/develop-websites/articles/databases/wix-data/hooks/about-data-hooks-for-dynamic-pages.md). ### Add a Data Binding Router Hook To add a data binding router hook: 1. Go to your dynamic page located in your site's pages. 2. Click the Show More icon ![](https://d2x3xhvgiqkx42.cloudfront.net/12345678-1234-1234-1234-1234567890ab/0ca9e8ba-16ed-4cd8-a1e1-58d01c4420f7/2020/10/25/30a7b8cf-6ad0-4562-8edb-40f5f54d27db/7c21e80f-9095-4668-90bf-14127f990bb9.png) and then click **Settings** to open the page's settings. 3. In the **Page Info** tab, scroll down to **Advanced Settings**, and click **Add Hooks** to display the Add Hooks panel. When adding a data binding router hook, function stubs for the data binding router hooks you chose are added to the **routers.js** file in your site's backend code. The data binding router hook functions are named with the following convention: _(params...) So if your dynamic page has the [prefix](https://dev.wix.com/docs/develop-websites/articles/databases/wix-data/dynamic-pages/making-dynamic-page-urls-meaningful-with-prefixes.md) **myPrefix**, the code added to the routers.js file for the **beforeRouter** hook should look like: myPrefix_beforeRouter(request) { // routing code ...} The hooks you can register are listed here in the order they run: * beforeRouter * customizeQuery * afterRouter To learn more about the hook functions, see the [Router API reference](http://wix.to/94BuAAs/wix-router.html). You can also register [data hooks](https://dev.wix.com/docs/develop-websites/articles/databases/wix-data/hooks/about-data-hooks.md) that run code before or after certain interactions with your site's collections. If you’ve done so, the data hooks will run between `customizeQuery()` and `afterRouter()`. ### beforeRouter( ) This hook is triggered before the router goes to the requested dynamic page. You can use this hook to route requests to a different page or return an error response. If you need the data that will be bound to the page to determine the correct response, use the `afterRouter()` hook instead. The `beforeRouter()` hook receives a [`WixRouterRequest`](http://wix.to/94BuAAs/wix-router.WixRouterRequest.html) object that contains information about the incoming request. The object has information about the URL used to reach the router, where the request came from, and who the request came from. Within the body of the hook you can write any code you want. The code you write there should help you determine how you want to respond to the request. The function needs to return a [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html) object that causes the router to continue its routing, or respond with an HTTP response code. If you want the router to continue to the same page it was originally going to with the same data, use the [`next()`](http://wix.to/94BuAAs/wix-router.html#next) function to return the appropriate [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html). However, if you want the router to do something other than it was originally going to do before reaching your hook, you can use the [`forbidden()`](http://wix.to/94BuAAs/wix-router.html#forbidden), [`notFound()`](http://wix.to/94BuAAs/wix-router.html#notFound), [`redirect()`](http://wix.to/94BuAAs/wix-router.html#redirect), or [`sendStatus()`](http://wix.to/94BuAAs/wix-router.html#sendStatus) functions to return a [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html). #### Example In this example we create a hook on the **dynamic** prefix that restricts certain requests from being routed to their intended target. The following code is placed in the **routers.js** file in your site's backend code. ```javascript import {forbidden, next} from 'wix-router'; export function dynamic_beforeRouter(request) { if (request.path.length > 1 && request.path[0] === "admin") { if (request.user && request.user.role == "siteOwner") return next(); else return forbidden(); } return next(); } ``` The functionality used to create data binding router hooks is contained in the [Router API](http://wix.to/94BuAAs/wix-router.html). To use some of this functionality, you need to import it.  Here we import the [`forbidden()`](http://wix.to/94BuAAs/wix-router.html#forbidden) and [`next()`](http://wix.to/94BuAAs/wix-router.html#next) functions. import {forbidden, next} from 'wix-router'; If you want to use more of the functionality from the Router API, you need to add it to the `import` statement. * * * In the hook function, we start by checking if the path begins with the string `"admin"`: if (request.path.length > 1 && request.path[0] === "admin") { // ... } If the path starts with anything other than "admin", the `if` is skipped and we tell the router to continue to where it was going before being intercepted by the hook: return next(); * * * However, if the path starts with `"admin"`, we check to see what type of user is making the request: if (request.user && request.user.role == "siteOwner") { // ... } If the user is the owner of the site, we once again tell the router to continue to where it was going before being intercepted by the hook: return next(); But if the user in not the owner of the site, we return a 403 response: return forbidden(); ### customizeQuery( ) This hook is triggered before the page's data query is executed. You can use this hook to further refine or change the query that will determine what data is bound to your page's dataset. The `customizeQuery()` hook receives a [`WixRouterRequest`](http://wix.to/94BuAAs/wix-router.WixRouterRequest.html) object that contains information about the incoming request, a string with the current route, and a [`WixDataQuery`](http://wix.to/94BuAAs/wix-data.WixDataQuery.html) object containing query which is going to be used to get the data for the page being routed to. Within the body of the hook you can write any code you want. The code you write there should help you determine if you want to continue with the initial data or if you want to change it in some way. The function needs to return a [`WixDataQuery`](http://wix.to/94BuAAs/wix-data.WixDataQuery.html) object that will be used to get the final data to be passed to the page that will be routed to. If you want the router to continue with the same data it was originally going to bind to the page, return the object that the function received in the `query` parameter. However, if you want the router use different data, you can either refine the current query using the functions of the [Data API](http://wix.to/94BuAAs/wix-data.html) or create a new query. #### Example In this example we create a hook on the **dynamic** prefix that filters the query for a certain route to only find active users. The following code is placed in the **routers.js** file in your site's backend code. ```javascript export function myRouter_customizeQuery(request, route, query) { if (route === "/users/{name}") return query.eq("status", "active"); else return query; } ``` The functionality used to create queries is contained in the [Data API](http://wix.to/94BuAAs/wix-data.html). To use some of this functionality, you need to import it.  * * * In the hook function, we start by checking if the route is going to a dynamic page that will be displaying users: if (route === "/users/{name}") // ... If it is going there, we refine the query to only get `"active"` users: return query.eq("status", "active"); Otherwise, we return the same query we received: return query; ### afterRouter( ) This hook is triggered after the router has bound the data, but before the page is displayed. You can use this hook to change the router's response based on the data that was retrieved.  The `afterRouter()` hook receives a [`WixRouterRequest`](http://wix.to/94BuAAs/wix-router.WixRouterRequest.html) object that contains information about the incoming request and a [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html) object containing information about the router's response. Within the body of the hook you can write any code you want. The code you write there should help you determine if you want to continue with the initial response or if you want to change it to another response. The function needs to return a [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html) object that causes the router to continue its routing, or respond with an HTTP response code. If you want the router to continue to the same page it was originally going to with the same data, return the object that the function received in the `response` parameter. However, if you want the router to do something other than it was originally going to do before reaching your hook, you can use the [`ok()`](http://wix.to/94BuAAs/wix-router.html#ok), [`forbidden()`](http://wix.to/94BuAAs/wix-router.html#forbidden), [`notFound()`](http://wix.to/94BuAAs/wix-router.html#notFound), [`redirect()`](http://wix.to/94BuAAs/wix-router.html#redirect), or [`sendStatus()`](http://wix.to/94BuAAs/wix-router.html#sendStatus) functions to return a [`WixRouterResponse`](http://wix.to/94BuAAs/wix-router.WixRouterResponse.html). To use the data from the router on a page that is different than the one the router was originally going to route to, you can use the \[`ok()`\] function to choose the page and pass it the `response.data` and `response.header` from the original response. For an example of this use case, see below. #### Example In this example we create a hook on the **dynamic** prefix that routes the user to one of two pages. We have two versions of a page, one for horizontal oriented images and another for vertical oriented ones. After the image is pulled from the database, we check which type of picture is to be shown and route to the page that corresponds to that image's orientation. The following code is placed in the **routers.js** file in your site's backend code. ```javascript import {ok} from 'wix-router'; export function myRouter_afterRouter(request, response) { if(response.status === 200 && response.page === "horizontal-pic") { if(response.data.picture.orientation === "vertical") return ok("vertical-pic", response.data, response.head); else return response; } return response; } ``` The functionality used to create data binding router hooks is contained in the [Router API](http://wix.to/94BuAAs/wix-router.html). To use some of this functionality, you need to import it.  Here we import the [`ok()`](http://wix.to/94BuAAs/wix-router.html#ok) function. import {ok} from 'wix-router'; If you want to use more of the functionality from the Router API, you need to add it to the `import` statement. * * * In the hook function, we start by checking if the response `status` is the okay status and if the page the response is routing to is the page that displays pictures with a horizontal orientation: if(response.status === 200 && response.page === "horizontal-pic") { // ... } If we find any other status or if the page we're responding with is not the one we have two versions of, we just return the original response: return response; * * * However, if the router is about to route to the page that displays horizontal images, we check the orientation of the image that will be displayed on the page. We do so by pulling the orientation information from the router's current response: if(response.data.picture.orientation === "vertical") // ... If the picture's orientation doesn't match the page it was being sent to, we route to a different page that does match its orientation and we take the `data` and `head` information from the original response and send it to the new page as well: return ok("vertical-pic", response.data, response.head); But if the picture's orientation already matches the page it was being sent to, we send it to where it was already going. return response;