Introduction

PSE - Listings

Default embeded code to use the new PSE:

<script src="https://sdk.sharplaunch.com/sharplaunch_SDK.js"></script>
<div id="PSE"></div>
<script>
  SharpLaunch.PSE.create('CLIENT_API_KEY', {
    el: '#PSE',
    config: {
      // Runtime configuration options (see below)
    }
  });
</script>

Configuration options

Optimally, when rendering the main PSE this shouldn't be used. The most important parameters are set via the PSE Settings page. Keep in mind that any runtime option (e.g. filters:) defined within the embed code will override (and not merge) the config value.

Config values available:

{
    // `base_url` is the root URL path for the app, set it to /properties/ or other in case the PSE is served from a directory/permalink.
    "base_url": "/",
    // `router` - see options below at "Navigation"
    "router": "default", 
    "navigation_mode": "direct", // direct|iframe|disabled
    // `colors` define client's accent color
    "colors": {
        "accent": "#3b86f2",
        "text_on_accent": "white" // Computed automatically based on `colors.accent` if not defined
    },
    // `views` define the display modes
    "views": [
        "sidebar", // split view: map with a list on the left/right side
        "list", // list view
        "map" // fullscreen map
    ],
    // `status` define which properties to include in the PSE by their status. Not related to status filtering within the filter bar.
    "status": ["active", "closed", "escrow"],
    // `status_toggle` creates a toggle button to switch between the statuses. Some considerations:
        // - The status filter needs to be enabled in the filter bar for this to work
        // - The status filter needs to be an array value '[]', not a string value '""'
    "status_toggle": [
        {
            "label": "Active",
            "value": ['active']
        },
        {
            "label": "Closed",
            "value": ['closed']
        }
    ],
    // `type` define which properties to include in the PSE by their type. Not related to type filtering within the filter bar.
    "type": [
        "retail",
        "special",
        "industrial",
        "medical",
        "other",
        "multifamily",
        "flex",
        "hospitality",
        "land",
        "mixed",
        "office",
        "farmranch"
    ],
    // `map_sidebar_position` define sidebar position on a `sidebar` view
    "map_sidebar_position": "left", // left | right
    // `map_tooltip_on_hover` display a small tooltip window when hovering over a map marker
    "map_tooltip_on_hover": false, // Boolean
    // `map_marker_style` @TODO: implement
    "map_marker_style": "default",
    // `map_marker_color`
    "map_marker_color": "#f50",
    /**
     *  `filters` Array of filters to display within the filter bar,
     *   see examples below.
     *
     *      - `name` id|slug of the filter
     *          For the Team/Brokers filter the value must be `team`
     *      - `label` displayed above the input field
     *         (if `filters.filters_show_labels == true`)
     *      - `placeholder` placeholder for the input field
     *      - `type` text | select | multiselect
     *      - `fields` it's an Array, although it only works with
     *        multiple values within the `type`: `text` search
     *      - `default` must match the value type on the website object:
     *          e.g. if property.type = [] 👉️ filters.$.default = []
     *          e.g. if property.state = "" 👉️ filters.$.default = ""
     *
     **/
    "filters": [
        {
            "name": "keyword",
            "label": "Keyword",
            "placeholder": "Keywords search ...",
            "type": "text",
            "fields": [
                "name",
                "state",
                "state_long",
                "city",
                "address",
                "description"
            ],
            "default": ""
        },
        {
            "name": "type",
            "label": "Type",
            "type": "select",
            "placeholder": "Any type",
            "fields": ["type"],
            "default": []
        },
        {
            "name": "location",
            "label": "Location",
            "placeholder": "Any state",
            "type": "select",
            "fields": ["state_long"],
            "default": ""
        },
        {
            "name": "status",
            "label": "Status",
            "placeholder": "Any status",
            "type": "select",
            "fields": ["status"],
            "default": ""
        },
        {
            "name": "transaction",
            "label": "Transaction",
            "placeholder": "Any Transaction",
            "type": "select",
            "fields": ["transaction"],
            "subfield": null,
            "default": ""
        },
        {
            "name": "team",
            "label": "Broker",
            "placeholder": "Any Broker",
            "type": "select",
            "fields": ["team"],
            "subfield": "name",
            "default": []
        },
        {
            "name": "price",
            "default": "",
            "options": [
                {
                    "value": "0-250000",
                    "label": "0 - $250,000"
                },
                {
                    "value": "250000-500000",
                    "label": "$250,000 - $500,000"
                },
                {
                    "value": "500000-1000000",
                    "label": "$500,000 - $1,000,000"
                },
                {
                    "value": "1000000-5000000",
                    "label": "$1,000,000 - $5,000,000"
                },
                {
                    "value": "5000000-10000000",
                    "label": "$5,000,000 - $10,000,000"
                },
                {
                    "value": "10000000-50000000",
                    "label": "$10,000,000 - $50,000,000"
                },
                {
                    "value": "50000000",
                    "label": "$50,000,000+"
                }
            ],
            "label": "Price",
            "placeholder": "Price",
            "type": "range_select",
            "fields": [
                "availabilities_min_rent",
                "availabilities_max_rent",
                "sale_price"
            ]
        },
        {
            "default": "",
            "name": "surface",
            "options": [
                {
                    "value": "0-2500",
                    "label": "0 - 2,500 SF"
                },
                {
                    "value": "2500-5000",
                    "label": "2,500 - 5,000 SF"
                },
                {
                    "value": "5000-10000",
                    "label": "5,000 - 10,000 SF"
                },
                {
                    "value": "10000-20000",
                    "label": "10,000 - 20,000 SF"
                },
                {
                    "value": "20000-50000",
                    "label": "20,000 - 50,000 SF"
                },
                {
                    "value": "50000-9999999",
                    "label": "50,000+ SF"
                }
            ],
            "label": "Surface (sqft)",
            "placeholder": "Any size",
            "type": "range_select",
            "fields": [
                "availabilities_min_surface_sqft",
                "availabilities_max_surface_sqft",
                "total_surface_sqft"
            ]
        }
    ],
    // `labels` label mapping for filters, see examples below
    "labels": {
        "type": {
            "special": "Special",
            "industrial": "Industrial",
            "medical": "Medical",
            "other": "Other",
            "multifamily": "Multifamily",
            "flex": "Flex",
            "hospitality": "Hospitality",
            "land": "Land",
            "mixed": "Mixed-use",
            "office": "Office",
            "retail": "Retail",
            "farmranch": "Farm & Ranch"
        },
        "status": {
            "active": "Active",
            "closed": "Closed",
            "escrow": "Escrow"
        }
    },
    // `filters_show_labels` show `filter.label` as a <label> above the filter input field
    "filters_show_labels": false, // Boolean
    // `filters_show_reset` although it shows only when there's an active filter you can disable it completely here
    "filters_show_reset": true, // Boolean
    // `list_heading` display a default heading on the `views.list` view
    "list_heading": true,
    // `list_layout` spacios | compact
    "list_layout": "spacious",
    "sort_by": "name",
    "sort_order": "desc",
    // `google_maps_key` provide custom Google Maps API key for the PSE
    "google_maps_key": null,
    /**
     * `google_maps_style` Array of styles,
     * see interface format at
     * https://developers.google.com/maps/documentation/javascript/reference#MapTypeStyle
     **/
    "google_maps_style": [
        {
            "featureType": "water",
            "elementType": "geometry",
            "stylers": [
                {
                    "color": "#e9e9e9"
                },
                {
                    "lightness": 17
                }
            ]
        }
    ],
    // `tile_datapoints` - overrides the default set of datapoints listed within the property tiles below the property title.
    "tile_datapoints": [
      {
        "name": "units",  // not in use atm, but same as field
        "field": "units", // datapoint name (key name from property JSON object, e.g.: sale_price|total_surface|units|yearbuiltstatus|...etc)
        "label": "Units", // Label for the datapoint in the tile
        "formatter": "number", // number|currency formatter method for the value, omit key if no need for a formatter
        "enabled": true // hide/show from tile
      }
    ],
    // `templates` (EXPERIMENTAL), will provide room for more detailed customizations through custom Vue <template>
    "templates": {
        "list_item": "<div style='color:blue;border:2px solid black;padding:20px'><div class='sl-font-bold'>{{property.name}} | {{property.city}}</div>{{property.description}}</div>"
    }
}

