Calling a JSON file from a page in HTML code.

Glamerstone
Tourist
9 2 2

Hi! I'm trying to include to my online store a store locator without using plugins, I'm using Google Maps Platform. I develop my map in a text editor and it works fine. But when I tried to embed to shopify there are lots of problems.

This is how it should it looks.

Glamerstone_0-1623868494192.png

 

And this is how it looks when I embed to shopify.

Glamerstone_1-1623868640021.png

The CSS don't fit in the page. And the markers come from a json file. So I need an advise of how to integrate that in my shopify store.

I'm going to add my map code.

 

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map By Glamerstone</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <link rel="stylesheet" type="text/css" href="index.css" />
    <script src="app.js"></script>
  </head>
  <body>
    <!-- The div to hold the map -->
    <div id="map"></div>

    <script src="app.js"></script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDlMk8xN7Z-Cq1aBdPVrp5A7Vy7chXw0DY&libraries=places&callback=initMap">
    </script>
  </body>
</html>

 

 This is the .js

 

function initMap() {
  // Create the map.
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 6,
    center: { lat: 23.81069, lng: -102.25753 },
  });

  // Load the stores GeoJSON onto the map.
  map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});
  
 // Define the custom marker icons, using the store's "category".
  map.data.setStyle((feature) => {
    return {
      icon: {
        url: 'https://cdn.shopify.com/s/files/1/0257/8605/6753/files/Pin_1.png?v=1613646379',
        scaledSize: new google.maps.Size(64, 64),
      },
    };
  });

  const apiKey = 'AIzaSyDlMk8xN7Z-Cq1aBdPVrp5A7Vy7chXw0DY'
  const infoWindow = new google.maps.InfoWindow();

  // Show the information for a store when its marker is clicked.
  map.data.addListener('click', (event) => {
    const category = event.feature.getProperty('category');
    const name = event.feature.getProperty('name');
    const description = event.feature.getProperty('description');
    const hours = event.feature.getProperty('hours');
    const phone = event.feature.getProperty('phone');
    const position = event.feature.getGeometry().get();
    const content = `
      <h2>${name}</h2><p>${description}</p>
      <p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
    `;

    infoWindow.setContent(content);
    infoWindow.setPosition(position);
    infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
    infoWindow.open(map);
  });
  // Build and add the search bar
  const card = document.createElement('div');
  const titleBar = document.createElement('div');
  const title = document.createElement('div');
  const container = document.createElement('div');
  const input = document.createElement('input');
  const options = {
    types: ['address'],
    componentRestrictions: {country: 'mx'},
  };

  card.setAttribute('id', 'pac-card');
  title.setAttribute('id', 'title');
  title.textContent = 'Find the nearest store';
  titleBar.appendChild(title);
  container.setAttribute('id', 'pac-container');
  input.setAttribute('id', 'pac-input');
  input.setAttribute('type', 'text');
  input.setAttribute('placeholder', 'Enter an address');
  container.appendChild(input);
  card.appendChild(titleBar);
  card.appendChild(container);
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

  // Make the search bar into a Places Autocomplete search bar and select
  // which detail fields should be returned about the place that
  // the user selects from the suggestions.
  const autocomplete = new google.maps.places.Autocomplete(input, options);

  autocomplete.setFields(
      ['address_components', 'geometry', 'name']);
      // Set the origin point when the user selects an address
  const originMarker = new google.maps.Marker({map: map});
  originMarker.setVisible(false);
  let originLocation = map.getCenter();

  autocomplete.addListener('place_changed', async () => {
    originMarker.setVisible(false);
    originLocation = map.getCenter();
    const place = autocomplete.getPlace();

    if (!place.geometry) {
      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      window.alert('No address available for input: \'' + place.name + '\'');
      return;
    }

    // Recenter the map to the selected address
    originLocation = place.geometry.location;
    map.setCenter(originLocation);
    map.setZoom(9);
    console.log(place);

    originMarker.setPosition(originLocation);
    originMarker.setVisible(true);

    // Use the selected address as the origin to calculate distances
    // to each of the store locations
    const rankedStores = await calculateDistances(map.data, originLocation);
    showStoresList(map.data, rankedStores);

    return;
  });

}
//center: { lat: 23.81069, lng: -102.25753 },
//const apiKey = 'AIzaSyDlMk8xN7Z-Cq1aBdPVrp5A7Vy7chXw0DY';

