Embedding Module7 in WordPress
This guide covers the full setup for embedding Module7 in WordPress using the JS embed approach.
With the JS embed, Module7 content is rendered in the browser after the page loads. Search engine crawlers that do not execute JavaScript will not index the content.
If SEO is a requirement, a server-side adapter is needed instead.
1. Server Configuration
The web server must proxy /module7/* requests to the Module7 server and route deep-linked view URLs back to WordPress.
The production Module7 server address is https://mo7.vns.services.
Nginx
Add the following to your .conf file (e.g. m7proxy.conf):
map $scheme $fcgi_https { https on; default ''; }
# Route /listing and /listing/* to WordPress's index.php.
# Catches both plain /listing and path-based filter URLs like /listing/type=poi.
location ~ ^/listing {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param REQUEST_URI /listing;
fastcgi_param SERVER_NAME $host;
fastcgi_param HTTPS $fcgi_https;
fastcgi_read_timeout 60s;
}
# Route /detail/* to WordPress's index.php.
# WordPress issues canonical 301/302 redirects for unknown URLs — the
# @detail_serve fallback block re-serves the same FastCGI response
# as a 200 without following the redirect.
location ~ ^/detail/.+ {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param REQUEST_URI /detail/;
fastcgi_param SERVER_NAME $host;
fastcgi_param HTTPS $fcgi_https;
fastcgi_read_timeout 60s;
fastcgi_intercept_errors on;
error_page 301 302 =200 @detail_serve;
}
location @detail_serve {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param REQUEST_URI /detail/;
fastcgi_param SERVER_NAME $host;
fastcgi_param HTTPS $fcgi_https;
fastcgi_read_timeout 60s;
}
# Proxy /module7/* to the Module7 server
location ^~ /module7/ {
proxy_pass https://mo7.vns.services/module7/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Accept-Encoding "";
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Integration-Key" always;
}
Apache
Add the following to your .htaccess file at the root of your WordPress installation (the same folder as wp-config.php).
Your .htaccess already contains a # BEGIN WordPress / # END WordPress block managed by WordPress. Paste the Module7 block above that block — WordPress regenerates everything between those markers and will overwrite anything placed inside them.
### Begin: Module7 ###
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Route /detail/* to the WordPress /detail page
RewriteCond %{THE_REQUEST} \s/detail/[^\s]+
RewriteRule ^detail/.*$ index.php?pagename=detail [L]
# Route /listing and /listing?... to the WordPress /listing page
RewriteCond %{REQUEST_URI} ^/listing
RewriteRule ^listing index.php?pagename=listing [L]
</IfModule>
### End: Module7 ###
# BEGIN WordPress ← your existing block starts here, do not touch it
The reverse proxy rule cannot go into .htaccess — it must be added to your Apache virtual host configuration by your hosting provider or server administrator:
On shared hosting, contact your hosting provider and ask them to add a reverse proxy rule for /module7/ pointing to https://mo7.vns.services.
# Add inside your <VirtualHost> block (both *:80 and *:443)
ProxyPreserveHost On
ProxyPass /module7/ https://mo7.vns.services/module7/
ProxyPassReverse /module7/ https://mo7.vns.services/module7/
<Location /module7/>
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type, Integration-Key"
</Location>
2. Loading the loader script
The Module7 loader script must be injected into the <head> of your WordPress site. Use the Code Snippets plugin for maximum robustness and ease of management:
Recommended: Code Snippets Plugin (Header & Footer)
- Install and activate the Code Snippets plugin
- Go to Snippets → Add New in the WordPress admin
- Paste the following code:
<script src="https://mo7.vns.services/module7/loader.js"></script>
- Set the Location to Header & Footer (not PHP code)
- Check Active
- Save
This approach is robust and survives theme updates and WordPress upgrades.
Alternative: Add to theme's functions.php
If you prefer not to use a plugin, add this to your theme's functions.php:
add_action('wp_head', function () {
echo '<script src="https://mo7.vns.services/module7/loader.js"></script>';
});
This method is less robust — the code will be lost if the theme is updated or switched.
3. Required WordPress pages
For deep-linked URLs to work, you must create two pages in WordPress with the following exact slugs:
| Page | Slug | Purpose |
|---|---|---|
| Listing | /listing | Handles listing view URLs, e.g. /listing?city=Heidelberg&type=venus%3AHikingTrail |
| Detail | /detail | Handles detail view URLs, e.g. /detail/id=68480f7917d87aa853d49bea |
Without these pages, deep-linked URLs will return a 404. If you don't need deep-link support and always use the view attribute on <m7-view>, this step can be skipped.
To create the pages:
- Go to Pages → Add New in the WordPress admin
- Set the title (e.g. "Listing") and make sure the slug matches exactly (
/listing) - Add the
<m7-view>element to the page content (see next section) - Publish the page
- Repeat for
/detail
4. Placing <m7-view> on a page
Once the loader is active, add a <m7-view> element to any WordPress page where Module7 content should appear.
In the block editor (Gutenberg), use a Custom HTML block:
<m7-view
view="listing"
token="your-integration-key">
</m7-view>
Fallback for editors that sanitize HTML
Some WordPress configurations, themes, or page builders remove unknown HTML tags like <m7-view> when saving content. If you see an empty <div> in the saved output instead of your element, use the data-m7-view fallback on a plain <div>:
<div
data-m7-view
data-view="listing"
data-token="your-integration-key">
</div>
The loader automatically upgrades these <div> placeholders to proper <m7-view> elements. All attributes work identically with the data- prefix.
URL-driven usage (for /listing and /detail pages)
On the pages you created in step 3, omit the view attribute. Module7 resolves the view from the current URL automatically:
<m7-view token="your-integration-key"></m7-view>
This way a single element handles all listing states (/listing, /listing?city=Berlin, /listing?time=next_week) and all detail views (/detail/id=abc123) without any changes to the page.
5. Available attributes
For a full reference of all <m7-view> attributes including filter, project, channel, and mode, see the <m7-view> Attribute Reference.