Controls how property links behave when a user clicks on a listing.

OptionDescription
directNavigates directly to the property page. Uses listings_route pattern if configured, otherwise loads the raw property URL. Best for: Standalones (Astro) or WP Plugin. Slug variable for listings_route is :slug
iframeUses Vue Router within the SPA. Property page renders inside the PSE module and displayed inside an iframe. Best for: Embedded sites. Slug variable for listings_route is :property_slug
disabledDisables all property links. Clicking does nothing. Best for: Display-only listings.

Default: If not set, it will send the user to the property page directly. That's SharpLaunch URL or external property URL if present.


history_mode

Only relevant when navigation_mode is iframe.

Controls Vue Router's history mode for SPA navigation.

OptionDescription
hashUses hash-based URLs (e.g., example.com/#/property-slug). Works without server config. Best for: Most embedded scenarios.
html5Uses clean URLs (e.g., example.com/property-slug). Requires server-side URL rewriting. Best for: When you control the server (Standalones and WP).

Default: "hash"

Reference: Vue Router History Modeopen in new window


router

Alternative routing mode that uses query parameters instead of path-based routing.

FormatDescription
querystringUses query parameter for navigation (default param: listing). URL: example.com?listing=property-slug

Default: Not set (uses standard path-based routing)


Default settings

This mode uses hash to navigate across pages and to track the listings page filters

{
  base: "/",
  history_mode: "hash",
  listings_route: "/listings/:property_slug",
  navigation_mode: "direct", // or "direct"
  router: "default"
}

HTML5 settings

In this mode you can host your PSE at URL https://yoursite.com/yoursubpage/ and generate https://yoursite.com/yoursubpage/listings/property-1. This is more SEO-friendly.

Just so you know, this config also needs server-side redirect settings to be configured.

{
  base: "/yoursubpage",
  history_mode: "html5",
  listings_route: "/listings/:property_slug",
  navigation_mode: "iframe", // or "direct"
  router: "default"
}

QueryString settings NEW!

UPDATE - 2024-05-14 Preferred mode, this will be the default in the next version

With this config, querystring takes over the routing to generate SEO-friendly URLs without additional server-side configuration.

This results in URLs like https://yoursite.com/listings/?listing=property-1

{
  base: "/",
  history_mode: "html5",
  navigation_mode: "iframe", // or "direct"
  router: "querystring"
}

PSE - Single site

Default call to get the data from the building site:

export async function getStaticPaths() {
    const res = await fetch(
        "https://pse-api.sharplaunch.com/data?entity=website",
        {
            headers: {
                "X-Api-Key": "CLIENT_API_KEY",
            },
        }
    ).then((res) => res.json());

    return res.items.map((item) => {
        item.id = item.username.toString(); // make sure the id is a string
        return {
            params: { id: item.username },
            props: { item },
        };
    });
}

Basic iframe to show the building website from the CMS:

<iframe
    src="{item.url}"
    style="width: 100%; height: 100%;"
    frameborder="0"
></iframe>

This call will return all the sites from your CMS, you just need to find the one you are interested to show and display the CMS website in the iframe using the URL inside the item.

Widget

Default embedded code to use the widget for featured properties from the CMS

    <script src="https://sdk.sharplaunch.com/sharplaunch_SDK.js"></script>
    <div id="featuredWidget"></div>
    <script>
        SharpLaunch.featuredWidget.create('CLIENT_API_KEY', {
            el: '#featuredWidget'
        })
    </script>
Last Updated:
Contributors: Carlos Jimenez Fabrgat, gabor-sl, Stefan Olaru