async function calculateDistances(data, origin) {
  const stores = [];
  const destinations = [];

  // Build parallel arrays for the store IDs and destinations
  data.forEach((store) => {
    const storeNum = store.getProperty('storeid');
    const storeLoc = store.getGeometry().get();

    stores.push(storeNum);
    destinations.push(storeLoc);
  });

  // Retrieve the distances of each store from the origin
  // The returned list will be in the same order as the destinations list
  const service = new google.maps.DistanceMatrixService();
  const getDistanceMatrix =
    (service, parameters) => new Promise((resolve, reject) => {
      service.getDistanceMatrix(parameters, (response, status) => {
        if (status != google.maps.DistanceMatrixStatus.OK) {
          reject(response);
        } else {
          const distances = [];
          const results = response.rows[0].elements;
          for (let j = 0; j < results.length; j++) {
            const element = results[j];
            const distanceText = element.distance.text;
            const distanceVal = element.distance.value;
            const distanceObject = {
              storeid: stores[j],
              distanceText: distanceText,
              distanceVal: distanceVal,
            };
            distances.push(distanceObject);
          }

          resolve(distances);
        }
      });
    });

  const distancesList = await getDistanceMatrix(service, {
    origins: [origin],
    destinations: destinations,
    travelMode: 'DRIVING',
    unitSystem: google.maps.UnitSystem.METRIC,
  });

  distancesList.sort((first, second) => {
    return first.distanceVal - second.distanceVal;
  });

  return distancesList;
}

function showStoresList(data, stores) {
  if (stores.length == 0) {
    console.log('empty stores');
    return;
  }

  let panel = document.createElement('div');
  // If the panel already exists, use it. Else, create it and add to the page.
  if (document.getElementById('panel')) {
    panel = document.getElementById('panel');
    // If panel is already open, close it
    if (panel.classList.contains('open')) {
      panel.classList.remove('open');
    }
  } else {
    panel.setAttribute('id', 'panel');
    const body = document.body;
    body.insertBefore(panel, body.childNodes[0]);
  }


  // Clear the previous details
  while (panel.lastChild) {
    panel.removeChild(panel.lastChild);
  }

  stores.forEach((store) => {
    // Add store details with text formatting
    const name = document.createElement('p');
    name.classList.add('place');
    const currentStore = data.getFeatureById(store.storeid);
    name.textContent = currentStore.getProperty('name');
    panel.appendChild(name);
    const distanceText = document.createElement('p');
    distanceText.classList.add('distanceText');
    distanceText.textContent = store.distanceText;
    panel.appendChild(distanceText);
  });

  // Open the panel
  panel.classList.add('open');

  return;
}

 

 This is the CSS.

 

#map {
    height: 100%;
  }

  html,
  body {
    height: 100%;
    margin: 0;
    padding: 0;
  }

  /* Styling for Autocomplete search bar */
  #pac-card {
    background-color: #fff;
    border-radius: 2px 0 0 2px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    box-sizing: border-box;
    font-family: Roboto;
    margin: 10px 10px 0 0;
    -moz-box-sizing: border-box;
    outline: none;
  }

  #pac-container {
    padding-top: 12px;
    padding-bottom: 12px;
    margin-right: 12px;
  }

  #pac-input {
    background-color: #fff;
    font-family: Roboto;
    font-size: 15px;
    font-weight: 300;
    margin-left: 12px;
    padding: 0 11px 0 13px;
    text-overflow: ellipsis;
    width: 400px;
  }

  #pac-input:focus {
    border-color: #4d90fe;
  }

  #title {
    color: #fff;
    background-color: #acbcc9;
    font-size: 18px;
    font-weight: 400;
    padding: 6px 12px;
  }

  .hidden {
    display: none;
  }

  /* Styling for an info pane that slides out from the left.
   * Hidden by default. */
  #panel {
    height: 100%;
    width: null;
    background-color: white;
    position: fixed;
    z-index: 1;
    overflow-x: hidden;
    transition: all .2s ease-out;
  }

  .open {
    width: 250px;
  }

  .place {
    font-family: 'open sans', arial, sans-serif;
    font-size: 1.2em;
    font-weight: 500;
    margin-block-end: 0px;
    padding-left: 18px;
    padding-right: 18px;
  }

  .distanceText {
    color: silver;
    font-family: 'open sans', arial, sans-serif;
    font-size: 1em;
    font-weight: 400;
    margin-block-start: 0.25em;
    padding-left: 18px;
    padding-right: 18px;
  }

 

 

 

In the .json file it include some example locations.

 

 

Thank you for any help you can provide.

0 Likes
KieranR
Shopify Partner
295 24 87

How have you embedded into your Shopify theme? Is the JS loading in the correct order? Are there errors in the console? Time to debug.

Full time Shopify SEO guy, based in NZ. Sometimes freelance outside the 9-5.
0 Likes
Glamerstone
Tourist
9 2 2

@KieranR 

Hi! I embedded adding the html code in the page section of "Sucursales", the CSS in my theme.css, I created an asset to save my stores information in .js following the google maps api requirements. 

This is the .json file that I have save it also in a .js file to call it in the html.

{
    "type": "FeatureCollection",
    "features": [{
            "geometry": {
                "type": "Point",
                "coordinates": [-103.3749947,
                    20.6541455
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Modern twists on classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Lázaro Cárdenas",
                "phone": "+523332683060",
                "storeid": "01"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-99.22633600859834, 
                    19.496363220462822
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and try our award-winning cakes and pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Echegaray",
                "phone": "+525553600350",
                "storeid": "02"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-103.36026327976226,
                    20.64898581643781
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Whatever the occasion, whether it's a birthday or a wedding, Josie's Patisserie has the perfect treat for you. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS 8 de Julio",
                "phone": "+523338101672",
                "storeid": "03"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [ -99.25536303558198,
                    19.380976884088653
                   
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "A gourmet patisserie that will delight your senses. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Cuajimalpa",
                "phone": "+525555132908",
                "storeid": "04"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-99.1885262932541,
                    19.405954077156586
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Spoil yourself or someone special with our classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Parque Lira",
                "phone": "+525555162059",
                "storeid": "05"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-99.17360166441803,
                    19.356580063243477
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and feast your eyes and tastebuds on our delicious pastries and cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Universidad",
                "phone": "+525591551579",
                "storeid": "06"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-98.28087673558198,
                    19.106332930251146
                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Josie's Patisserie is family-owned, and our delectable pastries, cakes, and great coffee are renowed. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Periférico Puebla",
                "phone": "+522227684553",
                "storeid": "07"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-98.22134503558196,
                    19.027991649561624
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Oakham's favorite spot for fresh coffee and delicious cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Juan Pablo II",
                "phone": "+522221366796",
                "storeid": "08"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-93.13830046441802,
                    16.74995028939294
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Enjoy freshly brewed coffe, and home baked cakes in our homely cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Periférico Sur",
                "phone": "+529611214918",
                "storeid": "09"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-93.08987053558197,
                    16.74896272631542                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "A delicious array of pastries with many flavours, and fresh coffee in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Matriz Palmas",
                "phone": "+529616141448",
                "storeid": "10"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-93.12449263558197,
                    16.759855036897424                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Grab a freshly brewed coffee, a decadent cake and relax in our idyllic cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS 5ta Norte",
                "phone": "+529616121918",
                "storeid": "11"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-92.65532613558196,
                    16.731815321629476                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Come in and unwind at this idyllic cafe with fresh coffee and home made cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS San Cristóbal",
                "phone": "+529676783107",
                "storeid": "12"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -93.27456436441803,
                    16.228104842458396                    
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Fresh coffee and delicious cakes in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "RADIAL LLANTAS Villaflores",
                "phone": "+529656521000",
                "storeid": "13"
            }
        }
    ]
}
0 Likes
KieranR
Shopify Partner
295 24 87

So code looks roughly fine, I'm not gonna go through and debug it line by line from a birds-eye view. Much better doing this live.

In my exp though it's really how it's all pulled in together on the live site. Few things I'd try: fire up F12 and look at console log for any tips or JS loading issues, make sure the JS file is actually running, throw in some JS console.log output or use breakpoints to see what parts are being reached as expected.

Full time Shopify SEO guy, based in NZ. Sometimes freelance outside the 9-5.
0 Likes